Skip to content

Commit c6a1a11

Browse files
authored
ULTRA l1b filter out events that are during a repointing (IMAP-Science-Operations-Center#2324)
* filter out events that were not during the current pointing
1 parent 4c4c107 commit c6a1a11

5 files changed

Lines changed: 98 additions & 9 deletions

File tree

imap_processing/tests/ultra/unit/test_de.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66

77
from imap_processing import imap_module_directory
88
from imap_processing.cdf.utils import load_cdf
9+
from imap_processing.spice.repoint import get_repoint_data
10+
from imap_processing.spice.time import met_to_ttj2000ns, ttj2000ns_to_et
911
from imap_processing.ultra.constants import UltraConstants
12+
from imap_processing.ultra.l1b.de import calculate_events_in_pointing
1013

1114
TEST_PATH = imap_module_directory / "tests" / "ultra" / "data" / "l1"
1215

@@ -119,3 +122,24 @@ def test_calculate_de(df_filt):
119122
len(l1b_de_dataset["epoch"]),
120123
3,
121124
)
125+
126+
127+
def test_calculate_events_in_pointing(use_fake_repoint_data_for_time):
128+
"""Tests calculate_events_in_pointing function."""
129+
use_fake_repoint_data_for_time(np.arange(511000000, 511000000 + 86400 * 5, 86400))
130+
repoint_id = 1
131+
repoint_data = get_repoint_data()
132+
pointing_start = repoint_data[repoint_data["repoint_id"] == repoint_id][
133+
"repoint_end_met"
134+
].values[0]
135+
# Create array of event times that are all within a pointing.
136+
event_times = np.arange(pointing_start, pointing_start + 10)
137+
# Edit the first event time to be during a repoint.
138+
event_times[0] = pointing_start - 1
139+
valid_events = np.ones_like(event_times, dtype=bool)
140+
in_poiting = calculate_events_in_pointing(
141+
repoint_id, ttj2000ns_to_et(met_to_ttj2000ns(event_times)), valid_events
142+
)
143+
# The first event should be False (not during a pointing), and the rest True.
144+
assert np.all(not in_poiting[0])
145+
assert np.all(in_poiting[1:])

imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from imap_processing import imap_module_directory
88
from imap_processing.quality_flags import ImapDEOutliersUltraFlags
99
from imap_processing.spice.spin import get_spin_data
10-
from imap_processing.spice.time import sct_to_et
10+
from imap_processing.spice.time import met_to_ttj2000ns, ttj2000ns_to_et
1111
from imap_processing.ultra.constants import UltraConstants
1212
from imap_processing.ultra.l1b.lookup_utils import get_angular_profiles
1313
from imap_processing.ultra.l1b.ultra_l1b_extended import (
@@ -559,8 +559,12 @@ def test_get_eventtimes(test_fixture, use_fake_spin_data_for_time):
559559
+ expected_max_df["spin_start_subsec_sclk"] / 1e6
560560
)
561561

562-
assert sct_to_et(spin_start_min.values[0]) == spin_starts.min()
563-
assert sct_to_et(spin_start_max.values[0]) == spin_starts.max()
562+
assert (
563+
ttj2000ns_to_et(met_to_ttj2000ns(spin_start_min.values[0])) == spin_starts.min()
564+
)
565+
assert (
566+
ttj2000ns_to_et(met_to_ttj2000ns(spin_start_max.values[0])) == spin_starts.max()
567+
)
564568

565569
event_times_min = spin_start_min.values[0] + spin_period_sec_min * (
566570
de_dataset["phase_angle"][0] / 720
@@ -569,8 +573,8 @@ def test_get_eventtimes(test_fixture, use_fake_spin_data_for_time):
569573
de_dataset["phase_angle"][-1] / 720
570574
)
571575

572-
assert sct_to_et(event_times_min) == event_times.min()
573-
assert sct_to_et(event_times_max) == event_times.max()
576+
assert ttj2000ns_to_et(met_to_ttj2000ns(event_times_min)) == event_times.min()
577+
assert ttj2000ns_to_et(met_to_ttj2000ns(event_times_max)) == event_times.max()
574578

575579

576580
@pytest.mark.external_test_data

imap_processing/ultra/l1b/de.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
ImapDEScatteringUltraFlags,
1010
)
1111
from imap_processing.spice.geometry import SpiceFrame
12+
from imap_processing.spice.repoint import get_repoint_data
13+
from imap_processing.spice.time import et_to_met
1214
from imap_processing.ultra.l1b.lookup_utils import get_geometric_factor
1315
from imap_processing.ultra.l1b.ultra_l1b_annotated import (
1416
get_annotated_particle_velocity,
@@ -74,6 +76,10 @@ def calculate_de(
7476
spin_number = get_spin_number(
7577
de_dataset["shcoarse"].values, de_dataset["spin"].values
7678
)
79+
repoint_id = de_dataset.attrs.get("Repointing", None)
80+
if repoint_id is not None:
81+
repoint_id = int(repoint_id.replace("repoint", ""))
82+
7783
de_dict["spin"] = spin_number
7884

7985
# Add already populated fields.
@@ -312,6 +318,14 @@ def calculate_de(
312318

313319
# Account for counts=0 (event times have FILL value)
314320
valid_events = event_times != FILLVAL_FLOAT32
321+
# TODO - find a better solution than filtering out data from repointings?
322+
if repoint_id is not None:
323+
in_pointing = calculate_events_in_pointing(
324+
repoint_id, event_times, valid_events
325+
)
326+
# Update valid_events to only include times within a pointing
327+
valid_events &= in_pointing
328+
315329
if np.any(valid_events):
316330
(
317331
sc_velocity[valid_events],
@@ -369,5 +383,49 @@ def calculate_de(
369383
de_dict["quality_scattering"] = scattering_quality_flags
370384

371385
dataset = create_dataset(de_dict, name, "l1b")
386+
if repoint_id is not None:
387+
# filter out the dataset to only include events in pointing
388+
dataset = dataset.isel(epoch=in_pointing)
372389

373390
return dataset
391+
392+
393+
def calculate_events_in_pointing(
394+
repoint_id: int, event_times: np.ndarray, valid_events: np.ndarray
395+
) -> np.ndarray:
396+
"""
397+
Calculate boolean array of events within a pointing.
398+
399+
Parameters
400+
----------
401+
repoint_id : int
402+
The repointing ID.
403+
event_times : np.ndarray
404+
Array of event times in ET.
405+
valid_events : np.ndarray
406+
Boolean array indicating valid events.
407+
408+
Returns
409+
-------
410+
in_pointing : np.ndarray
411+
Boolean array indicating whether each event is within the pointing period
412+
combined with the valid_events mask.
413+
"""
414+
# TODO add this as a helper function in repoint.py
415+
repoint_data = get_repoint_data()
416+
# To find the pointing start and stop, get the end of the current repointing
417+
# and the start of the next repointing
418+
repoint_row = repoint_data[repoint_data["repoint_id"] == repoint_id]
419+
next_repoint_row = repoint_data[repoint_data["repoint_id"] == repoint_id + 1]
420+
pointing_start_met = repoint_row["repoint_end_met"].values[0]
421+
pointing_end_met = next_repoint_row["repoint_start_met"].values[0]
422+
423+
# Create a boolean array for events within the pointing
424+
in_pointing = np.zeros(len(event_times), dtype=bool)
425+
426+
# Check which events are within the pointing
427+
in_pointing[valid_events] = (
428+
et_to_met(event_times[valid_events]) >= pointing_start_met
429+
) & (et_to_met(event_times[valid_events]) <= pointing_end_met)
430+
431+
return in_pointing

imap_processing/ultra/l1b/ultra_l1b_annotated.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ def get_annotated_particle_velocity(
5252
from_frame=instrument_frame,
5353
to_frame=spacecraft_frame,
5454
)
55-
5655
# Particle velocity in the pointing (DPS) frame wrt spacecraft.
5756
particle_velocity_dps_spacecraft = frame_transform(
5857
et=time,

imap_processing/ultra/l1b/ultra_l1b_extended.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
from imap_processing.quality_flags import ImapDEOutliersUltraFlags
1616
from imap_processing.spice.spin import get_spin_data
17-
from imap_processing.spice.time import sct_to_et
17+
from imap_processing.spice.time import met_to_ttj2000ns, ttj2000ns_to_et
1818
from imap_processing.ultra.constants import UltraConstants
1919
from imap_processing.ultra.l1b.lookup_utils import (
2020
get_angular_profiles,
@@ -996,17 +996,21 @@ def get_eventtimes(
996996
t_spin_period_sec * phase_angle/720
997997
"""
998998
spin_df = get_spin_data()
999+
9991000
index = np.searchsorted(spin_df["spin_number"].values, spin)
10001001
spin_starts = (
10011002
spin_df["spin_start_sec_sclk"].values[index]
10021003
+ spin_df["spin_start_subsec_sclk"].values[index] / 1e6
10031004
)
10041005

10051006
spin_period_sec = spin_df["spin_period_sec"].values[index]
1006-
10071007
event_times = spin_starts + spin_period_sec * (phase_angle / 720)
10081008

1009-
return sct_to_et(event_times), sct_to_et(spin_starts), spin_period_sec
1009+
return (
1010+
ttj2000ns_to_et(met_to_ttj2000ns(event_times)),
1011+
ttj2000ns_to_et(met_to_ttj2000ns(spin_starts)),
1012+
spin_period_sec,
1013+
)
10101014

10111015

10121016
def interpolate_fwhm(

0 commit comments

Comments
 (0)