def test_authenticate(): def request_callback(request): if 'wrongpassword' in request.body: return (200, dict(), json.dumps({'Login': '******'})) elif 'unknownresponse' in request.body: # Space-Track doesn't respond like this, but make sure anything # other than {'Login': '******'} doesn't raise AuthenticationError return (200, dict(), json.dumps({'Login': '******'})) else: return (200, dict(), json.dumps('')) responses.add_callback( responses.POST, 'https://www.space-track.org/ajaxauth/login', callback=request_callback, content_type='application/json') st = SpaceTrackClient('identity', 'wrongpassword') with pytest.raises(AuthenticationError): st.authenticate() assert len(responses.calls) == 1 st.password = '******' st.authenticate() st.authenticate() # Check that only one login request was made since successful # authentication assert len(responses.calls) == 2 st = SpaceTrackClient('identity', 'unknownresponse') st.authenticate()
def test_bytes_response(): responses.add( responses.POST, 'https://www.space-track.org/ajaxauth/login', json='""') responses.add( responses.GET, 'https://www.space-track.org/fileshare/modeldef/class/download', json={ 'controller': 'fileshare', 'data': [ { 'Default': '0', 'Extra': '', 'Field': 'FILE_ID', 'Key': '', 'Null': 'NO', 'Type': 'int(10) unsigned' }, { 'Default': None, 'Extra': '', 'Field': 'FILE_CONTENET', 'Key': '', 'Null': 'YES', 'Type': 'longblob' } ]}) data = b'bytes response \r\n' responses.add( responses.GET, 'https://www.space-track.org/fileshare/query/class/download' '/format/stream', body=data) st = SpaceTrackClient('identity', 'password') assert st.download(format='stream') == data with pytest.raises(ValueError): st.download(iter_lines=True, format='stream') # Just use file_id to disambiguate URL from those above responses.add( responses.GET, 'https://www.space-track.org/fileshare/query/class/download' '/file_id/1', body=b'a' * (100 * 1024) + b'b') result = list(st.download( iter_content=True, file_id=1)) assert result[0] == b'a' * (100 * 1024) assert result[1] == b'b'
def test_spacetrack_methods(): """Verify that e.g. st.tle_publish calls st.generic_request('tle_publish')""" st = SpaceTrackClient('identity', 'password') with patch.object(SpaceTrackClient, 'generic_request') as mock_generic_request: for class_ in st.request_classes: method = getattr(st, class_) method() assert mock_generic_request.call_args == call(class_) with pytest.raises(AttributeError): st.madeupmethod()
def test_non_ratelimit_error(): responses.add( responses.POST, 'https://www.space-track.org/ajaxauth/login', json='""') responses.add( responses.GET, 'https://www.space-track.org/basicspacedata/modeldef/class/tle_publish', json={ 'controller': 'basicspacedata', 'data': [ { 'Default': '0000-00-00 00:00:00', 'Extra': '', 'Field': 'PUBLISH_EPOCH', 'Key': '', 'Null': 'NO', 'Type': 'datetime' }, { 'Default': '', 'Extra': '', 'Field': 'TLE_LINE1', 'Key': '', 'Null': 'NO', 'Type': 'char(71)' }, { 'Default': '', 'Extra': '', 'Field': 'TLE_LINE2', 'Key': '', 'Null': 'NO', 'Type': 'char(71)' } ]}) st = SpaceTrackClient('identity', 'password') # Change ratelimiter period to speed up test st._ratelimiter.period = 1 mock_callback = Mock() st.callback = mock_callback responses.add( responses.GET, 'https://www.space-track.org/basicspacedata/query/class/tle_publish', status=500, body='some other error') with pytest.raises(HTTPError): st.tle_publish() assert not mock_callback.called
def test_predicate_parse(): st = SpaceTrackClient('identity', 'password') predicates_data = [ { 'Default': '', 'Extra': '', 'Field': 'TEST', 'Key': '', 'Null': 'NO', 'Type': '%brokentype' } ] with pytest.raises(ValueError): st._parse_predicates_data(predicates_data) predicates_data = [ { 'Default': '', 'Extra': '', 'Field': 'TEST', 'Key': '', 'Null': 'NO', 'Type': 'unknowntype' } ] with pytest.raises(ValueError): st._parse_predicates_data(predicates_data) predicates_data = [ { 'Default': '', 'Extra': '', 'Field': 'TEST', 'Key': '', 'Null': 'NO', 'Type': 'enum()' } ] with pytest.raises(ValueError): st._parse_predicates_data(predicates_data) predicates_data = [ { 'Default': '', 'Extra': '', 'Field': 'TEST', 'Key': '', 'Null': 'NO', 'Type': "enum('a','b')" } ] predicate = st._parse_predicates_data(predicates_data)[0] assert predicate.values == ('a', 'b')
def test_ratelimit_error(): responses.add( responses.POST, 'https://www.space-track.org/ajaxauth/login', json='""') responses.add( responses.GET, 'https://www.space-track.org/basicspacedata/modeldef/class/tle_publish', json={ 'controller': 'basicspacedata', 'data': [ { 'Default': '0000-00-00 00:00:00', 'Extra': '', 'Field': 'PUBLISH_EPOCH', 'Key': '', 'Null': 'NO', 'Type': 'datetime' }, { 'Default': '', 'Extra': '', 'Field': 'TLE_LINE1', 'Key': '', 'Null': 'NO', 'Type': 'char(71)' }, { 'Default': '', 'Extra': '', 'Field': 'TLE_LINE2', 'Key': '', 'Null': 'NO', 'Type': 'char(71)' } ]}) responses.add( responses.GET, 'https://www.space-track.org/basicspacedata/query/class/tle_publish', status=500, body='violated your query rate limit') st = SpaceTrackClient('identity', 'password') # Change ratelimiter period to speed up test st._ratelimiter.period = 1 # Do it first without our own callback, then with. # Catch the exception when URL is called a second time and still gets HTTP 500 with pytest.raises(HTTPError): st.tle_publish() mock_callback = Mock() st.callback = mock_callback # Catch the exception when URL is called a second time and still gets HTTP 500 with pytest.raises(HTTPError): st.tle_publish() assert mock_callback.call_count == 1
def main(noradID, path): st = SpaceTrackClient('*****@*****.**', 'COSGCGroundSegment') try: st.authenticate() # Will raise an error if incorrect login except: print('Incorrect Login.') sys.exit(0) data = st.tle_latest(iter_lines=True, norad_cat_id=noradID, limit=1, format='3le') # Change format to whatever is easiest line1 = next(data) # 0 MINXSS line2 = next(data) # 1 blah blah line3 = next(data) # 2 blah blah outFile = path + line1.split()[1] + '.txt' # Need to split up the generator to get the name for above. with open(outFile, 'w+') as f: f.write(line1) f.write(line2) f.write(line3)
def test_generic_request_exceptions(): st = SpaceTrackClient('identity', 'password') with pytest.raises(ValueError): st.generic_request(class_='tle', iter_lines=True, iter_content=True) with pytest.raises(ValueError): st.generic_request(class_='thisclassdoesnotexist') def mock_get_predicates(self, class_): return [] patch_authenticate = patch.object(SpaceTrackClient, 'authenticate') patch_get_predicates = patch.object( SpaceTrackClient, 'get_predicates', mock_get_predicates) with patch_authenticate, patch_get_predicates: with pytest.raises(TypeError): st.generic_request('tle', madeupkeyword=None)
def test_get_predicates(): st = SpaceTrackClient('identity', 'password') patch_authenticate = patch.object(SpaceTrackClient, 'authenticate') patch_get_predicates = patch.object(SpaceTrackClient, 'get_predicates') with patch_authenticate, patch_get_predicates as mock_get_predicates: st.tle.get_predicates() st.basicspacedata.tle.get_predicates() st.basicspacedata.get_predicates('tle') st.get_predicates('tle') st.get_predicates('tle', 'basicspacedata') expected_calls = [ call(class_='tle', controller='basicspacedata'), call(class_='tle', controller='basicspacedata'), call(class_='tle', controller='basicspacedata'), call('tle'), call('tle', 'basicspacedata') ] assert mock_get_predicates.call_args_list == expected_calls
pos = state[0:3] vel = state[3:6] d_pos = vel d_vel = -pos * mu / norm(pos)**3 return hstack([d_pos, d_vel]) login_info = sys.argv[1] Directory = sys.argv[2] login_file = open(login_info, 'r') username = login_file.readline().replace('\n', '') password = login_file.readline().replace('\n', '') st = SpaceTrackClient(username, password) for passfile in [ os.path.join(Directory, file) for file in os.listdir(Directory) if os.path.isdir(os.path.join(Directory, file)) ]: time.sleep(2) print(passfile) if (not os.path.join(passfile, 'sunvec.npy') in os.listdir(passfile)) or ( not os.path.join(passfile, 'obsvec.npy') in os.listdir(passfile)): julian_dates = load(os.path.join(passfile, 'julian_dates0.npy')) norad_id = load(os.path.join(passfile, 'norad_id0.npy')) timesteps = diff(julian_dates) * 24 * 3600 plt.plot(timesteps)
def update_from_online(tle_path): log.info("Updataing TLEs in {}".format(tle_path)) now = datetime.datetime.utcnow() time = now.strftime("%Y%m%d_%H%M%S") # Get Space Track TLEs catalog_tle = os.path.join(tle_path, 'catalog.tle') st = SpaceTrackClient(identity=cfg.get('Credentials', 'st-username'), password=cfg.get('Credentials', 'st-password')) data = st.tle_latest(iter_lines=True, epoch='>now-30', ordinal=1, format='3le') with open(catalog_tle, 'w') as fp: for line in data: # Fix missing leading zeros line = re.sub("^1 ", "1 0000", line) line = re.sub("^2 ", "2 0000", line) line = re.sub("^1 ", "1 000", line) line = re.sub("^2 ", "2 000", line) line = re.sub("^1 ", "1 00", line) line = re.sub("^2 ", "2 00", line) line = re.sub("^1 ", "1 0", line) line = re.sub("^2 ", "2 0", line) fp.write(line + '\n') copyfile(catalog_tle, os.path.join(tle_path, time + '_catalog.txt')) # Get classified TLEs resp = urlopen("http://www.prismnet.com/~mmccants/tles/classfd.zip") zipfile = ZipFile(BytesIO(resp.read())) zipfile.extractall(path=tle_path) classfd_tle = os.path.join(tle_path, 'classfd.tle') content = None outsize = 0 with open(classfd_tle, 'rb') as infile: content = infile.read() with open(classfd_tle, 'wb') as output: for line in content.splitlines(): outsize += len(line) + 1 output.write(line + b'\n') copyfile(classfd_tle, os.path.join(tle_path, time + '_classfd.txt')) # Get int TLEs resp = urlopen("http://www.prismnet.com/~mmccants/tles/inttles.zip") zipfile = ZipFile(BytesIO(resp.read())) zipfile.extractall(path=tle_path) int_tle = os.path.join(tle_path, 'inttles.tle') content = None outsize = 0 with open(int_tle, 'rb') as infile: content = infile.read() with open(int_tle, 'wb') as output: for line in content.splitlines(): outsize += len(line) + 1 output.write(line + b'\n') copyfile(int_tle, os.path.join(tle_path, time + '_inttles.txt')) # Create bulk catalog catalogs = [catalog_tle, classfd_tle] with open(os.path.join(tle_path, 'bulk.tle'), 'w') as outfile: for fname in catalogs: with open(fname) as infile: outfile.write(infile.read())
import sys import math import ephem import datetime import time import calendar from spacetrack import SpaceTrackClient st = SpaceTrackClient('*****@*****.**', 'johnnyboy1234567') import zipcode from geopy.geocoders import Nominatim import requests import json from twilio.rest import TwilioRestClient import pygame import RPi.GPIO as GPIO dates_viewable = [] def get_args(): opt_in_opt = "ERROR: cannot take another opt flag as a parameter" cmd_args = sys.argv zip_op = '-z' sat_op = '-s' if len(cmd_args) != 5: print('Error: Invalid number of argument!') sys.exit() # raise SystemExit cmd_len = len(cmd_args) if cmd_args[1] == zip_op and cmd_args[3] == sat_op: zip = cmd_args[2] sat = cmd_args[4]
def __init__(self): """ Connects user to Space-Track account """ self.client = SpaceTrackClient(identity=UN, password=self._request_access())
# Process commandline options and parse configuration cfg = configparser.ConfigParser(inline_comment_prefixes=('#', ';')) if args.conf_file: cfg.read([args.conf_file]) else: cfg.read('configuration.ini') tle_path = cfg.get('Common', 'tle_path') now = datetime.datetime.utcnow() time = now.strftime("%Y%m%d_%H%M%S") print('Get Space Track TLEs') catalog_tle = os.path.join(tle_path, 'catalog.tle') st = SpaceTrackClient(identity=cfg.get('Credentials', 'st-username'), password=cfg.get('Credentials', 'st-password')) data = st.tle_latest(iter_lines=True, epoch='>now-30', ordinal=1, format='3le') with open(catalog_tle, 'w') as fp: for line in data: # Fix missing leading zeros line = re.sub("^1 ", "1 0000", line) line = re.sub("^2 ", "2 0000", line) line = re.sub("^1 ", "1 000", line) line = re.sub("^2 ", "2 000", line) line = re.sub("^1 ", "1 00", line) line = re.sub("^2 ", "2 00", line)
def test_predicate_parse_modeldef(): st = SpaceTrackClient('identity', 'password') predicates_data = [{ 'Default': '', 'Extra': '', 'Field': 'TEST', 'Key': '', 'Null': 'NO', 'Type': '%brokentype' }] with pytest.raises(ValueError): st._parse_predicates_data(predicates_data) predicates_data = [{ 'Default': '', 'Extra': '', 'Field': 'TEST', 'Key': '', 'Null': 'NO', 'Type': 'unknowntype' }] msg = "Unknown predicate type 'unknowntype'" with pytest.warns(UnknownPredicateTypeWarning, match=msg): st._parse_predicates_data(predicates_data) predicates_data = [{ 'Default': '', 'Extra': '', 'Field': 'TEST', 'Key': '', 'Null': 'NO', 'Type': 'enum()' }] with pytest.raises(ValueError): st._parse_predicates_data(predicates_data) predicates_data = [{ 'Default': '', 'Extra': '', 'Field': 'TEST', 'Key': '', 'Null': 'NO', 'Type': "enum('a','b')" }] predicate = st._parse_predicates_data(predicates_data)[0] assert predicate.values == ('a', 'b') predicates_data = [{ 'Default': '', 'Extra': '', 'Field': 'TEST', 'Key': '', 'Null': 'NO', 'Type': "enum('a')" }] predicate = st._parse_predicates_data(predicates_data)[0] assert predicate.values == ('a', ) predicates_data = [{ 'Default': '', 'Extra': '', 'Field': 'TEST', 'Key': '', 'Null': 'NO', 'Type': "enum('a','b','c')" }] predicate = st._parse_predicates_data(predicates_data)[0] assert predicate.values == ('a', 'b', 'c')
def grab_gp_history_data(socrates_files_path, tle_file_path, spacetrack_key_file='./spacetrack_pwd.key'): ''' Determines which TLE data is missing and grabs it from Space Track Parameters: ----------- socrates_files_path : str Relative file path of socrates files tle_file_path : str Relative file path of TLE data spacetrack_key_file : str Relative file path of login credentials for spacetrack. File format: email,password Returns ------- None ''' print('Building socrates dataframe...') soc_df, tle_df = socrates.get_all_socrates_and_tle_data( socrates_files_path, tle_file_path) print('Complete') # Get space track login data spacetrack_usr, spacetrack_pwd = open( spacetrack_key_file).read()[:-1].split(',') st = SpaceTrackClient(identity=spacetrack_usr, password=spacetrack_pwd) tmp_tle_file = './tle2.csv' # Create a new df of the socrates entries with missing TLE data mtle_df1 = tle_df[tle_df['sat1_tle'].isnull()][[ 'sat1_norad', 'sat1_last_epoch' ]].rename(columns={ 'sat1_norad': 'norad', 'sat1_last_epoch': 'last_epoch' }) mtle_df2 = tle_df[tle_df['sat2_tle'].isnull()][[ 'sat2_norad', 'sat2_last_epoch' ]].rename(columns={ 'sat2_norad': 'norad', 'sat2_last_epoch': 'last_epoch' }) miss_tle_df = pd.concat([mtle_df1, mtle_df2]) miss_tle_df = miss_tle_df.sort_values('last_epoch') # Split the missing TLE dataset into bins bin_size = 100 num_bins = round(len(miss_tle_df) / bin_size + 0.49999) miss_tle_df['bin'] = pd.qcut(miss_tle_df['last_epoch'], num_bins, labels=list(range(num_bins))) print( f'There are {len(miss_tle_df)} missing TLE entries. We will make {num_bins} requests for this data.' ) print('Getting missing TLE data from Space Track...') # For each bin - make a request to SpaceTrack for all norads within that bin with a min/max daterange # This will save the data to a CSV file we will parse next (we save to ensure an interrupted progress # does not result in a massive amount of lost data) count = 0 for b in tqdm(range(num_bins)): tmp_df = miss_tle_df[miss_tle_df['bin'] == b] min_epoch = tmp_df['last_epoch'].min().to_pydatetime() max_epoch = tmp_df['last_epoch'].max().to_pydatetime() epoch_range = op.inclusive_range(min_epoch - timedelta(minutes=5), max_epoch + timedelta(minutes=5)) all_norads = list(tmp_df['norad'].unique()) all_data = st.gp_history(norad_cat_id=all_norads, epoch=epoch_range) # Write the data to a file for idx, row in tmp_df.iterrows(): d = list( filter( lambda rec: (rec['NORAD_CAT_ID'] == str(row['norad'])) & (abs( pd.to_datetime(rec['EPOCH'], format='%Y-%m-%dT%H:%M:%S.%f') - row['last_epoch']) < pd.Timedelta('5 min')), all_data))[0] with open(tmp_tle_file, 'a') as f: s = ','.join([ str(row['norad']), row['last_epoch'].strftime('%Y%m%d%H%M%S%f'), d['TLE_LINE1'], d['TLE_LINE2'], d['EPOCH'] ]) f.write(s + '\n') # Open the file created above which contains our new TLE data from SpaceTrack new_tle_df = pd.read_csv( tmp_tle_file, names=['norad', 'last_epoch', 'tle_line1', 'tle_line2', 'tle_epoch']) new_tle_df['last_epoch'] = pd.to_datetime(new_tle_df['last_epoch'], format='%Y%m%d%H%M%S%f') print(f'Space Track grabs are complete.') # For each TLE record, find the corresponding socrates data and update their TLE print(f'Merging {len(new_tle_df)} records with our socrates data...') count = 0 all_success = True for index, row in tqdm(new_tle_df.iterrows()): found = False target = tle_df[(tle_df['sat1_norad'] == row['norad']) & (abs(tle_df['sat1_last_epoch'] - row['last_epoch']) < pd.Timedelta('5 min'))].index if len(target) > 0: found = True tle_df.at[target, 'sat1_tle'] = row['tle_line1'] + ',' + row['tle_line2'] tle_df.at[target, 'sat1_tle_epoch'] = row['tle_epoch'] count += 1 target = tle_df[(tle_df['sat2_norad'] == row['norad']) & (abs(tle_df['sat2_last_epoch'] - row['last_epoch']) < pd.Timedelta('5 min'))].index if len(target) > 0: found = True tle_df.at[target, 'sat2_tle'] = row['tle_line1'] + ',' + row['tle_line2'] tle_df.at[target, 'sat2_tle_epoch'] = row['tle_epoch'] count += 1 if not found: print( f'Cant find norad={row["norad"]} for date {row["last_epoch"]} - perhaps we have an updated socrates file?' ) all_success = False print(f'Finished merging {count} records') # Save the TLE data to a pickle file print(f'Saving results...') tle_df[[ 'sat_pair', 'tca_time', 'sat1_norad', 'sat2_norad', 'sat1_tle', 'sat1_tle_epoch', 'sat2_tle', 'sat2_tle_epoch' ]].to_pickle(tle_file_path, 'gzip') print(f'Save to {tle_file_path} complete') if all_success: remove(tmp_tle_file) print(f'Removed temporary file') else: print( '******************************* WARNING *******************************' ) print( f'Please check messages and remove {tmp_tle_file} if everything was okay.' ) return None
def main(): #authenticate spacetrack API st = SpaceTrackClient(identity='<insert your registered email>', password='******') #pull TLE for NORAD catalog_id (25544 = ISS) v = st.tle(norad_cat_id=25544, orderby='epoch desc', limit=1, format='tle') #split at \n and set variables k = v.split("\n") #print("NORAD TLE for ISS (ZARYA) - cat id: 25544") #print(k[0]) #print(k[1] + "\n") #parse TLE t_e = k[0][20:32] #epoch minute e = "." + k[1][26:34] #eccentricity mean_motion = k[1][52:69] #mean motion (rev/day) M_e = k[1][43:52] #mean anomaly at epoch inclination = k[1][8:17] #inclination RAAN = k[1][17:26] #right angle of ascending node (uppercase omega) perigee = k[1][34:42] #argument of perigee (lowercase omega) #print("---Orbital Parameters---") #print("Epoch: " + t_e + " yrday.fracday") #print("Mean Anomaly (@epoch): " + M_e + " degrees") #print("Eccentricity: " + e) #print("Mean motion: " + mean_motion + " rev/day") #print("Inclination: " + inclination + " degrees") #print("RAAN: " + RAAN + " degrees") #print("Arg of perigee: " + perigee + " degrees\n") #convert mean motion into radians per second (rad/s) # # revolutions 2pi radians 1 day # -------------- x ----------- x ---------- # day revolution 86400 seconds n = float(mean_motion) * (2.0 * pi) / 86400.0 M_e = float(M_e)*pi/180.0 #print("Mean Motion: " + str(n) + " rad/s") #print("M_e: " + str(M_e)) #get current day and fractional portion of day curr_time = datetime.now() yd = datetime.now().timetuple().tm_yday #get current day of the year t = yd + ((curr_time.hour*3600.0 + curr_time.minute*60.0 + curr_time.second) / 86400.0) #print("Current time: " + str(t)) time_diff= float(t) - float(t_e) #print("Time difference: " + str(time_diff)) hours = time_diff*24.0 #print("Hours: " + str(hours) + "\t" + str(hours*3600)) minutes = (hours - int(hours))*60.0 #print("Minutes: " + str(minutes) + "\t" + str(minutes*60)) seconds = (minutes - int(minutes))*60.0 #print("Seconds: " + str(seconds)) temp = ((hours*3600.0)+(minutes*60.0)+seconds) #print("Seconds since Epoch: " + str(temp)) #calculate mean anomaly at current time M = (n*int(temp)+M_e)%(2*pi) print("Mean Anomaly: " + str(M*180.0/pi) + " degrees") #print("Mean Anomaly: " + str(M) + " radians") #56.410523467395286 #***************************************************************************** # #This section of code from: Paul Griffiths # #Solves for Eccentric Anomaly # #found @ 'https://github.com/paulgriffiths/pyastro/blob/master/functions.py' # #<borrowed code> desired_accuracy = 1e-6 e_anom = float(M) #starting guess #print("---Eccentric Anomaly---") #added #print("Initial guess: " + str(e_anom*180/pi) + " degrees") #added while True: diff = e_anom - float(e) * sin(e_anom) - float(M) e_anom -= float(diff) / (1 - float(e) * cos(e_anom)) if abs(diff) <= desired_accuracy: break #</borrowed code> #***************************************************************************** e_anom_degrees = e_anom * (180.0/pi) #convert eccentric anomaly into degrees #print("Eccentric Anomaly: " + str(e_anom_degrees) + " degrees") mu = 398600.5 J_2 = 1082.63e6 earthRadius = 6378.137 i = float(inclination) * (pi/180.0) #condensing crazy long formula for mean anomaly... p = 1.5 * J_2 * earthRadius**2.0 w = 1.0 - ((1.5)* sin(i)**2.0) q = 1.0 / sqrt(1.0 - (float(e)**2.0)**3.0) x = p * w * q #into a single variable for newton approximation sqrt_mu = sqrt(mu) #Begin Newton Approximation semiMajor_axis = (mu / n**2.0) ** (1. / 3) #initial guess for newton approximation #print("---Semi-Major Axis---") #print("Initial Guess: " + str(semiMajor_axis)) #iterate while True: difference = (sqrt_mu * sqrt((semiMajor_axis**-3.0))) + (x * sqrt_mu * sqrt((semiMajor_axis**-7.0))) - n semiMajor_axis -= float(difference) / (-3.0/2)*sqrt_mu*sqrt((semiMajor_axis**-5.0)) - (7.0/2.0)*x*sqrt_mu*sqrt((semiMajor_axis**-9.0)) if abs(diff) <= desired_accuracy: break #print("Newton Approx: " + str(semiMajor_axis)) #calculate satellite orbital coordinates sat_x = semiMajor_axis * (cos(e_anom) - float(e)) sat_y = semiMajor_axis * sqrt(1.0 - float(e)**2.0) * sin(e_anom) sat_z = 0.0 #print(str(sat_x) + "\t" + str(sat_y) + "\t" + str(sat_z)) #print("\n---Satellite Cartesian Orbital Coordinates---") #print("Xo: " + str(sat_x) + "km") #print("Yo: " + str(sat_y) + "km") #print("Zo: " + str(sat_z) + "km\n") #transform into inertial coordinates w = float(perigee)*pi/180.0 omega = float(RAAN)*pi/180.0 #transformation matrix inertial_trans = np.matrix([[cos(w)*cos(omega)-sin(w)*sin(omega)*cos(i),(-1.0)*sin(w)*cos(omega)-cos(w)*cos(i)*sin(omega),sin(omega)*sin(i)], [cos(w)*sin(omega)+sin(w)*cos(i)*cos(omega),(-1.0)*sin(w)*sin(omega)+cos(w)*cos(i)*cos(omega),(-1.0)*cos(omega)*sin(i)], [sin(w)*sin(i),cos(w)*sin(i),cos(i)]]) orbital_coord = np.matrix([[sat_x],[sat_y],[sat_z]]) inertial_coord = inertial_trans * orbital_coord #print("---Satellite Interial Coordinates---") #print("Xi: " + str(inertial_coord[0][0])) #print("Yi: " + str(inertial_coord[1][0])) #print("Zi: " + str(inertial_coord[2][0]) + "\n") #current Year Month and Date for Julian Days (JD) time calculation Y = curr_time.year M = curr_time.month D = t/7 if (M == 1 | M == 2): Y = Y - 1 M = M + 12 #calculate GMST angle A = floor(Y/100) B = 2 - A + floor(A / 4) JD = floor(365.25*(Y+4716)) + floor(30.6001*(M+1)) + D + B - 1524.5 #verified using an online calculator T = (JD - 2415020.0) / 36525 #GMSTo = 99.6910+36000.7689*T + 0.0004*(T**2.0) #wEarth = 7.2921150e-5 * 180 / pi GMST = 280.46061837 + (360.98564736629*(JD-2451545.0)) + 0.000387933*(T**2.0) - ((T**3.0)/38710000) #GMST = GMSTo + wEarth*JD #print("GMST angle: " + str(GMST)) GMST = GMST % 360 #convert to [0,360] range #print("GMST angle: " + str(GMST) + "\n") #this looked right based on ISS tracker GMST_rad = GMST * (pi/180.0) #Transform inertial coordinates into Greenwhich coordinates greenwich_trans = np.matrix([[cos(GMST_rad),sin(GMST_rad),0],[(-1.0)*sin(GMST_rad),cos(GMST_rad),0],[0,0,1]]) greenwich_coord = greenwich_trans * inertial_coord #print("---Satellite Greenwich Coordinates---") #print("Xg: " + str(greenwich_coord[0][0])) #print("Yg: " + str(greenwich_coord[1][0])) #print("Zg: " + str(greenwich_coord[2][0]) + "\n") #terminal-satellite vector in greenwich coordinates termLatitude = 33.889650*pi/180 termLongitutde = -77.434887*pi/180 h = 1.0 polarRadius = 6356.755 #geocentric latitude of ground terminal phi_gc = np.arctan((polarRadius/earthRadius)*np.tan(termLatitude)) #radius of the earth at ground terminal r_t = h + (earthRadius*polarRadius)/sqrt(((earthRadius*sin(phi_gc))**2.0)+((polarRadius*cos(phi_gc))**2.0)) #terminal cartesian coordinates terminal_coord = np.matrix([[r_t*cos(termLongitutde)*cos(termLatitude)], [r_t*sin(termLongitutde)*cos(termLatitude)], [r_t*sin(termLatitude)]]) terminal_x = float(terminal_coord[0][0]) * 1000.0 terminal_y = float(terminal_coord[1][0]) * 1000.0 terminal_z = float(terminal_coord[2][0]) * 1000.0 #print("---Ground Terminal Cartesian Coordinates---") #print("Rgx: " + str(terminal_x) + "m") #print("Rgy: " + str(terminal_y)) #print("Rgz: " + str(terminal_z) + "\n") #verified cartesian coordinates using online calculator #http://www.apsalin.com/convert-geodetic-to-cartesian.aspx #values were off slightly... dont know if this effects the overall output much though #calculate the terminal-satellite vector in greenwich coordinates #by subtracting ground terminal coordinates from satellite coordinates term_sat_greenwich_coord = np.matrix(greenwich_coord - terminal_coord) #print("---Terminal-Satellite Vector in Greenwich Coordinates---") #print("Rgx: " + str(term_sat_greenwich_coord[0][0])) #print("Rgy: " + str(term_sat_greenwich_coord[1][0])) #print("Rgz: " + str(term_sat_greenwich_coord[2][0]) + "\n") #terminal-satellite vector in topocentric coordinates topo_trans = np.matrix([[sin(phi_gc)*cos(termLongitutde),sin(phi_gc)*sin(termLongitutde),(-1.0)*cos(phi_gc)], [(-1.0)*sin(phi_gc),cos(phi_gc),0], [cos(phi_gc)*cos(termLongitutde),cos(phi_gc)*sin(termLongitutde),sin(phi_gc)]]) topo_coord = topo_trans * term_sat_greenwich_coord #print("---Terminal-Sattelite Vector Topocentric Coordinates") #print("Rx: " + str(topo_coord[0][0])) #print("Ry: " + str(topo_coord[1][0])) #print("Rz: " + str(topo_coord[2][0]) + "\n") Rx = float(topo_coord[0][0]) Ry = float(topo_coord[1][0]) Rz = float(topo_coord[2][0]) #calculate elevation, azimuth and slant range d = sqrt((Rx**2.0)+(Ry**2.0)+(Rz**2.0)) azimuth = pi - np.arctan(Ry/Rx) elevation = float(np.arcsin(Rz/d))*180/pi
def __init__(self): un, pw = self.requestAccess() self.username = un self.password = pw self.client = SpaceTrackClient(identity=un, password=pw)
class ST: """ Space-Track Interface """ def __init__(self): un, pw = self.requestAccess() self.username = un self.password = pw self.client = SpaceTrackClient(identity=un, password=pw) def requestAccess(self): """ Obtain user access details """ st_un = '*****@*****.**' st_pw = gp.getpass('Space-Track password: '******'>now-30', ordinal=1, format=LE_FORMAT) def getPastTLE(self, norad, start, end, epoch=None): """ Obtain list of TLEs for a NORAD object within an epoch range, narrowed down to one (most recent) if desired epoch given """ return def getRunCat(self, dates, cat_type, out_dir=None): """ Obtain catalog of GEO TLEs for a given epoch range Parameters ---------- dates : array-like List of (start, end) tuples corresponding to appropriate limits for querying the Space-Track API cat_type : str Type of objects to be queried (e.g. 'geo') out_dir : str, optional Output directory in which to store catalogue Default = None Returns ------- tles : array-like Element sets returned from query to SpaceTrack """ orb = Orbit(cat_type) tles = [] for date in dates: date_range = '{}--{}'.format(date[0].strftime('%Y-%m-%d'), date[1].strftime('%Y-%m-%d')) if cat_type in GEO_CHECK + LEO_CHECK: result = self.client.tle(iter_lines=True, eccentricity=orb.e_lim, mean_motion=orb.mm_lim, epoch=date_range, limit=200000, format=LE_FORMAT) elif cat_type in MEO_CHECK: result = self.client.tle(iter_lines=True, eccentricity=orb.e_lim, period=orb.p_lim, epoch=date_range, limit=200000, format=LE_FORMAT) elif cat_type in HEO_CHECK: result = self.client.tle(iter_lines=True, eccentricity=orb.e_lim, epoch=date_range, limit=200000, format=LE_FORMAT) elif cat_type in ALL_CHECK: result = self.client.tle(iter_lines=True, epoch=date_range, limit=200000, format=LE_FORMAT) else: print('Incorrect format! Please supply a valid' 'orbit type... \n' 'GEO - "g" \n' 'LEO - "l" \n' 'MEO - "m" \n' 'HEO - "h" \n' 'ALL - "a" \n') tles += [line for line in result] print('Number of tles returned: {}'.format(str(len(tles)))) if out_dir is not None: with open(out_dir + 'run_cat.txt', 'w') as f: for line in tles: f.write('{}\n'.format(line)) return tles
def test_generic_request(): responses.add( responses.POST, 'https://www.space-track.org/ajaxauth/login', json='""') responses.add( responses.GET, 'https://www.space-track.org/basicspacedata/modeldef/class/tle_publish', json={ 'controller': 'basicspacedata', 'data': [ { 'Default': '0000-00-00 00:00:00', 'Extra': '', 'Field': 'PUBLISH_EPOCH', 'Key': '', 'Null': 'NO', 'Type': 'datetime' }, { 'Default': '', 'Extra': '', 'Field': 'TLE_LINE1', 'Key': '', 'Null': 'NO', 'Type': 'char(71)' }, { 'Default': '', 'Extra': '', 'Field': 'TLE_LINE2', 'Key': '', 'Null': 'NO', 'Type': 'char(71)' } ]}) tle = ( '1 25544U 98067A 08264.51782528 -.00002182 00000-0 -11606-4 0 2927\r\n' '2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537\r\n') normalised_tle = tle.replace('\r\n', '\n') responses.add( responses.GET, 'https://www.space-track.org/basicspacedata/query/class/tle_publish' '/format/tle', body=tle) st = SpaceTrackClient('identity', 'password') assert st.tle_publish(format='tle') == normalised_tle lines = list( st.tle_publish(iter_lines=True, format='tle')) assert lines == [ '1 25544U 98067A 08264.51782528 -.00002182 00000-0 -11606-4 0 2927', '2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537' ] responses.add( responses.GET, 'https://www.space-track.org/basicspacedata/query/class/tle_publish', json={'a': 5}) result = st.tle_publish() assert result['a'] == 5 # Just use datetime to disambiguate URL from those above. responses.add( responses.GET, 'https://www.space-track.org/basicspacedata/query/class/tle_publish' '/publish_epoch/1986-01-28%2016:39:13', body='a' * (100 * 1024) + 'b') result = list(st.tle_publish( iter_content=True, publish_epoch=dt.datetime(1986, 1, 28, 16, 39, 13))) assert result[0] == 'a' * (100 * 1024) assert result[1] == 'b'
from spacetrack import SpaceTrackClient from skyfield.api import EarthSatellite, Topos, load from .stconfig.auth import USR, PASS if __name__ == "__main__": st = SpaceTrackClient(USR, PASS) tlelines = [st.tle_latest(norad_cat_id=45438)[0]["TLE_LINE1"], st.tle_latest(norad_cat_id=45438)[0]["TLE_LINE2"]] bcn = Topos(41.414850, 2.165036) ts = load.timescale() t0 = ts.utc(2020,12,23) t1 = ts.utc(2020,12,30) satellite = EarthSatellite(*tlelines, "STARKLINK-61", ts) t, events = satellite.find_events(bcn, t0, t1, altitude_degrees=30.0) for ti, event in zip(t, events): name = ('aos @ 30°', 'culminate', 'los @ < 30°')[event] if (ti.utc.hour >18 ):#and (event == 0): print(ti.utc_strftime('%Y %b %d %H:%M:%S'), name) difference = satellite - bcn topocentric = difference.at(ti) alt, az, distance = topocentric.altaz() print(" ",alt) print(" ",az) print(" ",int(distance.km), 'km')
class ST: """ Space-Track Interface """ def __init__(self): """ Connects user to Space-Track account """ un, pw = self.requestAccess() self.username = un self.password = pw self.client = SpaceTrackClient(identity=un, password=pw) def requestAccess(self): """ Obtain user access details - requests password from user """ st_un = '*****@*****.**' st_pw = gp.getpass('Space-Track password: '******'Pulling TLEs from Space-Track...') if orb.type in GEO_CHECK + LEO_CHECK: result = self.client.tle(iter_lines=True, eccentricity=orb.e_lim, mean_motion=orb.mm_lim, epoch='>now-30', limit=200000, format=LE_FORMAT) elif orb.type in MEO_CHECK: result = self.client.tle(iter_lines=True, eccentricity=orb.e_lim, period=orb.p_lim, epoch='>now-30', limit=200000, format=LE_FORMAT) elif orb.type in HEO_CHECK: result = self.client.tle(iter_lines=True, eccentricity=orb.e_lim, epoch='>now-30', limit=200000, format=LE_FORMAT) elif orb.type in ALL_CHECK: result = self.client.tle(iter_lines=True, epoch='>now-30', limit=200000, format=LE_FORMAT) else: print('Incorrect format! Please supply a valid' 'orbit type... \n' 'GEO - "g" \n' 'LEO - "l" \n' 'MEO - "m" \n' 'HEO - "h" \n' 'ALL - "a" \n') quit() result = [line for line in result] # organize into user-friendly format i = 0 catalog = {} while i < len(result): tle = TLE(result[i + 1], result[i + 2], name=result[i]) catalog.update({tle.norad_id: tle}) i += 3 return catalog
def test_generic_request_exceptions(): st = SpaceTrackClient('identity', 'password') with pytest.raises(ValueError): st.generic_request(class_='tle', iter_lines=True, iter_content=True) with pytest.raises(ValueError): st.generic_request(class_='thisclassdoesnotexist') def mock_get_predicates(self, class_): return [] patch_authenticate = patch.object(SpaceTrackClient, 'authenticate') patch_get_predicates = patch.object(SpaceTrackClient, 'get_predicates', mock_get_predicates) with patch_authenticate, patch_get_predicates: with pytest.raises(TypeError): st.generic_request('tle', madeupkeyword=None) with pytest.raises(ValueError): st.generic_request(class_='tle', controller='nonsense') with pytest.raises(ValueError): st.generic_request(class_='nonsense', controller='basicspacedata') with pytest.raises(AttributeError): st.basicspacedata.blahblah
def retrieveTLE(arglist=None): parser = ArgumentRecorder( description='Retrieve TLD data from space-track.org', fromfile_prefix_chars='@') parser.add_argument('-v', '--verbosity', type=int, default=1, private=True) parser.add_argument('--no-comments', action='store_true', help='Do not output descriptive comments') parser.add_argument('--no-header', action='store_true', help='Do not output CSV header with column names') parser.add_argument('-u', '--user', type=str, required=True, help='SpaceTrack.org username') parser.add_argument('-p', '--password', type=str, required=True, help='SpaceTrack.org password') parser.add_argument('-s', '--satellite', type=str, required=True, help='NORAD name') parser.add_argument('--startdate', type=str, required=True, help='Start date/time in any sensible format') parser.add_argument('--enddate', type=str, help='End date/time in any sensible format') parser.add_argument('-l', '--limit', type=int, help='Limit number of TLEs to retrieve') parser.add_argument('-o', '--outfile', type=str, help='Output CSV file, otherwise use stdout.', output=True) parser.add_argument( '--logfile', type=str, help= "Logfile, default is 'outfile'.log or stdout if outfile not specified") parser.add_argument('--no-logfile', action='store_true', help='Do not output descriptive comments') args = parser.parse_args(arglist) args.startdate = dateparser.parse( args.startdate) if args.startdate else None args.enddate = dateparser.parse(args.enddate) if args.enddate else None if args.outfile is None: outfile = sys.stdout else: if os.path.exists(args.outfile): shutil.move(args.outfile, args.outfile + '.bak') outfile = open(args.outfile, 'w') if not args.no_logfile: if not args.logfile and not args.outfile: logfile = sys.stdout else: if args.logfile: logfilename = args.logfile elif args.outfile: logfilename = args.outfile.split('/')[-1].rsplit('.', 1)[0] + '.log' logfile = open(logfilename, 'w') parser.write_comments(args, logfile, incomments=ArgumentHelper.separator()) if args.logfile or args.outfile: logfile.close() st = SpaceTrackClient(identity=args.user, password=args.password) tledict = tlefile.read_platform_numbers() norad_cat_id = tledict[args.satellite] drange = op.inclusive_range(args.startdate, args.enddate or date.today()) lines = st.tle(norad_cat_id=norad_cat_id, epoch=drange, format='tle', limit=args.limit).split("\n") for line in lines: if len(line): outfile.write(line + "\n") if args.outfile is not None: outfile.close() exit(0)
class ST: """ Space-Track Interface """ def __init__(self): """ Connects user to Space-Track account """ self.client = SpaceTrackClient(identity=UN, password=self._request_access()) def _request_access(self): """ Obtain access details - requests user's password Returns ------- pw : str Password entered by user """ return gp.getpass('Space-Track password: '******'3le') ] return TLE(el_set[1], el_set[2], name=el_set[0]) def get_past_tle(self, norad_id, epoch, search_radius=10): """ Obtain past TLE (closest to given epoch) for NORAD object Parameters ---------- norad_id : int NORAD ID for object epoch : datetime.datetime Desired epoch search_radius : int, optional Search radius either side of epoch [days] Returns ------- tle : st.tle.TLE Past TLE for NORAD object """ epoch_range = '{}--{}'.format( (epoch - timedelta(days=search_radius)).strftime('%Y-%m-%d'), (epoch + timedelta(days=search_radius)).strftime('%Y-%m-%d')) el_sets = [ line for line in self.client.tle(norad_cat_id=norad_id, epoch=epoch_range, iter_lines=True, format='3le') ] delta_t = [] for i in range(int(len(el_sets) / 3)): tle = TLE(el_sets[3 * i + 1], el_sets[3 * i + 2], name=el_sets[3 * i]) delta_t.append(abs(tle.epoch.date - epoch)) idx = np.argmin(delta_t) return TLE(el_sets[3 * idx + 1], el_sets[3 * idx + 2], el_sets[3 * idx]) def get_sat_cat(self, norad_id): """ Obtain SatCat entry for NORAD object Parameters ---------- norad_id : int NORAD ID for object Returns ------- sat_cat : astropy.table.Table Table of SatCat information for NORAD object """ sat_cat = self.client.satcat(norad_cat_id=norad_id)[0] for key in sat_cat: sat_cat[key] = [sat_cat[key]] return Table(sat_cat)
def test_generic_request(): responses.add(responses.POST, 'https://www.space-track.org/ajaxauth/login', json='""') responses.add( responses.GET, 'https://www.space-track.org/basicspacedata/modeldef/class/tle_publish', json={ 'controller': 'basicspacedata', 'data': [{ 'Default': '0000-00-00 00:00:00', 'Extra': '', 'Field': 'PUBLISH_EPOCH', 'Key': '', 'Null': 'NO', 'Type': 'datetime' }, { 'Default': '', 'Extra': '', 'Field': 'TLE_LINE1', 'Key': '', 'Null': 'NO', 'Type': 'char(71)' }, { 'Default': '', 'Extra': '', 'Field': 'TLE_LINE2', 'Key': '', 'Null': 'NO', 'Type': 'char(71)' }] }) tle = ( '1 25544U 98067A 08264.51782528 -.00002182 00000-0 -11606-4 0 2927\r\n' '2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537\r\n' ) normalised_tle = tle.replace('\r\n', '\n') responses.add( responses.GET, 'https://www.space-track.org/basicspacedata/query/class/tle_publish' '/format/tle', body=tle) st = SpaceTrackClient('identity', 'password') assert st.tle_publish(format='tle') == normalised_tle lines = list(st.tle_publish(iter_lines=True, format='tle')) assert lines == [ '1 25544U 98067A 08264.51782528 -.00002182 00000-0 -11606-4 0 2927', '2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537' ] responses.add( responses.GET, 'https://www.space-track.org/basicspacedata/query/class/tle_publish', json={'a': 5}) result = st.tle_publish() assert result['a'] == 5 # Just use datetime to disambiguate URL from those above. responses.add( responses.GET, 'https://www.space-track.org/basicspacedata/query/class/tle_publish' '/publish_epoch/1986-01-28%2016:39:13', body='a' * (100 * 1024) + 'b') result = list( st.tle_publish(iter_content=True, publish_epoch=dt.datetime(1986, 1, 28, 16, 39, 13))) assert result[0] == 'a' * (100 * 1024) assert result[1] == 'b'
class SatInfoUpdate(object): """Class for updating TLEs and saving to memcached and pickle files""" def __init__(self, satFilename, stUsername=stUsername, stPassword=stPassword, pickleSave=False, dataDir="data"): self.dataDir = dataDir self.satFilename = os.path.join(self.dataDir, satFilename) self.stUsername = stUsername self.stPassword = stPassword self.pickleSave = pickleSave # Get base name from the satellite filename self.satType = os.path.splitext(satFilename)[0] self.st = SpaceTrackClient(self.stUsername, self.stPassword) self.mc = memcache.Client(['127.0.0.1:11211'], debug=0) def updateSatInfo(self, force=False): """ Update the TLEs, possibly with pickled file as well""" self.ids = self.getIDs() timestamp = self.mc.get("%s-timestamp" % self.satType) if timestamp is None: timestamp = 0 # If it's been longer than a day, update sat info if (((time.time() - timestamp) > 86400) or force): self.tles = self.getTLEs(self.ids) self.satcats = self.getSATCATs(self.ids) self.mc.set("%s-ids" % self.satType, self.ids) self.mc.set("%s-timestamp" % self.satType, time.time()) satInfos = [] for id in self.ids: satInfoDict = {} satInfoDict["tle"] = self.tles[id] satInfoDict["satcat"] = self.satcats[id] self.mc.set("%s-data" % id, satInfoDict) satInfos.append(satInfoDict) # If we're to update the pickle file, do so if self.pickleSave: with open( os.path.join(self.dataDir, "%s.pickle" % self.satType), "wb") as f: cPickle.dump(satInfos, f) def getIDs(self): # TODO: Error handling ids = self.mc.get("%s-ids" % self.satType) if ids is None: # Need to get the IDs and put them in memcached with open(os.path.join(self.satFilename), "r") as f: data = f.readlines() ids = [] for item in data: id = item.split("\t")[1].strip() ids.append(id.lstrip("0")) self.ids = ids self.mc.set("%s-ids" % self.satType, self.ids) return ids else: self.ids = ids return ids def getSATCATs(self, ids): """Get an updated version of SATCATs based on a list of NORAD IDs""" # TODO: Error handling # Get the SATCATs for the given list of IDs satcats = self.st.satcat(norad_cat_id=ids) # Create a dictionary where the keys are IDs and the values are the satcats satcatDictionary = {} for item in xrange(0, len(ids)): satcatDictionary[ids[item]] = satcats[item] return satcatDictionary def getTLEs(self, ids): """Get an updated version of TLEs based on a list of NORAD IDs""" # TODO: Error handling # Get the TLEs for the given list of IDs tles = self.st.tle_latest(norad_cat_id=ids, ordinal=1, format='tle') # Split out the TLEs and remove an extraneous element tles = tles.split("\n") tles.pop() # Create a dictionary where the keys are IDs and the values are the TLEs, as a two element list tleDictionary = {} for item in xrange(0, len(ids)): tleDictionary[ids[item]] = (tles[item * 2], tles[item * 2 + 1]) return tleDictionary
#!/usr/bin/python3 from spacetrack import SpaceTrackClient from dotenv import load_dotenv import os load_dotenv('./.env') st = SpaceTrackClient(os.getenv('EMAIL'), os.getenv('PASSWD')) satelites = os.getenv('SATS').split(' ') output = st.tle_latest(norad_cat_id=satelites, ordinal=1, format='tle') file = open('output.tle', 'w') file.write(output) file.close()
import spacetrack.operators as op from spacetrack import SpaceTrackClient from tletools import TLE from tletools.pandas import load_dataframe from datetime import datetime from skyfield.api import Topos, load from skyfield.units import Distance from matplotlib import pyplot as plt from astropy.visualization import hist from itertools import combinations from math import degrees, pi USERNAME = '******' PASSWORD = '******' st = SpaceTrackClient(identity=USERNAME, password=PASSWORD) data_generator = st.tle_latest(iter_lines=True, ordinal=1, epoch='>now-30', format='3le') with open('data.txt', 'w') as f: for line in data_generator: f.write(line + '\n') df = load_dataframe('data.txt') df['a'] = df['n'].apply(lambda n: (8681663.653 / n)**(2 / 3)) df['ah'] = df['a'] * (1 - df['ecc']) - 6371 df['ph'] = df['a'] * (1 + df['ecc']) - 6371
print("execute getTLE") referenceTime = (dt.datetime.utcnow() + dt.timedelta(days=-2)).timetuple() endTime = (dt.datetime.utcnow() + dt.timedelta(days=-1)).timetuple() currentYear = referenceTime[0] currentMonth = referenceTime[1] currentDay = referenceTime[2] currentHour = referenceTime[3] currentMinute = referenceTime[4] currentSecond = referenceTime[5] endYear = endTime[0] endMonth = endTime[1] endDay = endTime[2] dateRange = op.inclusive_range(dt.date(currentYear, currentMonth, currentDay), dt.date(endYear, endMonth, endDay)) satellite = 'TERRA' # hardcode at moment, need to improve satelliteID = 25994 st = SpaceTrackClient('*****@*****.**', 'P62-AER-sNJ-ubK') lines = st.tle(iter_lines=True, epoch=dateRange, norad_cat_id=satelliteID, orderby='TLE_LINE1 ASC', format='tle') filePath = os.getcwd() + '/app/tle.txt' print(filePath) with open(filePath, 'w') as fp: fp.write(satellite + '\n') for line in lines: print(line) fp.write(line + '\n')
def test_authenticate(): def request_callback(request): if 'wrongpassword' in request.body: return (200, dict(), json.dumps({'Login': '******'})) elif 'unknownresponse' in request.body: # Space-Track doesn't respond like this, but make sure anything # other than {'Login': '******'} doesn't raise AuthenticationError return (200, dict(), json.dumps({'Login': '******'})) else: return (200, dict(), json.dumps('')) responses.add_callback(responses.POST, 'https://www.space-track.org/ajaxauth/login', callback=request_callback, content_type='application/json') st = SpaceTrackClient('identity', 'wrongpassword') with pytest.raises(AuthenticationError): st.authenticate() assert len(responses.calls) == 1 st.password = '******' st.authenticate() st.authenticate() # Check that only one login request was made since successful # authentication assert len(responses.calls) == 2 st = SpaceTrackClient('identity', 'unknownresponse') st.authenticate()
def tle_download(noradids): ''' Download the TLE/3LE data from https://www.space-track.org Usage: tlefile = tle_download(noradids) tlefile = tle_download('satno.txt') Inputs: noradids -> [str, int, list of str/int] NORADID of space targets; it can be a single NORADID, list of NORADID, or a file containing a set of NORADID. The form and format of the file is as follows: #satno 12345 23469 ... Outputs: tlefile -> [str] Path of TLE/3LE file ''' # Check whether a list is empty or not if not noradids: raise Exception('noradids is empty.') if type(noradids) is int: noradids = str(noradids) elif type(noradids) is list: if type(noradids[0]) is int: noradids = [str(i) for i in noradids] elif '.' in noradids: # noradids as a file noradids = list(set(np.loadtxt(noradids, dtype=np.str))) else: pass # username and password for Space-Track home = str(Path.home()) direc = home + '/src/spacetrack-data/' loginfile = direc + 'spacetrack-login' if not path.exists(direc): makedirs(direc) if not path.exists(loginfile): username = input( 'Please input the username for Space-Track(which can be created at https://www.space-track.org/auth/login): ' ) password = input('Please input the password for Space-Track: ') outfile = open(loginfile, 'w') for element in [username, password]: outfile.write('{:s}\n'.format(element)) outfile.close() else: infile = open(loginfile, 'r') username = infile.readline().strip() password = infile.readline().strip() infile.close() st = SpaceTrackClient(username, password) lines_3le = st.tle_latest(norad_cat_id=noradids, ordinal=1, iter_lines=True, format='3le') # save TLE/3LE data to files dir_TLE = 'TLE/' fileList_TLE = glob(dir_TLE + '*') if path.exists(dir_TLE): for file in fileList_TLE: remove(file) else: mkdir(dir_TLE) valid_ids = [] file_3le = open(dir_TLE + 'satcat_3le.txt', 'w') print('\nDownloading TLE/3LE data', end=' ... ') for line in lines_3le: words = line.split() if words[0] == '2': valid_ids.append(words[1]) file_3le.write(line + '\n') file_3le.close() print('Complete') if type(noradids) is not list: noradids = [noradids] missing_ids = list(set(noradids) - set(valid_ids)) if missing_ids: print('Note: TLE data for these targets are not avaliable: ', missing_ids) return dir_TLE + 'satcat_3le.txt'
def get_tle_spacetrack(filename, flag='all'): r"""Download TLEs from spacetrack.org This function will download some TLEs from Space - track.org. It requires a valid user account on the website. It uses favorites lists which can be setup in your own account. Parameters ---------- filename : string Filename to store the downloaded TLEs flag : string This string can take one of three values. It allows you decide which TLE set to download from the website. all - Download bulk catalog visible - Download the visible satellite list stations - Download personal list called STATIONS brightest - download personal list called BRIGHTEST rv2coe - list used in RV2COE comfix - list used in COMFIX propogate - list used in PROPOGATE Returns ------- None : writes to filename References ---------- .. [1] spacetrack - https://github.com/python-astrodynamics/spacetrack """ from spacetrack import SpaceTrackClient logger = logging.getLogger(__name__) logger.info('Getting SpaceTrack password and connecting') username = input('Enter SpaceTrack.org username: '******'Enter SpaceTrack.org password: '******'w') as f: if flag == 'all': all_tles = st.tle_latest(ordinal=1, format='3le') elif flag == 'stations': all_tles = st.tle_latest(favorites='STATIONS', ordinal=1, format='3le') elif flag == 'brightest': all_tles = st.tle_latest(favorites='BRIGHTEST', ordinal=1, format='3le') elif flag == 'visible': all_tles = st.tle_latest(favorites='Visible', ordinal=1, format='3le') elif flag == 'rv2coe': all_tles = st.tle_latest(favorites='RV2COE', ordinal=1, format='3le') elif flag == 'comfix': all_tles = st.tle_latest(favorites='COMFIX', ordinal=1, format='3le') elif flag == 'propagate': all_tles = st.tle_latest(favorites='PROPAGATE', ordinal=1, format='3le') else: logger.warning('Incorrect flag for spacetrack') all_tles = "Incorrect flag" f.write(all_tles) return 0
def download_tle( start_date, stop_date, norad_ids, st_ident=None, st_pass=None, out_dir=None, sleep=20, mock=False, ): """Download TLEs from space-track.org. Download satellite TLEs within a date interval for all sats in :func:`~embers.sat_utils.sat_list.norad_ids` .. code-block:: python from embers.sat_utils.sat_list import norad_ids, download_tle n_ids = norad_ids() download_tle( "2020-01-01", "2020-02-01", n_ids, st_ident="*****@*****.**", st_pass="******", out_dir="~/embers-data/TLE") .. code-block:: console >>> Starting TLE download >>> Grab a coffee, this may take a while >>> downloading tle for ORBCOMM-X satellite [21576] from space-tracks.org >>> ... :param start_date: in :samp:`YYYY-MM-DD` format :class:`~str` :param stop_date: in :samp:`YYYY-MM-DD` format :class:`~str` :param norad_ids: sat_name: NORAD_ID :class:`~dict` :param st_ident: space-track.org login identity :class:`~str` :param st_pass: space-track.org login password :class:`~str` :param out_dir: output dir to save TLE files :class:`~str` :param sleep: The amount of time to sleep between downloads. Default is 20 so as not to exceed the space-track download limit :param mock: For testing purposes. If True, will use a sample string to write test data to tle file :return: - tle file - saved to output directory """ if st_ident is not None and st_pass is not None: st = SpaceTrackClient(identity=st_ident, password=st_pass) # make a TLE directory Path(out_dir).mkdir(parents=True, exist_ok=True) print("Starting TLE download") print("Grab a coffee, this may take a while") for sat_name, sat_id in norad_ids.items(): print( f"downloading tle for {sat_name} satellite [{sat_id}] from space-tracks.org" ) if mock is True: data = "Hello!" else: data = st.tle( iter_lines=True, norad_cat_id=sat_id, orderby="epoch asc", epoch=f"{start_date}--{stop_date}", format="tle", ) with open(f"{out_dir}/{sat_id}.txt", "w") as fp: for line in data: fp.write(line + "\n") # Sleep to limit downloads to 200 TLEs per hour time.sleep(sleep) else: print( "Space-Track.org credentials not provided. Make an account before downloading TLEs" )