|
1
|
|
|
# Copyright (C) 2019 NRL |
|
2
|
|
|
# Author: Angeline Burrell |
|
3
|
|
|
# Disclaimer: This code is under the MIT license, whose details can be found at |
|
4
|
|
|
# the root in the LICENSE file |
|
5
|
|
|
# |
|
6
|
|
|
# -*- coding: utf-8 -*- |
|
7
|
|
|
"""Executed when aacgmv2 is invoked with python -m aacgmv2""" |
|
8
|
|
|
|
|
9
|
|
|
|
|
10
|
|
|
import argparse |
|
11
|
|
|
import datetime as dt |
|
12
|
|
|
import numpy as np |
|
13
|
|
|
import sys |
|
14
|
|
|
|
|
15
|
|
|
import aacgmv2 |
|
16
|
|
|
|
|
17
|
|
|
|
|
18
|
|
|
def main(): |
|
19
|
|
|
"""Entry point for the script""" |
|
20
|
|
|
|
|
21
|
|
|
desc = 'Converts between geographical coordinates, AACGM-v2, and MLT' |
|
22
|
|
|
parser = argparse.ArgumentParser(description=desc) |
|
23
|
|
|
|
|
24
|
|
|
desc = 'for help, run %(prog)s SUBCOMMAND -h' |
|
25
|
|
|
subparsers = parser.add_subparsers(title='Subcommands', prog='aacgmv2', |
|
26
|
|
|
dest='subcommand', description=desc) |
|
27
|
|
|
subparsers.required = True |
|
28
|
|
|
|
|
29
|
|
|
desc = 'convert to/from geomagnetic coordinates. Input file must have lines' |
|
30
|
|
|
desc += 'of the form "LAT LON ALT".' |
|
31
|
|
|
parser_convert = subparsers.add_parser('convert', help=(desc)) |
|
32
|
|
|
|
|
33
|
|
|
desc = 'convert between magnetic local time (MLT) and AACGM-v2 longitude. ' |
|
34
|
|
|
desc += 'Input file must have a single number on each line.' |
|
35
|
|
|
parser_convert_mlt = subparsers.add_parser('convert_mlt', help=(desc)) |
|
36
|
|
|
|
|
37
|
|
|
desc = 'input file (stdin if none specified)' |
|
38
|
|
|
for pp in [parser_convert, parser_convert_mlt]: |
|
39
|
|
|
pp.add_argument('-i', '--input', dest='file_in', metavar='FILE_IN', |
|
40
|
|
|
type=argparse.FileType('r'), default=sys.stdin.buffer, |
|
41
|
|
|
help=desc) |
|
42
|
|
|
pp.add_argument('-o', '--output', dest='file_out', metavar='FILE_OUT', |
|
43
|
|
|
type=argparse.FileType('w'), default=sys.stdout.buffer, |
|
44
|
|
|
help='output file (stdout if none specified)') |
|
45
|
|
|
|
|
46
|
|
|
desc = 'date for magnetic field model (1900-2020, default: today)' |
|
47
|
|
|
parser_convert.add_argument('-d', '--date', dest='date', metavar='YYYYMMDD', |
|
48
|
|
|
help=desc) |
|
49
|
|
|
|
|
50
|
|
|
desc = 'invert - convert AACGM to geographic instead of geographic to AACGM' |
|
51
|
|
|
parser_convert.add_argument('-v', '--a2g', dest='a2g', action='store_true', |
|
52
|
|
|
default=False, help=desc) |
|
53
|
|
|
|
|
54
|
|
|
desc = 'use field-line tracing instead of coefficients' |
|
55
|
|
|
parser_convert.add_argument('-t', '--trace', dest='trace', |
|
56
|
|
|
action='store_true', default=False, help=desc) |
|
57
|
|
|
|
|
58
|
|
|
desc = 'automatically use field-line tracing above 2000 km' |
|
59
|
|
|
parser_convert.add_argument('-a', '--allowtrace', dest='allowtrace', |
|
60
|
|
|
action='store_true', default=False, help=desc) |
|
61
|
|
|
|
|
62
|
|
|
desc = 'allow use of coefficients above 2000 km (bad idea!)' |
|
63
|
|
|
parser_convert.add_argument('-b', '--badidea', dest='badidea', |
|
64
|
|
|
action='store_true', default=False, help=desc) |
|
65
|
|
|
|
|
66
|
|
|
desc = 'assume inputs are geocentric with Earth radius 6371.2 km' |
|
67
|
|
|
parser_convert.add_argument('-g', '--geocentric', dest='geocentric', |
|
68
|
|
|
action='store_true', default=False, help=desc) |
|
69
|
|
|
|
|
70
|
|
|
parser_convert_mlt.add_argument('datetime', metavar='YYYYMMDDHHMMSS', |
|
71
|
|
|
help='date and time for conversion') |
|
72
|
|
|
|
|
73
|
|
|
desc = 'invert - convert MLT to AACGM longitude instead of AACGM longitude' |
|
74
|
|
|
desc += ' to MLT' |
|
75
|
|
|
parser_convert_mlt.add_argument('-v', '--m2a', dest='m2a', |
|
76
|
|
|
action='store_true', default=False, |
|
77
|
|
|
help=desc) |
|
78
|
|
|
|
|
79
|
|
|
args = parser.parse_args() |
|
80
|
|
|
array = np.loadtxt(args.file_in, ndmin=2) |
|
81
|
|
|
|
|
82
|
|
|
if args.subcommand == 'convert': |
|
83
|
|
|
if args.date is None: |
|
84
|
|
|
date = dt.date.today() |
|
85
|
|
|
else: |
|
86
|
|
|
date = dt.datetime.strptime(args.date, '%Y%m%d') |
|
87
|
|
|
|
|
88
|
|
|
code = aacgmv2.convert_bool_to_bit(a2g=args.a2g, trace=args.trace, |
|
89
|
|
|
allowtrace=args.allowtrace, |
|
90
|
|
|
badidea=args.badidea, |
|
91
|
|
|
geocentric=args.geocentric) |
|
92
|
|
|
lats, lons, alts = aacgmv2.convert_latlon_arr(array[:, 0], array[:, 1], |
|
93
|
|
|
array[:, 2], dtime=date, |
|
94
|
|
|
method_code=code) |
|
95
|
|
|
|
|
96
|
|
|
np.savetxt(args.file_out, np.column_stack((lats, lons, alts)), |
|
97
|
|
|
fmt='%.8f') |
|
98
|
|
|
elif args.subcommand == 'convert_mlt': |
|
99
|
|
|
dtime = dt.datetime.strptime(args.datetime, '%Y%m%d%H%M%S') |
|
100
|
|
|
out = np.array(aacgmv2.convert_mlt(array[:, 0], dtime, m2a=args.m2a)) |
|
101
|
|
|
|
|
102
|
|
|
if len(out.shape) == 0: |
|
103
|
|
|
out = np.array([out]) |
|
104
|
|
|
|
|
105
|
|
|
np.savetxt(args.file_out, out, fmt='%.8f') |
|
106
|
|
|
|
|
107
|
|
|
# If not a pipe to STDOUT or STDERR, ensure the file is closed |
|
108
|
|
|
not_pipe = ((args.file_out.name.find('stdout') < 0) |
|
109
|
|
|
& (args.file_out.name.find('stderr') < 0)) |
|
110
|
|
|
if not_pipe: |
|
111
|
|
|
args.file_out.close() |
|
112
|
|
|
|
|
113
|
|
|
|
|
114
|
|
|
if __name__ == '__main__': |
|
115
|
|
|
sys.exit(main()) |
|
116
|
|
|
|