Beispiel #1
0
 def __init__(self,
              dirname: str = "data",
              ephemerides: str = "de441") -> None:
     self.load = Loader(dirname)
     self._ephName = ephemerides
     if not self._ephName.endswith(".bsp"):
         self._ephName += ".bsp"
Beispiel #2
0
def main():
    # Set up and hide tkinter root window
    root = tk.Tk()
    root.withdraw()

    file_path = filedialog.askopenfilename()
    if not path.exists(file_path):
        print("Error - no such file")
        quit()

    root.destroy()

    # Load earth position from ephemeris data
    sfLoader = Loader('resources')
    ephemeris = sfLoader('de421.bsp')
    earth = ephemeris['earth']

    # Setup timescale for calculating ground track
    ts = sfLoader.timescale()
    now = datetime.utcnow()
    steps = np.arange(0, 180, 1)
    time = ts.utc(now.year, now.month, now.day, now.hour, steps)

    # Load satellite data from tle file
    satellites = sfLoader.tle_file(file_path)

    # Set up plot
    plt.figure()
    img = plt.imread('resources/map.png')
    plt.imshow(img, extent=[-180, 180, -90, 90])

    for sat in satellites:
        _calculateGroundTrack(earth, sat, time)

    plt.show()
Beispiel #3
0
def _convert_radec_to_altaz(ra, dec, lon, lat, height, time):
    """Convert a single position.

    This is done for easy code sharing with other tools.
    Skyfield does support arrays of positions.
    """
    load = Loader('.')
    # Skyfield uses FTP URLs, but FTP doesn't work on Github Actions so
    # we use alternative HTTP URLs.
    load.urls['finals2000A.all'] = 'https://datacenter.iers.org/data/9/'
    load.urls['.bsp'] = [
        ('*.bsp',
         'https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/')
    ]

    radec = Star(ra=Angle(degrees=ra), dec=Angle(degrees=dec))

    earth = load(EPHEMERIS)['earth']
    location = earth + wgs84.latlon(longitude_degrees=lon,
                                    latitude_degrees=lat,
                                    elevation_m=height * 1000.0)

    ts = load.timescale(builtin=False)
    with load.open('finals2000A.all') as f:
        finals_data = iers.parse_x_y_dut1_from_finals_all(f)
    iers.install_polar_motion_table(ts, finals_data)
    obstime = ts.from_astropy(Time(time, scale='utc'))

    alt, az, _ = location.at(obstime).observe(radec).apparent().altaz(
        pressure_mbar=0)

    return dict(az=az.degrees, alt=alt.degrees)
Beispiel #4
0
def skyfield_ephem(load_path=None, parallax_correction=False, utc=None):
    '''Returns skyfield objects used for doing solar planning and conversion.
    
    Optional keywords:
    
    load_path: Directory location where the bsp files are stored. Defaults to current
    working directory if None.
    
    parallax_corection: Download the latest NuSTAR TLE file and apply the parallax
    correction based on NuSTAR's position in its orbit. Defaults to "False". If "True"
    then uses the nustar_pysolar.io TLE methods to parse the closest TLE entry in the
    NuSTAR database.
    
    If you set parallax_correction=True then 
    
    Returns:
    
    observer, sun, ts
    
    The first two are Skyfield objects. "observer" is either geocentric or the NuSTAR
    location based on the TLE.
    
    "ts" is the Skyfield time object.
    
    '''




    # Initialize Skyfield ephemeris tools.
    from skyfield.api import EarthSatellite, Loader
    from astropy.time import Time
    import sunpy.sun

    if load_path is None:
        load_path = './'
        load=Loader(load_path)
    else:
        load=Loader(load_path)
            
    ts = load.timescale()
    planets = load('de436.bsp')
    earth = planets['Earth']
    sun = planets['Sun']


    if parallax_correction is False:
        observer = earth
    else:
        assert (not utc is None),"Must set UTC when using parallax correction!"            
        import nustar_pysolar.io as io
        tlefile = io.download_tle(outdir=load_path)
        mindt, line1, line2 = io.get_epoch_tle(utc, tlefile)
        nustar = EarthSatellite(line1, line2)
        observer = earth + nustar

    ts = load.timescale()


    return observer, sun, ts
Beispiel #5
0
def load_skyfield_data():
    """Load data files used in Skyfield. This will download files from the
    internet if they haven't been downloaded before.

    Skyfield downloads files to the current directory by default, which is not
    ideal. Here we abuse astropy and use its cache directory to cache the data
    files per-user. If we start downloading files in other places in pwkit we
    should maybe make this system more generic. And the dep on astropy is not
    at all necessary.

    Skyfield will print out a progress bar as it downloads things.

    Returns ``(planets, ts)``, the standard Skyfield ephemeris and timescale
    data files.

    """
    import os.path
    from astropy.config import paths
    from skyfield.api import Loader

    cache_dir = os.path.join(paths.get_cache_dir(), 'pwkit')
    loader = Loader(cache_dir)
    planets = loader('de421.bsp')
    ts = loader.timescale()
    return planets, ts
Beispiel #6
0
def loadAstronomyData():
    if g.astroDataLoaded:
        return

    try:
        from skyfield.api import Loader
        load = Loader(getUserDataPath(), verbose=False)
        g.timescale = load.timescale(builtin=False)
    except OSError:
        print(
            'Downloading the astronomy data failed.  Some astronomical functions will not be available.',
            file=sys.stderr)
        g.astroDataLoaded = True
        g.astroDataAvailable = False
        return

    try:
        g.ephemeris = load('de421.bsp')
    except OSError:
        print(
            'Downloading the astronomy data failed.  Some astronomical functions will not be available.',
            file=sys.stderr)
        g.astroDataLoaded = True
        g.astroDataAvailable = False
        return

    g.astroDataLoaded = True
    g.astroDataAvailable = True

    return
Beispiel #7
0
 def handle(self, *args, **options):
     load = Loader(settings.EPHEM_DIR)
     load('de405.bsp')
     load.timescale()
     self.stdout.write(
         self.style.SUCCESS(
             f'Successfully downloaded ephemeris files to {settings.EPHEM_DIR}!'
         ))
Beispiel #8
0
 def __init__(self, intercept_df=None, sat_df=None):
     '''
     Initialize
     '''
     load = Loader('./data')
     data = load('de421.bsp')
     self.timescale = load.timescale()
     self.intercept_df = intercept_df
     self.sat_df = sat_df
Beispiel #9
0
def generatePlot():
    print('Generating Plot')

    df = pandas.read_csv('../Data/tempCSV.csv')

    objectID = df.values[1][0][2:7]
    L1 = df.values[1][0]
    L2 = df.values[2][0]

    load = Loader(
        '~/Documents/fishing/SkyData')  # avoids multiple copies of large files
    ts = load.timescale()

    data = load('de421.bsp')
    earth = data['earth']
    ts = load.timescale()

    minutes = np.arange(60. * 24)  # seven days
    time = ts.utc(today.year, today.month, today.day, 0,
                  minutes)  # start June 1, 2018

    ISS = EarthSatellite(L1, L2)

    subpoint = ISS.at(time).subpoint()

    lon = subpoint.longitude.degrees
    lat = subpoint.latitude.degrees
    breaks = np.where(np.abs(lon[1:] - lon[:-1]) > 30)  #don't plot wrap-around

    lon, lat = lon[:-1], lat[:-1]
    lon[breaks] = np.nan

    my_tweet = 'Ground Track of NORAD ID #' + str(
        objectID) + ' for the next 24 hours'

    fig1, ax1 = plt.subplots()

    earth = mpimg.imread('../Figures/earth.tif')
    earth = mpimg.imread(earthImg)
    ax1.imshow(earth)

    ax1.plot(10800 * (lon / 360 + .5), 5400 * (lat / 180 + 0.5))
    plt.axis('off')
    imgFile = "../Figures/latestGroundTrack.png"

    plt.savefig(imgFile, dpi=300, bbox_inches='tight', pad_inches=0)

    fig2, ax2 = plt.subplots()
    ax2.plot(lon / 360 + .5, lat / 180 - .5)

    print(lat[0])
    if (math.isnan(lat[0])):
        exitFlag = False
    else:
        exitFlag = True

    return exitFlag, my_tweet
Beispiel #10
0
 def handle(self, *args, **options):
     load = Loader(settings.EPHEM_DIR)
     load("de405.bsp")
     load.timescale(builtin=True)
     self.stdout.write(
         self.style.SUCCESS(
             f"Successfully downloaded ephemeris files to {settings.EPHEM_DIR}!"
         )
     )
Beispiel #11
0
    def _load_sky_data(self, tmpdir):
        """
        Load the primary input data for skyfield.

        This requires a download for the first one, or
        the inclusion of the data files.
        """
        load = Loader(tmpdir)
        self._planets = load("de421.bsp")
        self._ts = load.timescale()
Beispiel #12
0
    def __init__(self):

        self._tokenInEnglish = {
            '_tok_1': 'SWX ADVISORY line',
            'test': 'STATUS: TEST',
            'exercise': 'STATUS: EXER',
            'dtg': 'Date/Time Group',
            'centre': 'Issuing SWX Centre',
            'advnum': 'YYYY/nnnn',
            'prevadvsry': 'Previous Advisory YYYY/nnnn',
            'phenomenon': 'SWX Hazard(s)',
            'init': '(OBS|FCST) SWX',
            'timestamp': 'DD/HHmmZ Group',
            'noos': 'NO SWX EXP',
            'notavail': 'NOT AVBL',
            'daylight': 'DAY(LIGHT)? SIDE',
            'lat_band': '(H|M)(N|S)H',
            'equator': 'EQ(N|S)',
            'longitudes': '(E|W)nnn[nn]-(E|W)nnn[nn]',
            'box': 'lat/long bounding box',
            'fltlvls': 'ABV FLnnn|FLnnn-nnn',
            'fcsthr': 'FCST SWX +nn HR',
            'rmk': 'RMK:',
            'nextdtg': 'Next advisory issuance date/time',
            'noadvisory': 'NO FURTHER ADVISORIES'
        }

        self.header = re.compile(r'.*(?=SWX ADVISORY)', re.DOTALL)

        setattr(self, 'lat_band', self.add_region)
        setattr(self, 'point', self.add_region)
        setattr(self, 'equator', self.add_region)

        self._Logger = logging.getLogger(__name__)
        #
        # Preparing Skyfield
        try:
            load = Loader(os.path.join(os.path.dirname(__file__), '../data'),
                          verbose=False)
            self._ts = load.timescale()
            #
            # Open NAIF/JPL/NASA SPICE Kernel
            planets = load('de421.bsp')
            self._Gaia = planets['earth']
            self._Helios = planets['sun']

        except Exception:
            self._Logger.exception(
                'Unable to load/initialize Skyfield Module.')
            raise

        return super(Decoder, self).__init__()
    def __init__(self, parent=None, view=None):
        """
        Arguments:
        parent -- Qt widget that is parent to this widget.
        view -- reference to mpl canvas class
        """
        super(RemoteSensingControlWidget, self).__init__(parent)
        self.setupUi(self)

        self.view = view
        self.load_bsp = Loader(skyfield_data.get_skyfield_data_path(),
                               verbose=False)

        self.planets = self.load_bsp('de421.bsp')
        self.timescale = self.load_bsp.timescale(builtin=True)

        button = self.btTangentsColour
        palette = QtGui.QPalette(button.palette())
        colour = QtGui.QColor()
        colour.setRgbF(1, 0, 0, 1)
        palette.setColor(QtGui.QPalette.Button, colour)
        button.setPalette(palette)

        self.dsbTangentHeight.setValue(10.)
        self.dsbObsAngleAzimuth.setValue(90.)
        self.dsbObsAngleElevation.setValue(-1.0)

        # update plot on every value change
        self.cbDrawTangents.stateChanged.connect(self.update_settings)
        self.cbShowSolarAngle.stateChanged.connect(self.update_settings)
        self.btTangentsColour.clicked.connect(self.set_tangentpoint_colour)
        self.dsbTangentHeight.valueChanged.connect(self.update_settings)
        self.dsbObsAngleAzimuth.valueChanged.connect(self.update_settings)
        self.dsbObsAngleElevation.valueChanged.connect(self.update_settings)
        self.cbSolarBody.currentIndexChanged.connect(self.update_settings)
        self.cbSolarAngleType.currentIndexChanged.connect(self.update_settings)
        self.lbSolarCmap.setText(
            "Solar angle colours, dark to light: reds (0-15), violets (15-45), greens (45-180)"
        )
        self.solar_cmap = ListedColormap([(1.00, 0.00, 0.00, 1.0),
                                          (1.00, 0.45, 0.00, 1.0),
                                          (1.00, 0.75, 0.00, 1.0),
                                          (0.47, 0.10, 1.00, 1.0),
                                          (0.72, 0.38, 1.00, 1.0),
                                          (1.00, 0.55, 1.00, 1.0),
                                          (0.00, 0.70, 0.00, 1.0),
                                          (0.33, 0.85, 0.33, 1.0),
                                          (0.65, 1.00, 0.65, 1.0)])
        self.solar_norm = BoundaryNorm(
            [0, 5, 10, 15, 25, 35, 45, 90, 135, 180], self.solar_cmap.N)

        self.update_settings()
Beispiel #14
0
def params_newton_angle():
    """
    Session-scoped fixture to "cache" the newton angle func parameters
    """
    load = Loader(get_skyfield_data_path())
    ts = load.timescale()
    planets = load('de421.bsp')
    earth = planets['earth']
    sun = planets['sun']

    jan_first = ts.utc(date(2021, 1, 1))
    t0 = ts.tt_jd(jan_first.tt).tt
    return t0, ts, earth, sun
def calculate_equinoxes(year, timezone='UTC'):
    """ calculate equinox with time zone """
    tz = pytz.timezone(timezone)

    load = Loader(get_skyfield_data_path())
    ts = load.timescale()
    planets = load('de421.bsp')

    t0 = ts.utc(year, 1, 1)
    t1 = ts.utc(year, 12, 31)
    datetimes, _ = almanac.find_discrete(t0, t1, almanac.seasons(planets))
    vernal_equinox = datetimes[0].astimezone(tz).date()
    autumn_equinox = datetimes[2].astimezone(tz).date()
    return vernal_equinox, autumn_equinox
Beispiel #16
0
def init_ephem(orbits, load_path=None, show=False, parallax_correction=False):
    '''Initialize Skyfield ephemeris for Jupiter BSP file
    
    Takes output of io.parse_occ as input.
    
    Requires Astropy and SkyField
    
    Optional:
    
    load_path (where the bsp and SkyField data files are found.
    
    parllax_correction (apply the parallax correction from NuSTAR's orbit).
        Downloads the latest TLE archive from the NuSTAR SOC.
    
    
    Returns:
    observer, jupiter, ts
    
    The first two are Skyfield objects. The third is the Skyfield time series
    object.
        
    '''
    from skyfield.api import Loader, EarthSatellite
    from astropy.time import Time

    if load_path is None:
        load_path = './'
        load = Loader(load_path)
    else:
        load = Loader(load_path)

    planets = load('jup310.bsp')
    jupiter, earth = planets['jupiter'], planets['earth']
    ts = load.timescale()

    if parallax_correction is False:
        observer = earth
    else:
        import nustar_planning.io as io
        start_date = orbits.loc[0, 'visible']

        utc = Time(start_date)
        tlefile = io.download_tle(outdir=load_path)
        mindt, line1, line2 = io.get_epoch_tle(utc, tlefile)
        nustar = EarthSatellite(line1, line2)
        observer = earth + nustar

    return observer, jupiter, ts
Beispiel #17
0
class StationList:

    def __init__(self):
        self._loader = Loader(DATA_PATH)
        self.update()

    def update(self):
        self._tles = {}
        for es in self._loader.tle_file(URL_TLE, True):
            self._tles[es.name] = es
        self._ts = self._loader.timescale()
        self._stations = self._tles.keys()
        LOGGER.info("Update StationList, found "+str(len(self._stations))+" items")
    
    def list(self):
        return self._stations

    def getStation(self, station, from_position):
        return Station(self._tles[station],self._ts, from_position)
def get_jupiter_radec(orbits, outfile=None):

    if outfile is not None:
        f = open(outfile, 'w')

    from skyfield.api import Loader
    load = Loader('../data')

    ts = load.timescale()
    planets = load('jup310.bsp')
    jupiter, earth = planets['jupiter'], planets['earth']

    for ind in range(len(orbits)):
        tstart = orbits.loc[ind, 'visible']
        tend = orbits.loc[ind, 'occulted']
        print()
        on_time = (tend - tstart).total_seconds()

        point_time = tstart + 0.5 * (tend - tstart)

        astro_time = Time(point_time)

        t = ts.from_astropy(astro_time)

        astrometric = earth.at(t).observe(jupiter)
        ra, dec, distance = astrometric.radec()
        radeg = ra.to(u.deg)
        decdeg = dec.to(u.deg)

        dt += on_time

        print(tstart.isoformat() + ' {}  {}'.format(radeg.value, decdeg.value))

        if outfile is not None:
            f.write(tstart.isoformat() +
                    ' {}  {}'.format(radeg.value, decdeg.value) + '\n')

    if outfile is not None:
        f.close()

    print('Total accumualted time {}'.format(dt))
Beispiel #19
0
def load_ephemerides(
        cache_dir: str = None,
        ephemerides_file: str = EPHEMERIDES_FILE
) -> skyfield.jpllib.SpiceKernel:
    """Load the DE421 ephemeris.

    Note that the first time this function is called, it will need to download
    the DE421 epehemeris file from JPL.  This file is 17 MB, but the server is
    a little slow, so it can take about 10 seconds.  Subsequently, this data
    will be cached in `$HOME/.cache/radecbot` and loading will be fast.

    """
    if cache_dir is None:
        cache_dir = os.path.join(os.getenv('HOME'), '.cache/radecbot')

    loader = Loader(cache_dir)

    filename = os.path.join(cache_dir, ephemerides_file)
    if not os.path.exists(filename):
        url = loader.build_url(ephemerides_file)
        loader.download(url, filename)

    if not os.path.exists(loader.path_to(ephemerides_file)):
        raise FileNotFoundError(
            f'Ephemerides file {loader.path_to(ephemerides_file)} not found! '
            f'Did the download fail?')

    return loader(ephemerides_file)
Beispiel #20
0
def skyfield_ephem(load_path=None, parallax_correction=False, utc=None):
    '''Returns skyfield objects used for doing solar planning and conversion.
    
    Optional keywords:
    
    load_path: Directory location where the bsp files are stored. Defaults to current
    working directory if None.
    
    parallax_corection: Download the latest NuSTAR TLE file and apply the parallax
    correction based on NuSTAR's position in its orbit. Defaults to "False". If "True"
    then uses the nustar_pysolar.io TLE methods to parse the closest TLE entry in the
    NuSTAR database.
    
    If you set parallax_correction=True then 
    
    Returns:
    
    observer, sun, ts
    
    The first two are Skyfield objects. "observer" is either geocentric or the NuSTAR
    location based on the TLE.
    
    "ts" is the Skyfield time object.
    
    '''

    # Initialize Skyfield ephemeris tools.
    from skyfield.api import EarthSatellite, Loader
    from astropy.time import Time
    #   Not actually used? So just comment out, and so no sunpy v1 issue
    #     import sunpy.sun

    if load_path is None:
        load_path = './'
        load = Loader(load_path)
    else:
        load = Loader(load_path)

    ts = load.timescale()
    planets = load('de436.bsp')
    earth = planets['Earth']
    sun = planets['Sun']

    if parallax_correction is False:
        observer = earth
    else:
        assert (
            not utc is None), "Must set UTC when using parallax correction!"
        import nustar_pysolar.io as io
        tlefile = io.download_tle(outdir=load_path)
        mindt, line1, line2 = io.get_epoch_tle(utc, tlefile)
        nustar = EarthSatellite(line1, line2)
        observer = earth + nustar

    ts = load.timescale()

    return observer, sun, ts
Beispiel #21
0
def is_light():
    """is_light returns True if the sun is up and False otherwise"""
    # load in data directory to avoid redownloading
    loader = Loader('~/skyfield_data')
    ts = loader.timescale()
    e = loader('de421.bsp')

    # set current location (melbourne does not appear in the default list)
    melbourne = api.Topos('37.951910 S', '145.152080 E')
    # get current time in UTC format
    now = datetime.datetime.utcnow()
    now = now.replace(tzinfo=utc)
    # set the interval for now and 24 hours from now
    t0 = ts.utc(now)
    t1 = ts.utc(now + timedelta(hours=24))

    # find the times and types of event (sunrise/sunset)
    t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(e, melbourne))

    #y[0] = True for sunrise (which means it is currently dark)

    light = not y[0]

    return light
Beispiel #22
0
class RemoteSensingControlWidget(QtWidgets.QWidget,
                                 ui.Ui_RemoteSensingDockWidget):
    """This class implements the remote sensing functionality as dockable widget.
    """
    def __init__(self, parent=None, view=None):
        """
        Arguments:
        parent -- Qt widget that is parent to this widget.
        view -- reference to mpl canvas class
        """
        super(RemoteSensingControlWidget, self).__init__(parent)
        self.setupUi(self)

        self.view = view
        self.load = Loader(MSS_CONFIG_PATH, verbose=False)
        self.planets = self.load('de421.bsp')
        self.timescale = self.load.timescale(builtin=True)
        # don't download files, use shipped files

        button = self.btTangentsColour
        palette = QtGui.QPalette(button.palette())
        colour = QtGui.QColor()
        colour.setRgbF(1, 0, 0, 1)
        palette.setColor(QtGui.QPalette.Button, colour)
        button.setPalette(palette)

        self.dsbTangentHeight.setValue(10.)
        self.dsbObsAngleAzimuth.setValue(90.)
        self.dsbObsAngleElevation.setValue(-1.0)

        # update plot on every value change
        self.cbDrawTangents.stateChanged.connect(self.update_settings)
        self.cbShowSolarAngle.stateChanged.connect(self.update_settings)
        self.btTangentsColour.clicked.connect(self.set_tangentpoint_colour)
        self.dsbTangentHeight.valueChanged.connect(self.update_settings)
        self.dsbObsAngleAzimuth.valueChanged.connect(self.update_settings)
        self.dsbObsAngleElevation.valueChanged.connect(self.update_settings)
        self.cbSolarBody.currentIndexChanged.connect(self.update_settings)
        self.cbSolarAngleType.currentIndexChanged.connect(self.update_settings)
        self.lbSolarCmap.setText(
            "Solar angle colours, dark to light: reds (0-15), violets (15-45), greens (45-180)"
        )
        self.solar_cmap = ListedColormap([(1.00, 0.00, 0.00, 1.0),
                                          (1.00, 0.45, 0.00, 1.0),
                                          (1.00, 0.75, 0.00, 1.0),
                                          (0.47, 0.10, 1.00, 1.0),
                                          (0.72, 0.38, 1.00, 1.0),
                                          (1.00, 0.55, 1.00, 1.0),
                                          (0.00, 0.70, 0.00, 1.0),
                                          (0.33, 0.85, 0.33, 1.0),
                                          (0.65, 1.00, 0.65, 1.0)])
        self.solar_norm = BoundaryNorm(
            [0, 5, 10, 15, 25, 35, 45, 90, 135, 180], self.solar_cmap.N)

        self.update_settings()

    @staticmethod
    def compute_view_angles(lon0, lat0, h0, lon1, lat1, h1, obs_azi, obs_ele):
        mlat = ((lat0 + lat1) / 2.)
        lon0 *= np.cos(np.deg2rad(mlat))
        lon1 *= np.cos(np.deg2rad(mlat))
        dlon = lon1 - lon0
        dlat = lat1 - lat0
        obs_azi_p = fix_angle(obs_azi + np.rad2deg(np.arctan2(dlon, dlat)))
        return obs_azi_p, obs_ele

    def compute_body_angle(self, body, jsec, lon, lat):
        t = self.timescale.utc(jsec_to_datetime(jsec).replace(tzinfo=utc))
        loc = self.planets["earth"] + Topos(lat, lon)
        astrometric = loc.at(t).observe(self.planets[body])
        alt, az, d = astrometric.apparent().altaz()
        return az.degrees, alt.degrees

    def update_settings(self):
        """
        Updates settings in TopView and triggers a redraw.
        """
        settings = {
            "reference": self,
            "draw_tangents": self.cbDrawTangents.isChecked(),
        }
        if self.cbShowSolarAngle.isChecked():
            settings["show_solar_angle"] = self.cbSolarAngleType.currentText(
            ), self.cbSolarBody.currentText()
        else:
            settings["show_solar_angle"] = None

        self.view.set_remote_sensing_appearance(settings)

    def set_tangentpoint_colour(self):
        """Slot for the colour buttons: Opens a QColorDialog and sets the
           new button face colour.
        """
        button = self.btTangentsColour
        palette = QtGui.QPalette(button.palette())
        colour = palette.color(QtGui.QPalette.Button)
        colour = QtWidgets.QColorDialog.getColor(colour)
        if colour.isValid():
            palette.setColor(QtGui.QPalette.Button, colour)
            button.setPalette(palette)
        self.update_settings()

    def compute_tangent_lines(self, bmap, wp_vertices, wp_heights):
        """
        Computes Tangent points of limb sounders aboard the aircraft

        Args:
            bmap: Projection of TopView
            wp_vertices: waypoints of the flight path
            wp_heights: altitude of the waypoints of flight path

        Returns: LineCollection of dotted lines at tangent point locations
        """
        x, y = list(zip(*wp_vertices))
        wp_lons, wp_lats = bmap(x, y, inverse=True)
        fine_lines = [
            bmap.gcpoints2(wp_lons[i],
                           wp_lats[i],
                           wp_lons[i + 1],
                           wp_lats[i + 1],
                           del_s=10.,
                           map_coords=False) for i in range(len(wp_lons) - 1)
        ]
        line_heights = [
            np.linspace(wp_heights[i],
                        wp_heights[i + 1],
                        num=len(fine_lines[i][0]))
            for i in range(len(fine_lines))
        ]
        # fine_lines = list of tuples with x-list and y-list for each segment
        tplines = [
            self.tangent_point_coordinates(
                fine_lines[i][0],
                fine_lines[i][1],
                line_heights[i],
                cut_height=self.dsbTangentHeight.value())
            for i in range(len(fine_lines))
        ]
        dirlines = self.direction_coordinates(wp_lons, wp_lats)
        lines = tplines + dirlines
        for i, line in enumerate(lines):
            for j, (lon, lat) in enumerate(line):
                line[j] = bmap(lon, lat)
            lines[i] = line
        return LineCollection(
            lines,
            colors=QtGui.QPalette(self.btTangentsColour.palette()).color(
                QtGui.QPalette.Button).getRgbF(),
            zorder=2,
            animated=True,
            linewidth=3,
            linestyles=[':'] * len(tplines) + ['-'] * len(dirlines))

    def compute_solar_lines(self, bmap, wp_vertices, wp_heights, wp_times,
                            solartype):
        """
        Computes coloured overlay over the flight path that indicates
        the danger of looking into the sun with a limb sounder aboard
        the aircraft.

        Args:
            bmap: Projection of TopView
            wp_vertices: waypoints of the flight path
            wp_heights: altitude of the waypoints of flight path

        Returns: LineCollection of coloured lines according to the
                 angular distance between viewing direction and solar
                 angle
        """
        # calculate distances and times
        body, difftype = solartype

        times = [datetime_to_jsec(_wp_time) for _wp_time in wp_times]
        x, y = list(zip(*wp_vertices))
        wp_lons, wp_lats = bmap(x, y, inverse=True)

        fine_lines = [
            bmap.gcpoints2(wp_lons[i],
                           wp_lats[i],
                           wp_lons[i + 1],
                           wp_lats[i + 1],
                           map_coords=False) for i in range(len(wp_lons) - 1)
        ]
        line_heights = [
            np.linspace(wp_heights[i],
                        wp_heights[i + 1],
                        num=len(fine_lines[i][0]))
            for i in range(len(fine_lines))
        ]
        line_times = [
            np.linspace(times[i], times[i + 1], num=len(fine_lines[i][0]))
            for i in range(len(fine_lines))
        ]
        # fine_lines = list of tuples with x-list and y-list for each segment
        # lines = list of tuples with lon-list and lat-list for each segment
        heights = []
        times = []
        for i in range(len(fine_lines) - 1):
            heights.extend(line_heights[i][:-1])
            times.extend(line_times[i][:-1])
        heights.extend(line_heights[-1])
        times.extend(line_times[-1])
        solar_x = []
        solar_y = []
        for i in range(len(fine_lines) - 1):
            solar_x.extend(fine_lines[i][0][:-1])
            solar_y.extend(fine_lines[i][1][:-1])
        solar_x.extend(fine_lines[-1][0])
        solar_y.extend(fine_lines[-1][1])
        points = []
        old_wp = None
        total_distance = 0
        for i, (lon, lat) in enumerate(zip(solar_x, solar_y)):
            points.append([[lon, lat]
                           ])  # append double-list for later concatenation
            if old_wp is not None:
                wp_dist = get_distance((old_wp[0], old_wp[1]),
                                       (lat, lon)) * 1000.
                total_distance += wp_dist
            old_wp = (lat, lon)
        vals = []
        for i in range(len(points) - 1):
            p0, p1 = points[i][0], points[i + 1][0]

            sol_azi, sol_ele = self.compute_body_angle(body, times[i], p0[0],
                                                       p0[1])
            obs_azi, obs_ele = self.compute_view_angles(
                p0[0], p0[1], heights[i], p1[0], p1[1], heights[i + 1],
                self.dsbObsAngleAzimuth.value(),
                self.dsbObsAngleElevation.value())
            if sol_azi < 0:
                sol_azi += 360
            if obs_azi < 0:
                obs_azi += 360
            rating = self.calc_view_rating(obs_azi, obs_ele, sol_azi, sol_ele,
                                           heights[i], difftype)
            vals.append(rating)

        # convert lon, lat to map points
        for i in range(len(points)):
            points[i][0][0], points[i][0][1] = bmap(points[i][0][0],
                                                    points[i][0][1])
        points = np.concatenate([points[:-1], points[1:]], axis=1)
        # plot
        solar_lines = LineCollection(points,
                                     cmap=self.solar_cmap,
                                     norm=self.solar_norm,
                                     zorder=2,
                                     linewidths=3,
                                     animated=True)
        solar_lines.set_array(np.array(vals))
        return solar_lines

    def tangent_point_coordinates(self,
                                  lon_lin,
                                  lat_lin,
                                  flight_alt=14,
                                  cut_height=12):
        """
        Computes coordinates of tangent points given coordinates of flight path.

        Args:
            lon_lin: longitudes of flight path
            lat_lin: latitudes of flight path
            flight_alt: altitude of aircraft (scalar or numpy array)
            cut_height: altitude of tangent points

        Returns: List of tuples of longitude/latitude coordinates

        """
        lins = list(zip(lon_lin[0:-1], lon_lin[1:], lat_lin[0:-1],
                        lat_lin[1:]))
        lins = [(x0 * np.cos(np.deg2rad(np.mean([y0, y1]))),
                 x1 * np.cos(np.deg2rad(np.mean([y0, y1]))), y0, y1)
                for x0, x1, y0, y1 in lins]

        direction = [(x1 - x0, y1 - y0) for x0, x1, y0, y1 in lins]
        direction = [(_x / np.hypot(_x, _y), _y / np.hypot(_x, _y))
                     for _x, _y in direction]
        los = [
            rotate_point(point, -self.dsbObsAngleAzimuth.value())
            for point in direction
        ]
        los.append(los[-1])

        if isinstance(flight_alt, (collections.abc.Sequence, np.ndarray)):
            dist = [(np.sqrt(
                max((EARTH_RADIUS + a)**2 -
                    (EARTH_RADIUS + cut_height)**2, 0)) / 110.)
                    for a in flight_alt[:-1]]
            dist.append(dist[-1])
        else:
            dist = (np.sqrt((EARTH_RADIUS + flight_alt)**2 -
                            (EARTH_RADIUS + cut_height)**2) / 110.)

        tp_dir = (np.array(los).T * dist).T

        tps = [(x0 + tp_x, y0 + tp_y, y0)
               for ((x0, x1, y0, y1), (tp_x, tp_y)) in zip(lins, tp_dir)]
        tps = [(x0 / np.cos(np.deg2rad(yp)), y0) for (x0, y0, yp) in tps]
        return tps

    def direction_coordinates(self, lon_lin, lat_lin):
        """
        Computes coordinates of tangent points given coordinates of flight path.

        Args:
            lon_lin: longitudes of flight path
            lat_lin: latitudes of flight path
            flight_alt: altitude of aircraft (scalar or numpy array)
            cut_height: altitude of tangent points

        Returns: List of tuples of longitude/latitude coordinates

        """
        lins = list(zip(lon_lin[0:-1], lon_lin[1:], lat_lin[0:-1],
                        lat_lin[1:]))
        lins = [(x0 * np.cos(np.deg2rad(np.mean([y0, y1]))),
                 x1 * np.cos(np.deg2rad(np.mean([y0, y1]))), y0, y1)
                for x0, x1, y0, y1 in lins]
        lens = [np.hypot(x1 - x0, y1 - y0) * 110. for x0, x1, y0, y1 in lins]
        lins = [_x for _x, _l in zip(lins, lens) if _l > 10]

        direction = [(0.5 * (x0 + x1), 0.5 * (y0 + y1), x1 - x0, y1 - y0)
                     for x0, x1, y0, y1 in lins]
        direction = [(_u, _v, _x / np.hypot(_x, _y), _y / np.hypot(_x, _y))
                     for _u, _v, _x, _y in direction]
        los = [
            rotate_point(point[2:], -self.dsbObsAngleAzimuth.value())
            for point in direction
        ]

        dist = 1.

        tp_dir = (np.array(los).T * dist).T

        tps = [(x0, y0, x0 + tp_x, y0 + tp_y)
               for ((x0, y0, _, _), (tp_x, tp_y)) in zip(direction, tp_dir)]
        tps = [[(x0 / np.cos(np.deg2rad(y0)), y0),
                (x1 / np.cos(np.deg2rad(y0)), y1)] for (x0, y0, x1, y1) in tps]
        return tps

    @staticmethod
    def calc_view_rating(obs_azi, obs_ele, sol_azi, sol_ele, height, difftype):
        """
        Calculates the angular distance between given directions under the
        condition that the sun is above the horizon.

        Args:
            obs_azi: observator azimuth angle
            obs_ele: observator elevation angle
            sol_azi: solar azimuth angle
            sol_ele: solar elevation angle
            height: altitude of observer

        Returns: angular distance or 180 degrees if sun is below horizon
        """
        delta_azi = obs_azi - sol_azi
        delta_ele = obs_ele - sol_ele
        if "horizon" in difftype:
            thresh = -np.rad2deg(
                np.arccos(EARTH_RADIUS / (height + EARTH_RADIUS))) - 3
            if sol_ele < thresh:
                delta_ele = 180

        if "azimuth" == difftype:
            return np.abs(obs_azi - sol_azi)
        elif "elevation" == difftype:
            return np.abs(obs_ele - sol_ele)
        else:
            return np.hypot(delta_azi, delta_ele)
Beispiel #23
0
import urllib.request
import xml.etree.ElementTree as ET
from datetime import datetime, timedelta, timezone
import dbf
import json
from skyfield import api
from skyfield import almanac
from skyfield.api import Loader
import math

ziptable = dbf.Table(modules.config['storage']['zipdbf'])
ziptable.open()
# Yeah, so this is slow and I need to figure out how to persist it.
zipidx = ziptable.create_index(lambda rec: rec.zcta5ce10)

loader = Loader(modules.config['storage']['skyfield'])
ts = loader.timescale()
ephem = loader('de421.bsp')


def actions():
    return {
        '': get,
        'get': get,
        'details': details,
        'astronomical': astronomical,
        'srss': astronomical,
    }


def with_zipcode(fcn):
Beispiel #24
0
def test_positions_skyfield(tmpdir):
    """
    Test positions against those generated by skyfield.
    """
    load = Loader(tmpdir)
    t = Time('1980-03-25 00:00')
    location = None

    # skyfield ephemeris
    try:
        planets = load('de421.bsp')
        ts = load.timescale()
    except OSError as e:
        if os.environ.get('CI', False) and 'timed out' in str(e):
            pytest.xfail('Timed out in CI')
        else:
            raise

    mercury, jupiter, moon = planets['mercury'], planets[
        'jupiter barycenter'], planets['moon']
    earth = planets['earth']

    skyfield_t = ts.from_astropy(t)

    if location is not None:
        earth = earth + Topos(latitude_degrees=location.lat.to_value(u.deg),
                              longitude_degrees=location.lon.to_value(u.deg),
                              elevation_m=location.height.to_value(u.m))

    skyfield_mercury = earth.at(skyfield_t).observe(mercury).apparent()
    skyfield_jupiter = earth.at(skyfield_t).observe(jupiter).apparent()
    skyfield_moon = earth.at(skyfield_t).observe(moon).apparent()

    if location is not None:
        frame = TETE(obstime=t, location=location)
    else:
        frame = TETE(obstime=t)

    ra, dec, dist = skyfield_mercury.radec(epoch='date')
    skyfield_mercury = SkyCoord(ra.to(u.deg),
                                dec.to(u.deg),
                                distance=dist.to(u.km),
                                frame=frame)
    ra, dec, dist = skyfield_jupiter.radec(epoch='date')
    skyfield_jupiter = SkyCoord(ra.to(u.deg),
                                dec.to(u.deg),
                                distance=dist.to(u.km),
                                frame=frame)
    ra, dec, dist = skyfield_moon.radec(epoch='date')
    skyfield_moon = SkyCoord(ra.to(u.deg),
                             dec.to(u.deg),
                             distance=dist.to(u.km),
                             frame=frame)

    # planet positions w.r.t true equator and equinox
    moon_astropy = get_moon(t, location, ephemeris='de430').transform_to(frame)
    mercury_astropy = get_body('mercury', t, location,
                               ephemeris='de430').transform_to(frame)
    jupiter_astropy = get_body('jupiter', t, location,
                               ephemeris='de430').transform_to(frame)

    assert (moon_astropy.separation(skyfield_moon) <
            skyfield_angular_separation_tolerance)
    assert (moon_astropy.separation_3d(skyfield_moon) <
            skyfield_separation_tolerance)

    assert (jupiter_astropy.separation(skyfield_jupiter) <
            skyfield_angular_separation_tolerance)
    assert (jupiter_astropy.separation_3d(skyfield_jupiter) <
            skyfield_separation_tolerance)

    assert (mercury_astropy.separation(skyfield_mercury) <
            skyfield_angular_separation_tolerance)
    assert (mercury_astropy.separation_3d(skyfield_mercury) <
            skyfield_separation_tolerance)
    planets.close()
Beispiel #25
0
from skyfield.api import Topos, Loader
load = Loader('./Skyfield-Data', expire=False, verbose=False)
planets = load('de423.bsp')
earth = planets['earth']
from astropy.constants import c
c = c.to(u.au / u.year)
GDEGENERATE = 0.2
SIGMA2_USE_ENERGY = 9


ts = load.timescale()

self.theta_x, self.theya_y, self.dtheta_x, self.dtheta_y = equatorial_to_tangent()

# Returns xyz position of ground-based observatory.
# Need to implement obscode! Hard-coded for DECam
def earth3d(self):
    t = ts.tt(jd=self.obsdate)
    earth += Topos('30.169 S', '70.804 W', elevation_m=2200)
    return earth.at(t).position.au * u.au

def kbo2d_linear(self):
    x_earth, y_earth, z_earth = earth3d()

    t_emit = self.obsdate - z_earth / c

    X = self.a + self.adot * t_emit - self.g * x_earth - self.gdot * (self.adot * t_emit**2 - self.g * x_earth * t_emit)
    Y = self.b + self.bdot * t_emit - self.g * y_earth - self.gdot * (self.bdot * t_emit**2 - self.g * y_earth * t_emit)

    dX = np.array([np.ones(nobs), t_emit, np.zeros(nobs), np.zeros(nobs),
                   -x_earth, self.g * x_earth * t_emit - self.adot * t_emit**2])
Beispiel #26
0
#!/usr/bin/env python

import os
import math
import pytz
import rospy

from datetime import datetime
from rosgraph_msgs.msg import Clock
from geometry_msgs.msg import Vector3
from skyfield.api import PlanetaryConstants, Loader, load

load = Loader(os.path.dirname(os.path.abspath(__file__)) + '/../include')

sim_time = 0
msg_timeout = 0.5
last_msg_time = 0.0

def sim_time_callback(data):
    global last_msg_time
    global sim_time
    last_msg_time = rospy.get_time()
    sim_time = data.clock.to_sec()

def run():
    rospy.init_node('sun_seeker_node', anonymous=True)
    rospy.Subscriber('/clock', Clock, sim_time_callback)

    pub = rospy.Publisher('/sun_seeker/vector', Vector3, queue_size=1)
    rate = rospy.Rate(0.1)
Beispiel #27
0
def get_loader():
    return Loader(CACHE_FOLDER)
Beispiel #28
0
from skyfield.api import Loader, Topos, Angle, EarthSatellite, Star
from skyfield.timelib import Time
from almanac2 import (meridian_transits, culminations, twilights,
                      risings_settings, seasons, moon_phases, apsides, nodes,
                      max_ecliptic_latitudes)
from almanac2 import (_ecliptic_lon_diff, _moon_ul_alt, _lha, _alt,
                      _satellite_alt, _ecliptic_lon, _linear_dist,
                      _ecliptic_lat)
from numpy import ndarray
from functools import partial

# Put your data directory here before running this file:
load = Loader(r'')

ts = load.timescale()
ephem = load('de430t.bsp')
earth = ephem['earth']
sun = ephem['sun']
moon = ephem['moon']
mars = ephem['mars barycenter']
venus = ephem['venus']

plain_greenwich = Topos(latitude='51.5 N', longitude='0 W')
greenwich = earth + plain_greenwich

iss_tle = """\
1 25544U 98067A   18161.85073725  .00003008  00000-0  52601-4 0  9993
2 25544  51.6418  50.3007 0003338 171.6979 280.7366 15.54163173117534
"""
ISS = EarthSatellite(*iss_tle.splitlines())
Beispiel #29
0
# v0.5.1: add attributes 'delta','r', 'phase_angle', 'elong'
#         'delta': geocentric distance
#         'r': barycentric distance
#         'phase_angle': phase angle in radian
#         'elong': solar elongation in radian
# v0.5.2: correct elong calculations
# v0.6: add propagate_lite, a faster, inaccurate version of propagate
# v0.6.1: change time to tt
##############################################################################

from __future__ import division
import numpy as np
from skyfield.api import Topos, Loader
from scipy.optimize import newton

load = Loader('./Skyfield-Data', expire=True)
planets = load('de423.bsp')


class propagate:
    """
    input Keplerian elements in the format of numpy arrays
    Units: au, radian, JD
      
    """
    def __init__(self, a, e, i, arg, node, M0, epoch, obs_date, helio=False):
        self.u_bary = 2.9630927492415936E-04  # standard gravitational parameter, GM, M is the mass of sun + all planets
        self.u_helio = 2.9591220828559093E-04  # GM, M is the mass of sun
        self.epsilon = 23.43929111 * np.pi / 180.  # obliquity
        if helio:
            self.a, self.e, self.i, self.arg, self.node, self.M0 = self.helio_to_bary(
    sun = ephemeris['sun']
    topos_at = (ephemeris['earth'] + topos).at

    def is_sun_up_at(t):
        """Return `True` if the sun has risen by time `t`."""
        t._nutation_angles = iau2000b(t.tt)
        return topos_at(t).observe(
            sun).apparent().altaz()[0].degrees > -degrees

    is_sun_up_at.rough_period = 0.5  # twice a day
    return is_sun_up_at


from skyfield import api
from skyfield.api import Loader
load = Loader('~/sqm-in-a-box/skyfield/skyfield-data/')

ts = load.timescale()
planets = load('de421.bsp')

from skyfield import almanac

loc = api.Topos(latitude, longitude, elevation_m=elevation)

t0 = ts.utc(datetime.now(tz))
t1 = ts.utc(tz.normalize(datetime.now(tz) + timedelta(1)))

#center_time, center_up = almanac.find_discrete(t0, t1, daylength(planets, loc, DAYLENGTH_CENTER_HORIZON))
#print('Sunrise Sunset center of sun is even with horizon:')
#print(center_time.utc_iso(), center_up)
    # Total rotation of each observation from the beginning of the night
    rot_tot = [
        f.integral(field_rot["delta_t"][0], i) for i in field_rot["delta_t"]
    ]
    field_rot["rot_tot"] = rot_tot

    for i, file in enumerate(f_names):
        rot_image(file=file, ini_angle=-70, angle=rot_tot[i], border=False)

    return field_rot


if __name__ == "__main__":

    # Download Ephemerides & timescale files
    load = Loader("ephemerides")
    planets = load("de421.bsp")
    ts = load.timescale()

    # Solar System Ephemerides
    sun = planets["sun"]
    mercury = planets["mercury"]
    venus = planets["venus"]
    mars = planets["mars"]
    earth = planets["earth"]
    moon = planets["moon"]
    jupiter = planets["jupiter barycenter"]
    saturn = planets["saturn barycenter"]
    uranus = planets["uranus barycenter"]
    neptune = planets["neptune barycenter"]
    pluto = planets["pluto barycenter"]