예제 #1
0
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()
예제 #2
0
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'
예제 #3
0
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()
예제 #4
0
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
예제 #5
0
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')
예제 #6
0
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
예제 #7
0
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) 
예제 #8
0
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)
예제 #9
0
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
예제 #10
0
    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)
예제 #11
0
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())
예제 #12
0
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]
예제 #13
0
 def __init__(self):
     """
     Connects user to Space-Track account
     """
     self.client = SpaceTrackClient(identity=UN,
                                    password=self._request_access())
예제 #14
0
    # 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)
예제 #15
0
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
예제 #17
0
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
예제 #18
0
파일: tle.py 프로젝트: jblake95/pyTLE
 def __init__(self):
     un, pw = self.requestAccess()
     self.username = un
     self.password = pw
     self.client = SpaceTrackClient(identity=un, password=pw)
예제 #19
0
파일: tle.py 프로젝트: jblake95/pyTLE
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
예제 #20
0
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'
예제 #21
0
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')

예제 #22
0
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
예제 #23
0
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
예제 #24
0
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)
예제 #25
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)
예제 #26
0
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'
예제 #27
0
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
예제 #28
0
#!/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()
예제 #29
0
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
예제 #30
0
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')
예제 #31
0
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()
예제 #32
0
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'
예제 #33
0
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
예제 #34
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"
        )