示例#1
0
def test_from_horizons_scalar_epoch_uses_reshaped_epochs(horizons_mock):
    unused_name = "Strange Object"
    unused_id_type = "id_type"
    unused_plane = Planes.EARTH_EQUATOR
    unused_location_str = "500@399"
    unused_attractor = Earth

    expected_epochs = Time(["2020-03-01 12:00:00"], scale="tdb")
    epochs = expected_epochs[0]

    horizons_mock().vectors.return_value = {
        "x": [1] * u.au,
        "y": [0] * u.au,
        "z": [0] * u.au,
        "vx": [0] * (u.au / u.day),
        "vy": [1] * (u.au / u.day),
        "vz": [0] * (u.au / u.day),
    }

    Ephem.from_horizons(
        unused_name,
        epochs,
        attractor=unused_attractor,
        plane=unused_plane,
        id_type=unused_id_type,
    )

    horizons_mock.assert_called_with(
        id=unused_name,
        location=unused_location_str,
        epochs=expected_epochs.jd,
        id_type=unused_id_type,
    )
示例#2
0
def test_from_body_non_tdb_epochs_warning(epochs):
    unused_body = Earth
    epochs = Time.now()  # This uses UTC scale

    warning_pattern = "Input time was converted to scale='tdb'"
    with pytest.warns(TimeScaleWarning, match=warning_pattern):
        Ephem.from_body(unused_body, epochs)
示例#3
0
def test_ephem_sample_same_epochs_returns_same_input(epochs, coordinates, method):
    unused_plane = Planes.EARTH_EQUATOR
    ephem = Ephem(coordinates, epochs, unused_plane)

    result_coordinates = ephem.sample(epochs, method=method)

    # TODO: Should it return exactly the same?
    assert_coordinates_allclose(result_coordinates, coordinates, atol_scale=1e-17)
示例#4
0
def test_ephem_sample_scalar_epoch_returns_1_dimensional_coordinates(
        epochs, coordinates, method):
    unused_plane = Planes.EARTH_EQUATOR
    ephem = Ephem(coordinates, epochs, unused_plane)

    result_coordinates = ephem.sample(epochs[0], method=method)

    # Exactly the same
    assert result_coordinates.ndim == 1
示例#5
0
def test_ephem_sample_no_arguments_returns_exactly_same_input(
        epochs, coordinates, method):
    unused_plane = Planes.EARTH_EQUATOR
    ephem = Ephem(coordinates, epochs, unused_plane)

    result_coordinates = ephem.sample(method=method)

    # Exactly the same
    assert np.all(result_coordinates == coordinates)
示例#6
0
def test_ephem_sample_existing_epochs_returns_corresponding_input(
    epochs, coordinates, method
):
    unused_plane = Planes.EARTH_EQUATOR
    ephem = Ephem(coordinates, epochs, unused_plane)

    result_coordinates = ephem.sample(epochs[::2], method=method)

    # Exactly the same
    assert_coordinates_allclose(result_coordinates, coordinates[::2], atol_scale=1e-17)
示例#7
0
def test_ephem_sample_scalar_epoch_and_coordinates_returns_exactly_same_input(
        epochs, coordinates, method):
    unused_plane = Planes.EARTH_EQUATOR
    coordinates = coordinates[0].reshape(-1)
    epochs = epochs[0].reshape(-1)
    ephem = Ephem(coordinates, epochs, unused_plane)

    result_coordinates = ephem.sample(epochs[0], method=method)

    # Exactly the same
    assert result_coordinates == coordinates
示例#8
0
def test_from_body_non_tdb_epochs_warning(epochs):
    unused_body = Earth
    epochs = Time.now()  # This uses UTC scale

    with pytest.warns(TimeScaleWarning) as record:
        Ephem.from_body(unused_body, epochs)

    assert len(record) == 1
    assert "Input time was converted to scale='tdb'" in record[0].message.args[
        0]
    assert "Use Time(..., scale='tdb') instead" in record[0].message.args[0]
示例#9
0
def test_rv_scalar_epoch_returns_scalar_vectors(coordinates, epochs):
    unused_plane = Planes.EARTH_EQUATOR
    ephem = Ephem(coordinates, epochs, unused_plane)

    expected_r = coordinates.get_xyz(xyz_axis=1)[0]
    expected_v = coordinates.differentials["s"].get_d_xyz(xyz_axis=1)[0]

    r, v = ephem.rv(epochs[0])

    assert_quantity_allclose(r, expected_r)
    assert_quantity_allclose(v, expected_v)
示例#10
0
def test_rv_no_parameters_returns_input_vectors(coordinates, epochs):
    unused_plane = Planes.EARTH_EQUATOR
    ephem = Ephem(coordinates, epochs, unused_plane)

    expected_r = coordinates.get_xyz(xyz_axis=1)
    expected_v = coordinates.differentials["s"].get_d_xyz(xyz_axis=1)

    r, v = ephem.rv()

    assert_quantity_allclose(r, expected_r)
    assert_quantity_allclose(v, expected_v)
示例#11
0
    def _plot_body_orbit(
        self,
        body,
        epoch,
        *,
        label=None,
        color=None,
        trail=False,
    ):
        if color is None:
            color = BODY_COLORS.get(body.name)

        self.set_attractor(body.parent)

        # Get approximate, mean value for the period
        period = get_mean_elements(body, epoch).period

        label = generate_label(epoch, label or str(body))
        epochs = time_range(epoch,
                            periods=self._num_points,
                            end=epoch + period,
                            scale="tdb")
        ephem = Ephem.from_body(body,
                                epochs,
                                attractor=body.parent,
                                plane=self.plane)

        return self._plot_ephem(ephem,
                                epoch,
                                label=label,
                                color=color,
                                trail=trail)
 def _get_ephem(self):
     for x in self.body_dict["bodies"]:
         body = DummyBody(moon_dict[x]["index"])
         ephem = Ephem.from_body(body,
                                 self.current_time,
                                 attractor=self.body_dict["attractor"])
         self.ephems[x] = ephem
示例#13
0
def test_ephem_from_body_has_expected_properties(method, plane, FrameClass,
                                                 rtol):
    epochs = Time(
        [
            "2020-03-01 12:00:00", "2020-03-17 00:00:00.000",
            "2020-04-01 12:00:00.000"
        ],
        scale="tdb",
    )
    equatorial_coordinates = CartesianRepresentation(
        [
            (-1.40892271e08, 45067626.83900666, 19543510.68386639),
            (-1.4925067e08, 9130104.71634121, 3964948.59999307),
            (-1.46952333e08, -27413113.24215863, -11875983.21773582),
        ] * u.km,
        xyz_axis=1,
        differentials=CartesianDifferential(
            [
                (-10.14262131, -25.96929533, -11.25810932),
                (-2.28639444, -27.3906416, -11.87218591),
                (5.67814544, -26.84316701, -11.63720607),
            ] * (u.km / u.s),
            xyz_axis=1,
        ),
    )

    expected_coordinates = (
        ICRS(equatorial_coordinates).transform_to(FrameClass).represent_as(
            CartesianRepresentation, CartesianDifferential))

    earth = Ephem.from_body(Earth, epochs, plane=plane)
    coordinates = earth.sample(method=method)

    assert earth.epochs is epochs
    assert_coordinates_allclose(coordinates, expected_coordinates, rtol=rtol)
示例#14
0
def test_ephem_from_horizons_calls_horizons_with_correct_parameters(
    horizons_mock, attractor, location_str, plane, refplane_str
):
    unused_name = "Strange Object"
    unused_id_type = "id_type"
    epochs = Time(["2020-03-01 12:00:00"], scale="tdb")

    horizons_mock().vectors.return_value = {
        "x": [1] * u.au,
        "y": [0] * u.au,
        "z": [0] * u.au,
        "vx": [0] * (u.au / u.day),
        "vy": [1] * (u.au / u.day),
        "vz": [0] * (u.au / u.day),
    }
    expected_coordinates = CartesianRepresentation(
        [(1, 0, 0)] * u.au,
        xyz_axis=1,
        differentials=CartesianDifferential([(0, 1, 0)] * (u.au / u.day), xyz_axis=1),
    )

    ephem = Ephem.from_horizons(
        unused_name, epochs, attractor=attractor, plane=plane, id_type=unused_id_type
    )

    horizons_mock.assert_called_with(
        id=unused_name, location=location_str, epochs=epochs.jd, id_type=unused_id_type
    )
    horizons_mock().vectors.assert_called_once_with(refplane=refplane_str)

    coordinates = ephem.sample()

    assert_coordinates_allclose(coordinates, expected_coordinates)
 def _get_ephem_from_list_of_bodies(
         bodies, epochs) -> Dict[str, Tuple[SolarSystemPlanet, Ephem]]:
     list_of_bodies = {}
     for i in bodies:
         ephem = Ephem.from_body(i, epochs)
         list_of_bodies[i.name] = (i, ephem)
     return list_of_bodies
示例#16
0
def test_ephem_fails_if_dimensions_are_not_correct(epochs, coordinates):
    unused_plane = Planes.EARTH_EQUATOR
    with pytest.raises(ValueError) as excinfo:
        Ephem(epochs[0], coordinates, unused_plane)
    assert (
        "Coordinates and epochs must have dimension 1, got 0 and 1" in excinfo.exconly()
    )
示例#17
0
def distance_chart(body1, body2, date_start, interval, steps):
    """Generates a distance chart between body1 (e.g. Earth) and body2 (e.g. Mars)
       from date_start till interval (e.g. 10 days) and steps (36).
       Returns plotly's Figure."""

    eph1 = Ephem.from_body(
        body1, time_range(date_start, end=date_start + steps * interval))
    eph2 = Ephem.from_body(
        body2, time_range(date_start, end=date_start + steps * interval))

    # Solve for departure and target orbits
    orb1 = Orbit.from_ephem(Sun, eph1, date_start)
    orb2 = Orbit.from_ephem(Sun, eph2, date_start)

    t_tbl = []
    dist_tbl = []

    t = date_start

    for i in range(1, steps):
        day = str(orb1.epoch)[:10]  # take the first "2020-01-01" from the date
        t_tbl.append(day)
        dist = np.linalg.norm(orb1.r - orb2.r)
        dist_tbl.append(dist.value)

        orb1 = orb1.propagate(interval)
        orb2 = orb2.propagate(interval)

    fig = go.Figure()
    fig.add_trace(
        go.Scatter(x=t_tbl,
                   y=dist_tbl,
                   mode="lines+markers",
                   name="Earth - Mars distance"))

    name = body1.name + "-" + body2.name + " distance"

    fig.update_layout(legend=dict(orientation="h",
                                  yanchor="bottom",
                                  y=1.02,
                                  xanchor="right",
                                  x=1),
                      xaxis_title="date",
                      yaxis_title="Distance [km]",
                      title=name,
                      margin=dict(l=20, r=20, t=40, b=20))
    return fig
示例#18
0
def test_from_body_scalar_epoch_uses_reshaped_epochs():
    expected_epochs = Time(["2020-03-01 12:00:00"], scale="tdb")
    epochs = expected_epochs[0]

    unused_plane = Planes.EARTH_EQUATOR
    ephem = Ephem.from_body(Earth, epochs, plane=unused_plane)

    assert ephem.epochs == expected_epochs
示例#19
0
def test_ephem_str_matches_expected_representation(epochs, coordinates):
    plane = Planes.EARTH_EQUATOR
    ephem = Ephem(coordinates, epochs, plane)

    expected_str = (
        "Ephemerides at 4 epochs "
        "from 2020-03-01 12:00:00.000 (TDB) to 2020-03-04 12:00:00.000 (TDB)")

    assert repr(ephem) == str(ephem) == expected_str
示例#20
0
def test_can_set_iss_attractor_to_earth():
    # See https://github.com/poliastro/poliastro/issues/798
    epoch = Time("2019-11-10 12:00:00")
    ephem = Ephem.from_horizons(
        "International Space Station", epochs=epoch, attractor=Sun, id_type="majorbody"
    )
    iss = Orbit.from_ephem(Sun, ephem, epoch)
    iss = iss.change_attractor(Earth)
    assert iss.attractor == Earth
示例#21
0
def get_earth_ephem(epoch=None):

    if epoch is None:
        today = date.today()
        epoch = time.Time(today.strftime("%Y-%m-%d") + " 12:00")  # UTC by default

    earth_eph = Ephem.from_body(Earth, epoch.tdb)

    return earth_eph
示例#22
0
def test_ephem_without_frame_raises_error():
    epochs = time.Time("2020-04-29 10:43", scale="tdb")
    earth = Ephem.from_body(Earth, epochs)
    plotter = OrbitPlotter2D()

    with pytest.raises(ValueError) as excinfo:
        plotter.set_attractor(Sun)
        plotter.plot_ephem(earth)
    assert ("A frame must be set up first, please use "
            "set_orbit_frame(orbit) or plot(orbit)" in excinfo.exconly())
示例#23
0
def test_from_ephem_has_expected_properties():
    epoch = J2000_TDB
    ephem = Ephem.from_body(Earth, epoch, attractor=Sun)
    expected_r, expected_v = ephem.rv(epoch)

    ss = Orbit.from_ephem(Sun, ephem, epoch)

    assert ss.plane is ephem.plane
    assert ss.epoch == epoch
    assert_quantity_allclose(ss.r, expected_r)
    assert_quantity_allclose(ss.v, expected_v)
示例#24
0
def test_from_orbit_scalar_epoch_uses_reshaped_epochs():
    r = [-6045, -3490, 2500] * u.km
    v = [-3.457, 6.618, 2.533] * u.km / u.s
    orb = Orbit.from_vectors(Earth, r, v)
    expected_epochs = Time(["2020-01-02 12:00:00"])
    epochs = expected_epochs[0]

    unused_plane = Planes.EARTH_EQUATOR
    ephem = Ephem.from_orbit(orbit=orb, epochs=epochs, plane=unused_plane)

    assert ephem.epochs == expected_epochs
示例#25
0
def dist_chart(asteroid, date, timespan):
    solar_system_ephemeris.set('jpl')

    EPOCH = Time(date, scale="tdb")

    epochs = time_range(EPOCH - TimeDelta(timespan),
                        end=EPOCH + TimeDelta(timespan))

    epochs_moon = time_range(EPOCH - TimeDelta(15 * u.day),
                             end=EPOCH + TimeDelta(15 * u.day))

    moon = Ephem.from_body(Moon, epochs_moon, attractor=Earth)
    aster = Ephem.from_horizons(asteroid, epochs, attractor=Earth)

    plotter = StaticOrbitPlotter()
    plotter.set_attractor(Earth)
    plotter.set_body_frame(Moon)
    plotter.plot_ephem(moon, EPOCH, label=Moon)
    plotter.plot_ephem(aster, EPOCH, label=asteroid)

    return plotter
示例#26
0
def bodies_vector(T, dt, body1, body2, epoch=J2000, timedelta = None):
    """Returns vector for every dt in [0,T] from bodie1 to bodie2
    
    Parameters
    ----------
    T : float
        time of propagation
    dt : float
        time interval
    body1 : ~poliastro.bodies.Body
        first body
    body2 : ~poliastro.bodies.Body
        second body
    epoch : ~astropy.time.Time, optional
        Epoch offset
    timedelta : ~astropy.time.Time, optional
        desired time of propagation
    
    Returns
    -------
    diff : ~astropy.units.quantity.Quantity
        vectors for timedelta propagation from body1 to body2
    """
    
    DT_TIME = 500
    if not timedelta:
        time_delta = Time([epoch + j*u.s for j in np.linspace(0,3600*24*1.01*T, int(3600*24*T/DT_TIME)) ] )
    else:
        time_delta = timedelta
    
    ephem_b1 = Ephem.from_body(body1, time_delta.tdb)
    ephem_b2 = Ephem.from_body(body2, time_delta.tdb)
    
    tofs = Time([epoch + j*dt*u.s for j in range(10,int(3600*24*T/dt)+10)])
    r_b1, _ = ephem_b1.rv(tofs)
    r_b2, _ = ephem_b2.rv(tofs)
    
    diff = (r_b2-r_b1).to(u.km)
    return diff
示例#27
0
def test_plot_ephem_no_epoch():
    epoch = Time("2020-02-14 00:00:00")
    ephem = Ephem.from_horizons(
        "2020 CD3",
        time_range(Time("2020-02-13 12:00:00"), end=Time("2020-02-14 12:00:00")),
        attractor=Earth,
    )

    fig, ax = plt.subplots()
    plotter = StaticOrbitPlotter(ax=ax)
    plotter.set_attractor(Earth)
    plotter.set_orbit_frame(Orbit.from_ephem(Earth, ephem, epoch))

    plotter.plot_ephem(ephem, label="2020 CD3 Minimoon", color="k")

    return fig
示例#28
0
def test_plot_ephem_different_plane_raises_error():
    unused_epochs = Time.now().reshape(-1)
    unused_coordinates = CartesianRepresentation(
        [(1, 0, 0)] * u.au,
        xyz_axis=1,
        differentials=CartesianDifferential([(0, 1, 0)] * (u.au / u.day), xyz_axis=1),
    )

    op = StaticOrbitPlotter(plane=Planes.EARTH_ECLIPTIC)
    op.set_attractor(Sun)
    op.set_body_frame(Earth)
    with pytest.raises(ValueError) as excinfo:
        op.plot_ephem(Ephem(unused_epochs, unused_coordinates, Planes.EARTH_EQUATOR))

    assert (
        "sample the ephemerides using a different plane or create a new plotter"
        in excinfo.exconly()
    )
示例#29
0
    def reset(self):
        # get planet and spaceship positions at start_time, reset spaceship fuel,

        self.current_time = self.start_time

        self.current_ephem = self._get_ephem_from_list_of_bodies(
            self.body_list, self.start_time)

        # set up spacecraft
        self.spaceship = self._init_spaceship()

        start_body_ephem = Ephem.from_body(self.start_body, self.start_time)
        self.spaceship.rv = (self.spaceship.rv[0] + start_body_ephem.rv()[0],
                             self.spaceship.rv[1] + start_body_ephem.rv()[1])
        # convert spaceship rv to system-relative rather than earth

        observation = self._get_observation()

        return observation
示例#30
0
    def set_body_frame(self, body, epoch=None):
        """Sets perifocal frame based on the orbit of a body at a particular epoch if given.

        Parameters
        ----------
        body : poliastro.bodies.SolarSystemPlanet
            Body.
        epoch : astropy.time.Time, optional
            Epoch of current position.

        """
        from warnings import warn

        from astropy import time

        from poliastro.bodies import Sun
        from poliastro.twobody import Orbit

        from ..warnings import TimeScaleWarning

        if not epoch:
            epoch = time.Time.now().tdb
        elif epoch.scale != "tdb":
            epoch = epoch.tdb
            warn(
                "Input time was converted to scale='tdb' with value "
                f"{epoch.tdb.value}. Use Time(..., scale='tdb') instead.",
                TimeScaleWarning,
                stacklevel=2,
            )

        with warnings.catch_warnings():
            ephem = Ephem.from_body(body,
                                    epoch,
                                    attractor=Sun,
                                    plane=self.plane)  # type: ignore
            orbit = Orbit.from_ephem(Sun, ephem, epoch).change_plane(
                self.plane)  # type: ignore

        self.set_orbit_frame(orbit)