Skip to content

Commit c2a515f

Browse files
Harrison #56 - PMCL - GLOWS: Refactor LoL1bNHK class into a function and make all its tests read from CDFs
1 parent 4df80a0 commit c2a515f

2 files changed

Lines changed: 34 additions & 37 deletions

File tree

imap_l3_processing/glows/l3e/glows_l3e_utils.py

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -127,29 +127,20 @@ def find_first_updated_cr(new_l3d: Path, old_l3d: str) -> Optional[int]:
127127

128128
return None
129129

130-
@dataclass
131-
class LoL1bNHK:
132-
epoch: np.ndarray
133-
angle: np.ndarray
134-
135-
@classmethod
136-
def read_from_cdf(cls, path: Path) -> LoL1bNHK:
137-
with CDF(str(path)) as cdf:
138-
epoch = cdf['epoch'][...]
139-
angle = cdf['pcc_coarse_pot_pri'][...]
140-
return cls(epoch, angle)
141-
142-
def get_pivot_angle(self) -> float:
143-
if len(self.epoch) == 0:
144-
return 90
145-
t0 = self.epoch[0]
146-
start = t0 + timedelta(hours=3)
147-
end = t0 + timedelta(hours=15)
148-
start_index, end_index = np.searchsorted(self.epoch, [start, end])
149-
angles = self.angle[start_index:end_index]
150-
if len(angles) == 0:
151-
return 90
152-
return np.round(np.median(angles))
130+
def get_lo_pivot_angle_from_l1b_file(path: Path) -> float:
131+
with CDF(str(path)) as cdf:
132+
epoch = cdf['epoch'][...]
133+
angles = cdf['pcc_coarse_pot_pri'][...]
134+
if len(epoch) == 0:
135+
return 90
136+
t0 = epoch[0]
137+
start = t0 + timedelta(hours=3)
138+
end = t0 + timedelta(hours=15)
139+
start_index, end_index = np.searchsorted(epoch, [start, end])
140+
angles_to_consider = angles[start_index:end_index]
141+
if len(angles_to_consider) == 0:
142+
return 90
143+
return np.round(np.median(angles_to_consider))
153144

154145
def get_lo_pivot_angles(repointings: list[int]) -> dict[int, float]:
155146
l1b_results = imap_data_access.query(
@@ -163,7 +154,7 @@ def get_lo_pivot_angles(repointings: list[int]) -> dict[int, float]:
163154
for repointing in repointings:
164155
if path := paths_by_repointing.get(repointing):
165156
downloaded_path = imap_data_access.download(path)
166-
result[repointing] = LoL1bNHK.read_from_cdf(downloaded_path).get_pivot_angle()
157+
result[repointing] = get_lo_pivot_angle_from_l1b_file(downloaded_path)
167158
else:
168159
result[repointing] = 90
169160
return result

tests/glows/l3e/test_glows_l3e_utils.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1+
import tempfile
12
import unittest
23
from datetime import datetime, timedelta
34
from pathlib import Path
45
from unittest.mock import patch, Mock, call, sentinel
56

67
import numpy as np
8+
from spacepy.pycdf import CDF
79

810
from imap_l3_processing.glows.l3e.glows_l3e_call_arguments import GlowsL3eCallArguments
911
from imap_l3_processing.glows.l3e.glows_l3e_utils import determine_call_args_for_l3e_executable, \
10-
determine_l3e_files_to_produce, find_first_updated_cr, LoL1bNHK, get_lo_pivot_angles
12+
determine_l3e_files_to_produce, find_first_updated_cr, get_lo_pivot_angles, \
13+
get_lo_pivot_angle_from_l1b_file
1114
from tests.test_helpers import get_test_data_path, create_mock_query_results
1215

1316

@@ -207,12 +210,12 @@ def test_find_first_updated_cr(self, mock_CDF, mock_download):
207210

208211
self.assertEqual(actual_cr, expected)
209212

210-
def test_lo_l1b_nhk_get_pivot_angle_integration(self):
213+
def test_get_lo_pivot_angle_from_l1b_file_real_cdf(self):
211214
l1b_file = get_test_data_path("glows/imap_lo_l1b_nhk_20260318-repoint00189_v003.cdf")
212-
actual = LoL1bNHK.read_from_cdf(l1b_file).get_pivot_angle()
215+
actual = get_lo_pivot_angle_from_l1b_file(l1b_file)
213216
self.assertEqual(90.0, actual)
214217

215-
def test_lo_l1b_nhk_get_pivot_angle(self):
218+
def test_get_lo_pivot_angle_from_l1b_file_scenarios(self):
216219
first_three_hours = [
217220
datetime(2026, 3, 20, 0, 45),
218221
datetime(2026, 3, 20, 2, 45),
@@ -240,12 +243,17 @@ def test_lo_l1b_nhk_get_pivot_angle(self):
240243
]
241244
for name, epochs, pivot_angles, expected in cases:
242245
with self.subTest(name):
243-
actual = LoL1bNHK(epochs, pivot_angles).get_pivot_angle()
244-
self.assertEqual(expected, actual)
245-
246-
@patch('imap_l3_processing.glows.l3e.glows_l3e_utils.LoL1bNHK')
246+
with tempfile.TemporaryDirectory() as tmp_dir:
247+
cdf_path = Path(tmp_dir,"l1b.cdf")
248+
with CDF(str(cdf_path), create=True) as cdf:
249+
cdf["epoch"] = epochs
250+
cdf["pcc_coarse_pot_pri"] = pivot_angles
251+
actual = get_lo_pivot_angle_from_l1b_file(cdf_path)
252+
self.assertEqual(expected, actual)
253+
254+
@patch('imap_l3_processing.glows.l3e.glows_l3e_utils.get_lo_pivot_angle_from_l1b_file')
247255
@patch('imap_l3_processing.glows.l3e.glows_l3e_utils.imap_data_access')
248-
def test_get_lo_pivot_angles(self, mock_imap_data_access, mock_nhk_model):
256+
def test_get_lo_pivot_angles(self, mock_imap_data_access, mock_get_pivot_angle_from_file):
249257
available_repointings = [1, 2, 3, 4, 5, 6]
250258
mock_imap_data_access.query.return_value = [
251259
{'file_path': f'file{i}.cdf', 'repointing': i}
@@ -261,10 +269,8 @@ def test_get_lo_pivot_angles(self, mock_imap_data_access, mock_nhk_model):
261269
Path("local/path/to/file6.cdf"): 84,
262270
}
263271
def mock_read_from_cdf(path: Path):
264-
result = Mock()
265-
result.get_pivot_angle.return_value = pivot_angles_by_file_path[path]
266-
return result
267-
mock_nhk_model.read_from_cdf.side_effect = mock_read_from_cdf
272+
return pivot_angles_by_file_path[path]
273+
mock_get_pivot_angle_from_file.side_effect = mock_read_from_cdf
268274

269275
result = get_lo_pivot_angles([3, 4, 6, 10])
270276

0 commit comments

Comments
 (0)