• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

moeyensj / thor / 6733525095

02 Nov 2023 01:52PM UTC coverage: 40.544% (+0.9%) from 39.595%
6733525095

push

github

web-flow
Merge pull request #123 from moeyensj/v2.0-link-aims-sample

Link AIMS sample

301 of 301 new or added lines in 12 files covered. (100.0%)

1878 of 4632 relevant lines covered (40.54%)

0.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

54.44
/thor/tests/test_main.py
1
import pyarrow.compute as pc
1✔
2
import pytest
1✔
3
from adam_core.utils.helpers import make_observations, make_real_orbits
1✔
4

5
from ..config import Config
1✔
6
from ..main_2 import link_test_orbit, range_and_transform
1✔
7
from ..observations import Observations
1✔
8
from ..observations.filters import TestOrbitRadiusObservationFilter
1✔
9
from ..orbit import TestOrbit as THORbit
1✔
10

11
OBJECT_IDS = [
1✔
12
    "594913 'Aylo'chaxnim (2020 AV2)",
13
    "163693 Atira (2003 CP20)",
14
    "(2010 TK7)",
15
    "3753 Cruithne (1986 TO)",
16
    "54509 YORP (2000 PH5)",
17
    "2063 Bacchus (1977 HB)",
18
    "1221 Amor (1932 EA1)",
19
    "433 Eros (A898 PA)",
20
    "3908 Nyx (1980 PA)",
21
    "434 Hungaria (A898 RB)",
22
    "1876 Napolitania (1970 BA)",
23
    "2001 Einstein (1973 EB)",
24
    "2 Pallas (A802 FA)",
25
    "6 Hebe (A847 NA)",
26
    "6522 Aci (1991 NQ)",
27
    "10297 Lynnejones (1988 RJ13)",
28
    "17032 Edlu (1999 FM9)",
29
    "202930 Ivezic (1998 SG172)",
30
    "911 Agamemnon (A919 FB)",
31
    "1143 Odysseus (1930 BH)",
32
    "1172 Aneas (1930 UA)",
33
    "3317 Paris (1984 KF)",
34
    "5145 Pholus (1992 AD)",
35
    "5335 Damocles (1991 DA)",
36
    "15760 Albion (1992 QB1)",
37
    "15788 (1993 SB)",
38
    "15789 (1993 SC)",
39
    "1I/'Oumuamua (A/2017 U1)",
40
]
41
TOLERANCES = {
1✔
42
    "default": 0.1 / 3600,
43
    "594913 'Aylo'chaxnim (2020 AV2)": 2 / 3600,
44
    "1I/'Oumuamua (A/2017 U1)": 5 / 3600,
45
}
46

47

48
@pytest.fixture
1✔
49
def observations():
1✔
50
    return make_observations()
1✔
51

52

53
@pytest.fixture
1✔
54
def orbits():
1✔
55
    return make_real_orbits()
1✔
56

57

58
@pytest.fixture
1✔
59
def ray_cluster():
1✔
60
    import ray
×
61

62
    ray_initialized = False
×
63
    if not ray.is_initialized():
×
64
        ray.init(
×
65
            num_cpus=4, include_dashboard=False, namespace="THOR Integration Tests"
66
        )
67
        ray_initialized = True
×
68
    yield
×
69
    if ray_initialized:
×
70
        ray.shutdown()
×
71

72

73
def test_Orbit_generate_ephemeris_from_observations_empty(orbits):
1✔
74
    # Test that when passed empty observations, TestOrbit.generate_ephemeris_from_observations
75
    # returns a Value Error
76
    observations = Observations.empty()
1✔
77
    test_orbit = THORbit.from_orbits(orbits[0])
1✔
78
    with pytest.raises(ValueError, match="Observations must not be empty."):
1✔
79
        test_orbit.generate_ephemeris_from_observations(observations)
1✔
80

81

82
@pytest.mark.parametrize("object_id", OBJECT_IDS)
1✔
83
def test_range_and_transform(object_id, orbits, observations):
1✔
84

85
    orbit = orbits.select("object_id", object_id)
1✔
86
    exposures, detections, associations = observations
1✔
87

88
    # Make THOR observations from the detections and exposures
89
    observations = Observations.from_detections_and_exposures(detections, exposures)
1✔
90

91
    # Select the associations that match this object ID
92
    associations_i = associations.select("object_id", object_id)
1✔
93
    assert len(associations_i) == 90
1✔
94

95
    # Extract the observations that match this object ID
96
    obs_ids_expected = associations_i.detection_id.unique().sort()
1✔
97

98
    # Filter the observations to include only those that match this object
99
    observations = observations.apply_mask(
1✔
100
        pc.is_in(observations.detections.id, obs_ids_expected)
101
    )
102

103
    if object_id in TOLERANCES:
1✔
104
        tolerance = TOLERANCES[object_id]
1✔
105
    else:
106
        tolerance = TOLERANCES["default"]
1✔
107

108
    # Create a test orbit for this object
109
    test_orbit = THORbit.from_orbits(orbit)
1✔
110

111
    # Set a filter to include observations within 1 arcsecond of the predicted position
112
    # of the test orbit
113
    filters = [TestOrbitRadiusObservationFilter(radius=tolerance)]
1✔
114
    for filter in filters:
1✔
115
        observations = filter.apply(observations, test_orbit)
1✔
116

117
    # Run range and transform and make sure we get the correct observations back
118
    transformed_detections = range_and_transform(
1✔
119
        test_orbit,
120
        observations,
121
    )
122
    assert len(transformed_detections) == 90
1✔
123
    assert pc.all(
1✔
124
        pc.less_equal(pc.abs(transformed_detections.coordinates.theta_x), tolerance)
125
    ).as_py()
126
    assert pc.all(
1✔
127
        pc.less_equal(pc.abs(transformed_detections.coordinates.theta_y), tolerance)
128
    ).as_py()
129

130
    # Ensure we get all the object IDs back that we expect
131
    obs_ids_actual = transformed_detections.id.unique().sort()
1✔
132
    assert pc.all(pc.equal(obs_ids_actual, obs_ids_expected))
1✔
133

134

135
@pytest.mark.parametrize(
1✔
136
    "object_id",
137
    [
138
        pytest.param(OBJECT_IDS[0], marks=pytest.mark.xfail(reason="Fails OD")),
139
    ]
140
    + OBJECT_IDS[1:3]
141
    + [
142
        pytest.param(OBJECT_IDS[3], marks=pytest.mark.xfail(reason="Fails OD")),
143
        pytest.param(OBJECT_IDS[4], marks=pytest.mark.xfail(reason="Fails OD")),
144
        pytest.param(OBJECT_IDS[5], marks=pytest.mark.xfail(reason="Fails OD")),
145
    ]
146
    + [OBJECT_IDS[6]]
147
    + [
148
        pytest.param(OBJECT_IDS[7], marks=pytest.mark.xfail(reason="Fails OD")),
149
        pytest.param(OBJECT_IDS[8], marks=pytest.mark.xfail(reason="Fails OD")),
150
    ]
151
    + OBJECT_IDS[9:],
152
)
153
@pytest.mark.parametrize("parallelized", [True, False])
1✔
154
@pytest.mark.integration
1✔
155
def test_link_test_orbit(object_id, orbits, observations, parallelized, ray_cluster):
1✔
156

157
    config = Config()
×
158
    if parallelized:
×
159
        config.max_processes = 4
×
160
    else:
161
        config.max_processes = 1
×
162

163
    # Reduce the clustering grid size to speed up the test
164
    config.vx_bins = 10
×
165
    config.vy_bins = 10
×
166
    config.vx_min = -0.01
×
167
    config.vx_max = 0.01
×
168
    config.vy_min = -0.01
×
169
    config.vy_max = 0.01
×
170

171
    orbit = orbits.select("object_id", object_id)
×
172
    exposures, detections, associations = observations
×
173

174
    # Select the associations that match this object ID
175
    associations_i = associations.select("object_id", object_id)
×
176
    detections_i = detections.apply_mask(
×
177
        pc.is_in(detections.id, associations_i.detection_id)
178
    )
179
    exposures_i = exposures.apply_mask(pc.is_in(exposures.id, detections_i.exposure_id))
×
180
    assert len(associations_i) == 90
×
181

182
    # Limit detections to first two weeks
183
    time_mask = pc.and_(
×
184
        pc.greater_equal(detections_i.time.days, pc.min(detections_i.time.days)),
185
        pc.less_equal(
186
            detections_i.time.days, pc.min(detections_i.time.days).as_py() + 14
187
        ),
188
    )
189
    detections_i = detections_i.apply_mask(time_mask)
×
190
    exposures_i = exposures_i.apply_mask(
×
191
        pc.is_in(exposures_i.id, detections_i.exposure_id)
192
    )
193
    associations_i = associations_i.apply_mask(
×
194
        pc.is_in(associations_i.detection_id, detections_i.id)
195
    )
196

197
    # Extract the observations that match this object ID
198
    obs_ids_expected = associations_i.detection_id.unique().sort()
×
199

200
    # Make THOR observations from the detections and exposures
201
    observations = Observations.from_detections_and_exposures(detections_i, exposures_i)
×
202

203
    if object_id in TOLERANCES:
×
204
        config.cell_radius = TOLERANCES[object_id]
×
205
    else:
206
        config.cell_radius = TOLERANCES["default"]
×
207

208
    # Create a test orbit for this object
209
    test_orbit = THORbit.from_orbits(orbit)
×
210

211
    # Run link_test_orbit and make sure we get the correct observations back
212
    for i, results in enumerate(
×
213
        link_test_orbit(test_orbit, observations, config=config)
214
    ):
215
        if i == 4:
×
216
            od_orbits, od_orbit_members = results
×
217
        else:
218
            continue
×
219

220
    assert len(od_orbit_members) == len(obs_ids_expected)
×
221

222
    # Ensure we get all the object IDs back that we expect
223
    obs_ids_actual = od_orbit_members["obs_id"].values
×
224
    assert pc.all(pc.equal(obs_ids_actual, obs_ids_expected))
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc