def test_expiration_distant_future(mocked_exp):
    mocked_exp.return_value = {
        'de421.bsp': date.today() + timedelta(days=10000)
    }
    with mock.patch('warnings.warn') as mocked_warn:
        get_skyfield_data_path()
    assert mocked_warn.call_count == 0
def test_expiration_yesterday(mocked_exp):
    mocked_exp.return_value = {'de421.bsp': date.today() - timedelta(days=1)}
    with mock.patch('warnings.warn') as mocked_warn:
        get_skyfield_data_path()
    assert mocked_warn.call_count == 1
    message = mocked_warn.call_args[0][0]
    assert "The file de421.bsp has expired." in message
def test_expiration_custom_limit(mocked_exp):
    # It expires in 20 days
    mocked_exp.return_value = {'de421.bsp': date.today() + timedelta(days=20)}
    with mock.patch('warnings.warn') as mocked_warn:
        # Limit is 40 days, the limit is reached
        get_skyfield_data_path(expiration_limit=40)
    assert mocked_warn.call_count == 1
    message = mocked_warn.call_args[0][0]
    assert "The file de421.bsp would expire in less than 40 days." in message

    with mock.patch('warnings.warn') as mocked_warn:
        # Limit is 15 days, the limit is not reached
        get_skyfield_data_path(expiration_limit=15)
    assert mocked_warn.call_count == 0
예제 #4
0
    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()
예제 #5
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
예제 #6
0
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
def test_wrong_custom_expiration_limit_get_path():
    with pytest.raises(ValueError):
        get_skyfield_data_path(expiration_limit=-1)

    with pytest.raises(ValueError):
        get_skyfield_data_path(expiration_limit=None)

    with pytest.raises(ValueError):
        get_skyfield_data_path(expiration_limit="bad")
def test_no_expiration(mocked_exp):
    mocked_exp.return_value = {}
    with mock.patch('warnings.warn') as mocked_warn:
        get_skyfield_data_path()
    assert mocked_warn.call_count == 0
예제 #9
0
def test_load_finals_builtins(tmpdir):
    load = Loader(get_skyfield_data_path())
    with mock.patch('skyfield.iokit.download') as download_patched:
        load.timescale(builtin=True)
    assert download_patched.call_count == 0
예제 #10
0
def test_load_using_cache_de421(download_patched):
    load = Loader(get_skyfield_data_path())
    load('de421.bsp')
    assert download_patched.call_count == 0
예제 #11
0
def solar_term(year, degrees, timezone='UTC'):
    """
    Returns the date of the solar term for the given longitude
    and the given year.

    Solar terms are used for Chinese and Taiwanese holidays
    (e.g. Qingming Festival in Taiwan).

    More information:
    - https://en.wikipedia.org/wiki/Solar_term
    - https://en.wikipedia.org/wiki/Qingming

    This function is adapted from the following topic:
    https://answers.launchpad.net/pyephem/+question/110832
    """
    # Target angle as radians
    target_angle = radians(degrees)

    load = Loader(get_skyfield_data_path())
    planets = load('de421.bsp')
    earth = planets['earth']
    sun = planets['sun']
    ts = load.timescale()
    tz = pytz.timezone(timezone)

    jan_first = ts.utc(date(year, 1, 1))
    current_longitude = get_current_longitude(jan_first, earth, sun)

    # Find approximately the right time of year.
    difference = (target_angle - current_longitude) % tau
    # Here we have an approximation of the number of julian days to go
    date_delta = 365.25 * difference / tau
    # convert to "tt" and reconvert it back to a Time object
    t0 = ts.tt_jd(jan_first.tt + date_delta)

    def f(t):
        # We've got a float which is the `tt`
        sky_tt = ts.tt_jd(t)
        longitude = get_current_longitude(sky_tt, earth, sun)
        result = target_angle - longitude
        if result > pi:
            result = result - pi
        elif result < -pi:
            result = result + pi
        return result

    # Using datetimes to compute the next step date
    t0_plus_one_minute = t0.utc_datetime() + timedelta(minutes=1)
    # Back to Skyfield Time objects
    t0_plus_one_minute = ts.utc(t0_plus_one_minute)

    # Julian day for the starting date
    t0 = t0.tt
    # Adding one minute to have a second boundary
    t0_plus_one_minute = t0_plus_one_minute.tt
    # Newton method to converge towards the target angle
    t = newton(f, t0, t0_plus_one_minute)
    # Here we have a float to convert to julian days.
    t = ts.tt_jd(t)
    # To convert to datetime
    t = t.utc_datetime()
    # Convert in the timezone
    result = t.astimezone(tz)
    return result.date()
예제 #12
0
    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
        if '://' in MSS_CONFIG_PATH:
            try:
                _fs = fs.open_fs(MSS_CONFIG_PATH)
                download_path = _fs.getsyspath("")
            except fs.errors.CreateFailed:
                logging.error(
                    f'Make sure that the FS url "{MSS_CONFIG_PATH}" exists')
            except fs.opener.errors.UnsupportedProtocol:
                logging.error(f'FS url "{MSS_CONFIG_PATH}" not supported')
        else:
            download_path = MSS_CONFIG_PATH

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

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

        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()