open-space-toolkit-astrodynamics 16.7.1__py39-none-manylinux2014_x86_64.whl → 16.7.3__py39-none-manylinux2014_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: open-space-toolkit-astrodynamics
3
- Version: 16.7.1
3
+ Version: 16.7.3
4
4
  Summary: Orbit, attitude, access.
5
5
  Author: Open Space Collective
6
6
  Author-email: contact@open-space-collective.org
@@ -1,18 +1,18 @@
1
1
  ostk/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
2
- ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-39-x86_64-linux-gnu.so,sha256=3_OBMoc6Pxt8REFzfQwqZtv1btU4TBUBswozZiMZG1Y,2980256
2
+ ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-39-x86_64-linux-gnu.so,sha256=Twmz5G1ykkUVE8kEwccYyUoXqljAqLO-e6THUV0xzCc,2980256
3
3
  ostk/astrodynamics/__init__.py,sha256=3gWyqFIbhAfcdeMhmfBPQPlPQTmaOzm-6flkJe745Zk,251
4
- ostk/astrodynamics/__init__.pyi,sha256=XWkCMyodZw1DS4P7xFaFRjo6q8qPYVWJU6caKIQsBok,32224
5
- ostk/astrodynamics/access.pyi,sha256=t2CF0TU6_6ow_rkV_I4rVKap7ZIdC4jYKL3WkTDHRXg,25157
4
+ ostk/astrodynamics/__init__.pyi,sha256=tsr8hkEyFBjbprq2pxcxhxzWZPwfL2JBa3mSNfThIDw,32224
5
+ ostk/astrodynamics/access.pyi,sha256=pp2t81kKH4sP4BcGb8nAZHmpwhISjFODMpbZ4ucLFAw,25157
6
6
  ostk/astrodynamics/converters.py,sha256=luPh30qMp9bzEkN7hUccmxlLf7zRp_AzqmBe8IUjPhU,3314
7
7
  ostk/astrodynamics/converters.pyi,sha256=HrZFyizkc6Hv_K38ZKZ80fX_bAxd6keA_NFWNQygvbs,1745
8
8
  ostk/astrodynamics/dataframe.py,sha256=v-36rBHKdf7kQw1jdvJWrvkR-ZjW5DKRchtTEJWhdxk,25012
9
- ostk/astrodynamics/display.py,sha256=LZESZgx2wlrFO4cwAGMb3VPJfdtcjNgCgKFrqot0NYU,6339
9
+ ostk/astrodynamics/display.py,sha256=D9PrX1G-XmXk2j3Jl7Na7q52PTc4WKWB1-oRFJPT6w0,8606
10
10
  ostk/astrodynamics/dynamics.pyi,sha256=gZ95KoGex4SB-1z6yMrngkZN1Ir9X6bEmrZgdLxq1ZE,13270
11
11
  ostk/astrodynamics/eclipse.pyi,sha256=Q8fzdukA7fyxbUM3wjEXAHukT-Ovl4FM00NbjsMPnUM,3211
12
12
  ostk/astrodynamics/estimator.pyi,sha256=MnahWzp8aACxrNKWlYRsgQr5zpBxogNr-yPm7hJob5k,14000
13
13
  ostk/astrodynamics/event_condition.pyi,sha256=2c_1Sq7tkYKeAA_aRWBi43KDQXXxu6EMSmUpEWz_Fa4,45814
14
14
  ostk/astrodynamics/guidance_law.pyi,sha256=rVmbpV2Y5FsIXejaInxINS67nVHmTIxVEkhaDIn17SA,12171
15
- ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.16,sha256=t_qeaFkF1EQVdxB4zBfGjMZDsANcsQP2Eb4bm-fKZTQ,127462728
15
+ ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.16,sha256=lyI6yjgxxfXRXbY2uOmW5YtETg3vCjEUtZbZLd2zsII,130575872
16
16
  ostk/astrodynamics/solver.pyi,sha256=dRdR9RLqwSaBBX_ZRmpeBv06WvM_BFNo3WUdNzorYTY,17805
17
17
  ostk/astrodynamics/utilities.py,sha256=y8mr3M46J5z-GhS1oIEnuEJA6otwcyJ9YDhvn_5JxHM,6976
18
18
  ostk/astrodynamics/viewer.py,sha256=SlKyOWKjaF3V9HFB3I7ZgHy7n_GLeHTWM9q2wXkpxe8,27077
@@ -34,7 +34,7 @@ ostk/astrodynamics/test/conftest.py,sha256=stmQOt7UXjBlXKJzNN6RkS2miv1xXSOX-YNpF
34
34
  ostk/astrodynamics/test/test_access.py,sha256=MCBsUPtuVm7NgHZR0z0DpWnPZ_qBu4aRhLI2PnRNUYs,3940
35
35
  ostk/astrodynamics/test/test_converters.py,sha256=mFpDD0YM8o356lj91GGIwYdMk2ut6xZFV3uYcgZepMY,8744
36
36
  ostk/astrodynamics/test/test_dataframe.py,sha256=NddmwnV8R1QgTD_iLXn_h0xK2kP5Qk22Oh93hF6KjT0,38300
37
- ostk/astrodynamics/test/test_display.py,sha256=CQEz66OZna6W8_ZIEVCPKAH-cM9YjzCOGpoINqC8m40,3840
37
+ ostk/astrodynamics/test/test_display.py,sha256=jQ94OeLPlcKzzSLgLTujr9ew9T2uwGZMijS_jHBJAGA,6529
38
38
  ostk/astrodynamics/test/test_event_condition.py,sha256=fQ-rVYpQsa7xacxRMBOQDyn61CuAGX1QBOGZxGWR0_s,2204
39
39
  ostk/astrodynamics/test/test_import.py,sha256=py_hALBR0IYuUzv9dfgQZzrrLHJIpnyKvt3Oi1XBqCg,1251
40
40
  ostk/astrodynamics/test/test_root_solver.py,sha256=hQ8O6g-WP49gZH_H3Rdufv0F0gQorpzJyIcjBGGUQ34,1831
@@ -138,8 +138,8 @@ ostk/astrodynamics/trajectory/orbit/model/kepler.pyi,sha256=KL-FwPbG4OUkPjhQb1Pa
138
138
  ostk/astrodynamics/trajectory/orbit/model/sgp4.pyi,sha256=OhFzoPPQHlYy7m3LiZ8TXF89M4uBTfNk6tGsBEp0sjI,14235
139
139
  ostk/astrodynamics/trajectory/state/__init__.pyi,sha256=bq__Fii35czVrTeNxc9eQVjXdqwbbQxUdNQWK3vLrMo,17649
140
140
  ostk/astrodynamics/trajectory/state/coordinate_subset.pyi,sha256=kYMfMwEjCqO1NepMYFT4QS6kIPBkVL6sGCLeLbogcMw,10176
141
- open_space_toolkit_astrodynamics-16.7.1.dist-info/METADATA,sha256=XO8JRdEPgLt74YCe3W0vBpqU3tW5zeDVLgbrpbNytZA,1913
142
- open_space_toolkit_astrodynamics-16.7.1.dist-info/WHEEL,sha256=Lf7t-kOlAeOyExg08NFEPC9xn1Q2CLFgwDRGfj0NsM4,109
143
- open_space_toolkit_astrodynamics-16.7.1.dist-info/top_level.txt,sha256=zOR18699uDYnafgarhL8WU_LmTZY_5NVqutv-flp_x4,5
144
- open_space_toolkit_astrodynamics-16.7.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
145
- open_space_toolkit_astrodynamics-16.7.1.dist-info/RECORD,,
141
+ open_space_toolkit_astrodynamics-16.7.3.dist-info/METADATA,sha256=H13jmIAfCL_DeIh7ndH-8RXPpwKaXmWkhBkMGDbgNlE,1913
142
+ open_space_toolkit_astrodynamics-16.7.3.dist-info/WHEEL,sha256=Lf7t-kOlAeOyExg08NFEPC9xn1Q2CLFgwDRGfj0NsM4,109
143
+ open_space_toolkit_astrodynamics-16.7.3.dist-info/top_level.txt,sha256=zOR18699uDYnafgarhL8WU_LmTZY_5NVqutv-flp_x4,5
144
+ open_space_toolkit_astrodynamics-16.7.3.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
145
+ open_space_toolkit_astrodynamics-16.7.3.dist-info/RECORD,,
@@ -5,8 +5,8 @@ from ostk.astrodynamics.trajectory import State as PyState
5
5
  from ostk import core as OpenSpaceToolkitCorePy
6
6
  from ostk.core import container
7
7
  from ostk.core import filesystem
8
- from ostk.core import type
9
8
  import ostk.core.type
9
+ from ostk.core import type
10
10
  from ostk import io as OpenSpaceToolkitIOPy
11
11
  from ostk.io import URL
12
12
  from ostk.io import ip
@@ -19,13 +19,13 @@ from ostk import physics as OpenSpaceToolkitPhysicsPy
19
19
  from ostk.physics import Environment
20
20
  from ostk.physics import Manager
21
21
  from ostk.physics import Unit
22
- import ostk.physics.coordinate
23
22
  from ostk.physics import coordinate
23
+ import ostk.physics.coordinate
24
24
  import ostk.physics.coordinate.spherical
25
25
  from ostk.physics import environment
26
26
  import ostk.physics.environment.object
27
- import ostk.physics.time
28
27
  from ostk.physics import time
28
+ import ostk.physics.time
29
29
  from ostk.physics import unit
30
30
  import ostk.physics.unit
31
31
  import typing
@@ -491,7 +491,7 @@ class VisibilityCriterion:
491
491
  Creates a visibility criterion from an elevation interval.
492
492
 
493
493
  Args:
494
- elevation_interval (RealInterval): The elevation interval in radians.
494
+ elevation_interval (RealInterval): The elevation interval in degrees.
495
495
 
496
496
  Returns:
497
497
  VisibilityCriterion: The visibility criterion instance.
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import warnings
5
6
  from typing import Any
6
7
 
7
8
  import pandas as pd
@@ -10,13 +11,11 @@ import plotly.graph_objs as go
10
11
 
11
12
  from ostk.mathematics.object import RealInterval
12
13
 
13
- from ostk.physics.coordinate import Position
14
14
  from ostk.physics.coordinate import Frame
15
15
  from ostk.physics.coordinate.spherical import LLA
16
16
  from ostk.physics.environment.object import Celestial
17
17
  from ostk.physics.time import Duration
18
18
  from ostk.physics.time import Instant
19
- from ostk.physics.unit import Length
20
19
 
21
20
  from ostk.astrodynamics import Access
22
21
  from ostk.astrodynamics import Trajectory
@@ -81,7 +80,9 @@ DEFAULT_LAYOUT_3D: go.Layout = go.Layout(
81
80
 
82
81
 
83
82
  def convert_to_ground_track_plotting_data(
84
- longitude: list, latitude: list, color: str = DEFAULT_COLOR
83
+ longitude: list,
84
+ latitude: list,
85
+ color: str = DEFAULT_COLOR,
85
86
  ) -> go.Scattergeo:
86
87
  return go.Scattergeo(
87
88
  lon=longitude,
@@ -94,18 +95,25 @@ def convert_to_ground_track_plotting_data(
94
95
  )
95
96
 
96
97
 
97
- def create_plotly_figure(data: Any, layout: go.Layout) -> go.Figure:
98
+ def create_plotly_figure(
99
+ data: Any,
100
+ layout: go.Layout,
101
+ ) -> go.Figure:
98
102
  return go.Figure(
99
103
  data=data,
100
104
  layout=layout,
101
105
  )
102
106
 
103
107
 
104
- def create_2d_map(data: Any) -> go.Figure:
108
+ def create_2d_map(
109
+ data: Any,
110
+ ) -> go.Figure:
105
111
  return create_plotly_figure(data, DEFAULT_LAYOUT_2D)
106
112
 
107
113
 
108
- def create_3d_globe(data: Any) -> go.Figure:
114
+ def create_3d_globe(
115
+ data: Any,
116
+ ) -> go.Figure:
109
117
  return create_plotly_figure(data, DEFAULT_LAYOUT_3D)
110
118
 
111
119
 
@@ -121,36 +129,27 @@ class AccessesPlot:
121
129
  interval: RealInterval,
122
130
  trajectory_step: Duration,
123
131
  access_step: Duration,
124
- ground_station_lla: LLA,
125
- color: str,
132
+ ground_station_lla: LLA | None = None,
133
+ color: str | None = None,
126
134
  ):
135
+ self._data = []
127
136
  self._earth = earth
128
137
  self._trajectory_grid: list[Instant] = interval.generate_grid(trajectory_step)
129
- self._access_step: Instant = access_step
130
- self._ned_frame: Frame = self._earth.get_frame_at(
131
- ground_station_lla, self._earth.FrameType.NED
132
- )
133
- self._ground_station_position_ned: Position = Position(
134
- [0.0, 0.0, 0.0],
135
- Length.Unit.Meter,
136
- self._ned_frame,
137
- )
138
- self._data = []
139
- self._data.append(
140
- dict(
141
- type="scattergeo",
142
- lon=[float(ground_station_lla.get_longitude().in_degrees())],
143
- lat=[float(ground_station_lla.get_latitude().in_degrees())],
144
- mode="markers",
145
- marker=dict(
146
- size=10,
147
- color=color,
148
- ),
138
+ self._access_step: Duration = access_step
139
+
140
+ if ground_station_lla is not None and color is not None:
141
+ warnings.warn(
142
+ "Ground station and color are deprecated; use add_ground_station instead.",
143
+ DeprecationWarning,
144
+ stacklevel=2,
149
145
  )
150
- )
146
+ self.add_ground_station(ground_station_lla, color)
151
147
 
152
148
  def _generate_and_append_data(
153
- self, data: list[list[float]], trajectory: Trajectory, grid: list[Instant]
149
+ self,
150
+ data: list[list[float]],
151
+ trajectory: Trajectory,
152
+ grid: list[Instant],
154
153
  ) -> None:
155
154
  for state in trajectory.get_states_at(grid):
156
155
  lla: LLA = LLA.cartesian(
@@ -168,7 +167,10 @@ class AccessesPlot:
168
167
  )
169
168
 
170
169
  def _append_line(
171
- self, df: pd.DataFrame, width: int, rgb: list[int], alpha: float
170
+ self,
171
+ df: pd.DataFrame,
172
+ width: int,
173
+ rgb: str,
172
174
  ) -> None:
173
175
  self._data.append(
174
176
  dict(
@@ -178,30 +180,56 @@ class AccessesPlot:
178
180
  mode="lines",
179
181
  line=dict(
180
182
  width=width,
181
- color=f"rgba({str(rgb[0])},{str(rgb[1])},{str(rgb[2])},{str(alpha)})",
183
+ color=rgb,
182
184
  ),
183
185
  )
184
186
  )
185
187
 
186
- def add_satellite(
187
- self, trajectory: Trajectory, accesses: list[Access], rgb: list[int]
188
+ def add_ground_station(
189
+ self,
190
+ ground_station_lla: LLA,
191
+ color: str | tuple[int, int, int],
188
192
  ) -> None:
189
193
  """
190
- Add a satellite trajectory to the plot, including a highligh ot the interference
191
- accesses.
194
+ Add a ground station to the plot.
195
+
196
+ Args:
197
+ ground_station_lla (LLA): The ground station location.
198
+ color (str | tuple[int, int, int]): The color of the ground station.
192
199
  """
200
+ if isinstance(color, (tuple, list)):
201
+ color = f"rgba({str(color[0])},{str(color[1])},{str(color[2])},1.0)"
193
202
 
194
- # Satellite trajectory
195
- satellite_trajectory_data: list[list[float]] = []
196
- self._generate_and_append_data(
197
- satellite_trajectory_data, trajectory, self._trajectory_grid
198
- )
199
- satellite_trajectory_df: pd.Dataframe = pd.DataFrame(
200
- satellite_trajectory_data, columns=["Longitude", "Latitude"]
203
+ self._data.append(
204
+ dict(
205
+ type="scattergeo",
206
+ lon=[float(ground_station_lla.get_longitude().in_degrees())],
207
+ lat=[float(ground_station_lla.get_latitude().in_degrees())],
208
+ mode="markers",
209
+ marker=dict(
210
+ size=10,
211
+ color=color,
212
+ ),
213
+ )
201
214
  )
202
- self._append_line(satellite_trajectory_df, 1, rgb, 0.1)
203
215
 
204
- # Satellite accesses
216
+ def add_accesses(
217
+ self,
218
+ trajectory: Trajectory,
219
+ accesses: list[Access],
220
+ rgb: str | tuple[int, int, int],
221
+ ) -> None:
222
+ """
223
+ Add accesses to the plot.
224
+
225
+ Args:
226
+ trajectory (Trajectory): The satellite trajectory.
227
+ accesses (list[Access]): The list of accesses.
228
+ rgb (str | tuple[int, int, int]): The color of the accesses, as a string or tuple of RGB values.
229
+ """
230
+ if isinstance(rgb, (tuple, list)):
231
+ rgb = f"rgba({str(rgb[0])},{str(rgb[1])},{str(rgb[2])},1.0)"
232
+
205
233
  for access in accesses:
206
234
  satellite_access_data: list[list[float]] = []
207
235
  self._generate_and_append_data(
@@ -209,10 +237,66 @@ class AccessesPlot:
209
237
  trajectory,
210
238
  access.get_interval().generate_grid(self._access_step),
211
239
  )
212
- satellite_access_df: pd.Dataframe = pd.DataFrame(
213
- satellite_access_data, columns=["Longitude", "Latitude"]
240
+ satellite_access_df: pd.DataFrame = pd.DataFrame(
241
+ satellite_access_data,
242
+ columns=["Longitude", "Latitude"],
243
+ )
244
+ self._append_line(
245
+ satellite_access_df,
246
+ 2,
247
+ rgb,
214
248
  )
215
- self._append_line(satellite_access_df, 2, rgb, 1.0)
249
+
250
+ def add_satellite(
251
+ self,
252
+ trajectory: Trajectory,
253
+ accesses: list[Access] | None = None,
254
+ rgb: str | tuple[int, int, int] | None = None,
255
+ opacity: float = 0.3,
256
+ ) -> None:
257
+ """
258
+ Add a satellite trajectory to the plot. If `accesses` is provided (deprecated),
259
+ they will be plotted and a deprecation warning will be emitted.
260
+
261
+ Args:
262
+ trajectory (Trajectory): The satellite trajectory.
263
+ accesses (list[Access] | None, optional): (Deprecated) Accesses to plot; use add_accesses().
264
+ rgb (str | tuple[int, int, int] | None, optional): The color of the satellite, as a string or tuple of RGB values.
265
+ opacity (float, optional): Opacity of the satellite trajectory line.
266
+ """
267
+ if rgb is None:
268
+ rgb = f"rgba(255, 0, 0, {opacity})"
269
+
270
+ elif isinstance(rgb, (tuple, list)):
271
+ rgb = f"rgba({str(rgb[0])},{str(rgb[1])},{str(rgb[2])},{opacity})"
272
+
273
+ if accesses is not None:
274
+ warnings.warn(
275
+ "Passing accesses to add_satellite() is deprecated; use add_accesses() instead.",
276
+ DeprecationWarning,
277
+ stacklevel=2,
278
+ )
279
+ self.add_accesses(
280
+ trajectory,
281
+ accesses,
282
+ rgb,
283
+ )
284
+
285
+ satellite_trajectory_data: list[list[float]] = []
286
+ self._generate_and_append_data(
287
+ satellite_trajectory_data,
288
+ trajectory,
289
+ self._trajectory_grid,
290
+ )
291
+ satellite_trajectory_df: pd.DataFrame = pd.DataFrame(
292
+ satellite_trajectory_data,
293
+ columns=["Longitude", "Latitude"],
294
+ )
295
+ self._append_line(
296
+ satellite_trajectory_df,
297
+ 1,
298
+ rgb,
299
+ )
216
300
 
217
301
  def show(self):
218
302
  """
@@ -1,10 +1,9 @@
1
1
  # Apache License 2.0
2
2
 
3
- from ostk.mathematics.object import RealInterval
3
+ import pytest
4
4
 
5
5
  from ostk.physics import Environment
6
6
  from ostk.physics.coordinate import Position
7
- from ostk.physics.coordinate import Frame
8
7
  from ostk.physics.coordinate.spherical import LLA
9
8
  from ostk.physics.environment.object import Celestial
10
9
  from ostk.physics.time import DateTime
@@ -20,99 +19,207 @@ from ostk.astrodynamics.access import Generator as AccessGenerator
20
19
  from ostk.astrodynamics.trajectory import Orbit
21
20
  from ostk.astrodynamics.trajectory.orbit.model import SGP4
22
21
  from ostk.astrodynamics.trajectory.orbit.model.sgp4 import TLE
22
+ from ostk.astrodynamics import Access
23
23
  from ostk.astrodynamics.access import AccessTarget
24
24
  from ostk.astrodynamics.access import VisibilityCriterion
25
25
 
26
26
 
27
- class TestDisplay:
28
- def test_accesses_plot(self):
29
- start_instant: Instant = Instant.date_time(
30
- DateTime(2023, 1, 3, 0, 0, 0),
31
- Scale.UTC,
32
- )
33
- duration: Duration = Duration.hours(1.0)
34
- step: Duration = Duration.seconds(10.0)
35
- tolerance: Duration = Duration.seconds(1.0)
36
-
37
- ground_station_lla: LLA = LLA(
38
- Angle.degrees(70.0),
39
- Angle.degrees(160.0),
40
- Length.meters(0.0),
41
- )
42
-
43
- tle_1 = TLE(
44
- "1 55076U 23001BV 23146.17959645 .00004328 00000-0 23719-3 0 9993",
45
- "2 55076 97.4793 205.9529 0016244 89.9523 270.3571 15.14609100 21723",
46
- )
47
-
48
- tle_2 = TLE(
49
- "1 48915U 21059AN 23146.32782040 .00004955 00000-0 24678-3 0 9999",
50
- "2 48915 97.5954 279.7041 0010303 354.9434 5.1694 15.18004448105867",
51
- )
52
-
53
- environment: Environment = Environment.default()
54
- earth: Celestial = environment.access_celestial_object_with_name("Earth")
55
-
56
- visibility_criterion: VisibilityCriterion = (
57
- VisibilityCriterion.from_line_of_sight(environment)
58
- )
59
-
60
- access_target: AccessTarget = AccessTarget.from_position(
61
- visibility_criterion,
62
- Position.meters(
63
- ground_station_lla.to_cartesian(
64
- earth.get_equatorial_radius(),
65
- earth.get_flattening(),
66
- ),
67
- Frame.ITRF(),
68
- ),
69
- )
70
-
71
- stop_instant: Instant = start_instant + duration
72
- search_interval: RealInterval = Interval.closed(start_instant, stop_instant)
73
-
74
- orbit_1: Orbit = Orbit(SGP4(tle_1), earth)
75
- orbit_2: Orbit = Orbit(SGP4(tle_2), earth)
76
-
77
- generator = AccessGenerator(
78
- environment=environment,
79
- step=step,
80
- tolerance=tolerance,
81
- )
82
-
83
- accesses_1 = generator.compute_accesses(
84
- interval=search_interval,
85
- access_target=access_target,
86
- to_trajectory=orbit_1,
87
- )
88
-
89
- assert len(accesses_1) > 0
27
+ @pytest.fixture
28
+ def environment() -> Environment:
29
+ return Environment.default()
30
+
31
+
32
+ @pytest.fixture
33
+ def earth(environment: Environment) -> Celestial:
34
+ return environment.access_celestial_object_with_name("Earth")
35
+
36
+
37
+ @pytest.fixture
38
+ def search_interval() -> Interval:
39
+ start_instant: Instant = Instant.date_time(
40
+ DateTime(2023, 1, 3, 0, 0, 0),
41
+ Scale.UTC,
42
+ )
43
+ duration: Duration = Duration.hours(1.0)
44
+ stop_instant: Instant = start_instant + duration
45
+ return Interval.closed(start_instant, stop_instant)
46
+
47
+
48
+ @pytest.fixture
49
+ def access_plot() -> display.AccessesPlot:
50
+ return display.AccessesPlot(
51
+ earth=earth,
52
+ interval=search_interval,
53
+ trajectory_step=Duration.minutes(5.0),
54
+ access_step=Duration.seconds(10.0),
55
+ )
56
+
57
+
58
+ @pytest.fixture
59
+ def satellite_1_trajectory(earth: Celestial) -> Orbit:
60
+ tle_1 = TLE(
61
+ "1 55076U 23001BV 23146.17959645 .00004328 00000-0 23719-3 0 9993",
62
+ "2 55076 97.4793 205.9529 0016244 89.9523 270.3571 15.14609100 21723",
63
+ )
64
+ return Orbit(SGP4(tle_1), earth)
65
+
66
+
67
+ @pytest.fixture
68
+ def satellite_2_trajectory(earth: Celestial) -> Orbit:
69
+ tle_2 = TLE(
70
+ "1 48915U 21059AN 23146.32782040 .00004955 00000-0 24678-3 0 9999",
71
+ "2 48915 97.5954 279.7041 0010303 354.9434 5.1694 15.18004448105867",
72
+ )
73
+ return Orbit(SGP4(tle_2), earth)
74
+
75
+
76
+ @pytest.fixture
77
+ def ground_station_lla() -> LLA:
78
+ return LLA(
79
+ Angle.degrees(70.0),
80
+ Angle.degrees(160.0),
81
+ Length.meters(0.0),
82
+ )
83
+
84
+
85
+ @pytest.fixture
86
+ def access_target(
87
+ environment: Environment,
88
+ ground_station_lla: LLA,
89
+ ) -> AccessTarget:
90
+ return AccessTarget.from_position(
91
+ VisibilityCriterion.from_line_of_sight(environment),
92
+ Position.from_lla(
93
+ ground_station_lla,
94
+ environment.access_celestial_object_with_name("Earth"),
95
+ ),
96
+ )
97
+
98
+
99
+ @pytest.fixture
100
+ def access_generator(environment: Environment) -> AccessGenerator:
101
+ return AccessGenerator(
102
+ environment=environment,
103
+ step=Duration.seconds(10.0),
104
+ tolerance=Duration.seconds(1.0),
105
+ )
106
+
107
+
108
+ @pytest.fixture
109
+ def satellite_1_accesses(
110
+ satellite_1_trajectory: Orbit,
111
+ environment: Environment,
112
+ search_interval: Interval,
113
+ access_target: AccessTarget,
114
+ access_generator: AccessGenerator,
115
+ ) -> list[Access]:
116
+ return access_generator.compute_accesses(
117
+ interval=search_interval,
118
+ access_target=access_target,
119
+ to_trajectory=satellite_1_trajectory,
120
+ )
121
+
122
+
123
+ @pytest.fixture
124
+ def satellite_2_accesses(
125
+ satellite_2_trajectory: Orbit,
126
+ environment: Environment,
127
+ search_interval: Interval,
128
+ access_target: AccessTarget,
129
+ access_generator: AccessGenerator,
130
+ ) -> list[Access]:
131
+ return access_generator.compute_accesses(
132
+ interval=search_interval,
133
+ access_target=access_target,
134
+ to_trajectory=satellite_2_trajectory,
135
+ )
90
136
 
91
- accesses_2 = generator.compute_accesses(
92
- interval=search_interval,
93
- access_target=access_target,
94
- to_trajectory=orbit_2,
95
- )
96
137
 
97
- assert len(accesses_2) > 0
138
+ class TestDisplay:
139
+ def test_accesses_plot(
140
+ self,
141
+ environment: Environment,
142
+ earth: Celestial,
143
+ search_interval: Interval,
144
+ access_target: AccessTarget,
145
+ ground_station_lla: LLA,
146
+ satellite_1_trajectory: Orbit,
147
+ satellite_2_trajectory: Orbit,
148
+ satellite_1_accesses: list[Access],
149
+ satellite_2_accesses: list[Access],
150
+ ):
98
151
 
99
152
  accesses_plot = display.AccessesPlot(
100
153
  earth=earth,
101
154
  interval=search_interval,
102
155
  trajectory_step=Duration.minutes(5.0),
103
156
  access_step=Duration.seconds(10.0),
104
- ground_station_lla=ground_station_lla,
105
- color="green",
106
157
  )
107
158
 
108
159
  accesses_plot.add_satellite(
109
- trajectory=orbit_1,
110
- accesses=accesses_1,
160
+ trajectory=satellite_1_trajectory,
111
161
  rgb=[180, 0, 0],
112
162
  )
113
163
 
114
164
  accesses_plot.add_satellite(
115
- trajectory=orbit_2,
116
- accesses=accesses_2,
165
+ trajectory=satellite_2_trajectory,
117
166
  rgb=[0, 0, 180],
118
167
  )
168
+
169
+ accesses_plot.add_accesses(
170
+ trajectory=satellite_1_trajectory,
171
+ accesses=satellite_1_accesses,
172
+ rgb=[180, 0, 0],
173
+ )
174
+
175
+ accesses_plot.add_accesses(
176
+ trajectory=satellite_2_trajectory,
177
+ accesses=satellite_2_accesses,
178
+ rgb=[0, 0, 180],
179
+ )
180
+
181
+ accesses_plot.add_ground_station(
182
+ ground_station_lla,
183
+ color="green",
184
+ )
185
+
186
+ def test_accesses_plot_backwards_compatibility(
187
+ self,
188
+ environment: Environment,
189
+ earth: Celestial,
190
+ search_interval: Interval,
191
+ access_target: AccessTarget,
192
+ satellite_1_trajectory: Orbit,
193
+ satellite_2_trajectory: Orbit,
194
+ satellite_1_accesses: list[Access],
195
+ satellite_2_accesses: list[Access],
196
+ ground_station_lla: LLA,
197
+ ):
198
+ with pytest.warns(
199
+ DeprecationWarning,
200
+ match="Ground station and color are deprecated",
201
+ ):
202
+ accesses_plot = display.AccessesPlot(
203
+ earth=earth,
204
+ interval=search_interval,
205
+ trajectory_step=Duration.minutes(5.0),
206
+ access_step=Duration.seconds(10.0),
207
+ ground_station_lla=ground_station_lla,
208
+ color="green",
209
+ )
210
+
211
+ with pytest.warns(
212
+ DeprecationWarning,
213
+ match="Passing accesses to add_satellite\(\) is deprecated.*",
214
+ ):
215
+ accesses_plot.add_satellite(
216
+ trajectory=satellite_1_trajectory,
217
+ accesses=satellite_1_accesses,
218
+ rgb=[180, 0, 0],
219
+ )
220
+
221
+ accesses_plot.add_satellite(
222
+ trajectory=satellite_2_trajectory,
223
+ accesses=satellite_2_accesses,
224
+ rgb=[0, 0, 180],
225
+ )