OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
spacetrack_tles.py
Go to the documentation of this file.
1 #! /usr/bin/env python3
2 # Retrieve TLE files from the https://www.space-track.org website
3 
4 import argparse
5 import os
6 import shutil
7 import logging
8 import requests
9 import sys
10 import json
11 
12 __version__ = "2.0-20200212"
13 
14 norad = {
15  'TERRA': 25994,
16  'AQUA': 27424,
17  'CALIPSO': 29108,
18  'CLOUDSAT': 29107,
19  'PROBA': 26958,
20  'NPP': 37849,
21  'JPSS1': 43013,
22  'LANDSAT-8': 39084,
23  'SEAHAWK-1': 43820,
24  'SENTINEL-2A': 40697,
25  'SENTINEL-2B': 42063,
26  'SENTINEL-3A': 41335,
27  'SENTINEL-3B': 43437,
28  'OCEANSAT-2': 35931,
29  'GCOM-C': 43065
30 }
31 
32 
33 parser = argparse.ArgumentParser(prog='spacetrack_tles',
34  description='This script retrieves Two-Line Elements from www.space-track.org for a given satellite name or NORAD catalog ID')
35 parser.add_argument('--version', action='version', version='%(prog)s ' + __version__)
36 parser.add_argument('satellite',nargs='?', help='Satellite TLE to retrieve. "ALL" will return TLEs for all in the list above.', type=str,
37  choices=['TERRA',
38  'AQUA',
39  'CALIPSO',
40  'CLOUDSAT',
41  'PROBA',
42  'NPP',
43  'JPSS1',
44  'LANDSAT-8',
45  'SEAHAWK-1',
46  'SENTINEL-2A',
47  'SENTINEL-2B',
48  'SENTINEL-2B',
49  'SENTINEL-3A',
50  'SENTINEL-3B',
51  'OCEANSAT-2',
52  'GCOM-C',
53  'ALL'])
54 parser.add_argument('--ofile','-o', type=str, default=None, help="Name of file to store retreived TLE")
55 parser.add_argument('--catID', '-c', type=int, default=None, help='NORAD Catalog ID of satellite to retrieve; ingored if a satellite name is provided.')
56 parser.add_argument('--username', '-u', type=str, default=None, help="Space-track.org username")
57 parser.add_argument('--password', '-p', type=str, default=None, help="Space-track.org password")
58 parser.add_argument('--copyTCE', default=False, action='store_true', help="Copy TLE to latest '<satellite>.tce' file")
59 parser.add_argument('--directory','-d', type=str, default=os.getcwd(), help="Direcotry to write TLEs; default is the current working directory")
60 parser.add_argument('--norad_catIDs', '-n', type=str, default=os.path.join(os.environ['OCDATAROOT'],'common','norad_catalog.json'), help="JSON file in the form {'satellite':<catID>}")
61 parser.add_argument('--verbose', '-v', action='count', default=0)
62 
63 args = parser.parse_args()
64 
65 if args.verbose > 1:
66  logging.basicConfig(level=logging.DEBUG)
67 
68 identity = args.username
69 password = args.password
70 
71 if not identity:
72  netrc = os.path.join(os.environ['HOME'],'.netrc')
73  with open(netrc,'r') as cred:
74  for line in cred:
75  if line.startswith('machine www.space-track.org'):
76  parts = line.split()
77  identity = parts[3]
78  password = parts[5]
79 
80 credentials={'identity':identity,'password':password}
81 
82 if not identity or not password:
83  sys.exit("Authentication credentials required! Check your $HOME/.netrc or pass in via --username/--password")
84 
85 baseTLEdir = args.directory
86 
87 if args.norad_catIDs:
88  if os.path.isfile(args.norad_catIDs):
89  try:
90  with open(args.norad_catIDs) as fj:
91  norad = json.load(fj)
92  except json.JSONDecodeError as e:
93  print(e)
94  sys.exit("Failed to read %s" % args.norad_catIDs)
95  elif args.norad_catIDs == os.path.join(os.environ['OCDATAROOT'],'common','norad_catalog.json') and not os.path.isfile(args.norad_catIDs):
96  if args.verbose:
97  print("%s does not exist, using default set" % args.norad_catIDs)
98  else:
99  sys.exit("%s does not exist...exiting" % args.norad_catIDs)
100 
101 tleIDs = None
102 if args.satellite:
103  if args.satellite == 'ALL':
104  tleIDs = ','.join(str(tle) for tle in norad.values())
105  else:
106  tleIDs = str(norad[args.satellite])
107 
108 if args.catID:
109  tleIDs = str(args.catID)
110 
111 if not tleIDs:
112  parser.print_help()
113  sys.exit("\nEither provide a satellite name (or ALL) or as --catID")
114 
115 baseurl = "https://www.space-track.org"
116 loginurl = '/'.join([baseurl, "ajaxauth","login"])
117 tleurl = '/'.join([baseurl,"basicspacedata","query","class","tle_latest","ORDINAL","1","NORAD_CAT_ID",tleIDs,"format","tle"])
118 
119 #Get login cookie
120 stConn = requests.Session()
121 
122 #Get TLEs
123 tlehash = {}
124 
125 try:
126  req = stConn.post(loginurl, data=credentials)
127  if req.status_code != 200:
128  sys.exit("Received response: %d from space-track.org...unable to log in...exiting..." % req.status_code)
129 
130  if args.verbose:
131  print("Contacting Space-Track with the following request\n\t%s" % tleurl)
132 
133 except requests.exceptions.RequestException as e:
134  print(e)
135  sys.exit(1)
136 
137 try:
138  tlereq = stConn.get(tleurl)
139  if tlereq.status_code != 200:
140  sys.exit("Received response: %d from space-track.org...exiting..." % tlereq.status_code)
141 
142  for line in tlereq.text.splitlines():
143  if len(line) < 10:
144  continue
145  parts = line.split()
146  tleID = int(parts[1].strip('U'))
147  if tleID in tlehash:
148  tlehash[tleID].append(line)
149  else:
150  tlehash[tleID] = [line]
151 
152  tlereq.close()
153 except requests.exceptions.RequestException as e:
154  print(e)
155  sys.exit(1)
156 
157 #Process retrieved TLEs
158 for tleID in tlehash.keys():
159 
160  bird = 'NORAD_' + str(tleID)
161  for sat, cat in norad.items():
162  if cat == tleID:
163  bird = sat
164 
165  tle = tlehash[tleID]
166  if len(tle) != 2:
167  print ("Whoops! TLE retrieval error for %s" % bird)
168  else:
169  tleDate = tle[0].split()[3]
170  year = str(int(tleDate[0:2]) + 2000)
171  doy = tleDate[2:5]
172  tleFile = os.path.join(baseTLEdir,bird+doy+year+".dat")
173  if args.ofile:
174  tleFile = args.ofile
175 
176  if args.verbose:
177  print("Writing TLE for NORAD catalog ID %d to %s" % (tleID,tleFile))
178 
179  with open(tleFile,'a') as f:
180  f.write(tle[0])
181  f.write("\n")
182  f.write(tle[1])
183  f.write("\n")
184 
185  if args.copyTCE:
186  tceFile = os.path.join(baseTLEdir,bird+".tce")
187  if args.ofile:
188  tceFile, ext = os.path.splitext(tleFile)
189  tceFile = tceFile + ".tce"
190 
191  if args.verbose:
192  print("Copying TLE: %s to %s" % (tleFile,tceFile))
193 
194  shutil.copyfile(tleFile,tceFile)