Skip to content

Commit 8e125b1

Browse files
authored
Ultra l1c pset sensitivity calculation and minor organization (IMAP-Science-Operations-Center#1604)
1 parent 634b870 commit 8e125b1

16 files changed

Lines changed: 257 additions & 115 deletions

imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,43 @@ theta:
250250
LABLAXIS: theta
251251
UNITS: degrees
252252

253+
phi_fwhm:
254+
<<: *default_float32
255+
CATDESC: FWHM of the phi distribution.
256+
FIELDNAM: phi_fwhm
257+
LABLAXIS: phi fwhm
258+
UNITS: degrees
259+
260+
theta_fwhm:
261+
<<: *default_float32
262+
CATDESC: FWHM of the theta distribution.
263+
FIELDNAM: phi_fwhm
264+
LABLAXIS: phi fwhm
265+
UNITS: degrees
266+
253267
event_efficiency:
254268
<<: *default_float32
255269
CATDESC: Estimated event efficiency for this path through the instrument.
256270
FIELDNAM: event_efficiency
257271
LABLAXIS: event efficiency
258272
UNITS: " "
259273

274+
direct_event_unit_velocity:
275+
<<: *default_float32
276+
CATDESC: Unit vector of the direct event velocity in the instrument frame.
277+
DEPEND_1: component
278+
FIELDNAM: direct_event_unit_velocity
279+
LABLAXIS: direct event unit velocity
280+
UNITS: " "
281+
282+
direct_event_unit_position:
283+
<<: *default_float32
284+
CATDESC: Unit vector of the direct event position in the instrument frame.
285+
DEPEND_1: component
286+
FIELDNAM: direct_event_unit_position
287+
LABLAXIS: direct event unit position
288+
UNITS: " "
289+
260290
velocity_sc:
261291
<<: *default_float32
262292
CATDESC: x,y,z-components of the velocity vector of the ena in the spacecraft frame.

imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,6 @@ longitude:
3131
LABLAXIS: longitude
3232
UNITS: degrees
3333

34-
spin_angle:
35-
<<: *default
36-
CATDESC: Angular bin defined by central location of the bin
37-
FIELDNAM: spin_angle
38-
LABLAXIS: spin angle
39-
# TODO: come back to format
40-
UNITS: degrees
41-
42-
time_bin:
43-
<<: *default
44-
CATDESC: Time bin defined by central location of the bin.
45-
FIELDNAM: time_bin
46-
LABLAXIS: time bin
47-
# TODO: come back to format
48-
UNITS: seconds
49-
5034
species_bin:
5135
<<: *default
5236
CATDESC: Species bin defined by central location.
@@ -95,30 +79,6 @@ sid:
9579
# TODO: come back to format
9680
UNITS: " "
9781

98-
row:
99-
<<: *default
100-
CATDESC: Row number.
101-
FIELDNAM: row
102-
LABLAXIS: row
103-
# TODO: come back to format
104-
UNITS: " "
105-
106-
column:
107-
<<: *default
108-
CATDESC: Column number.
109-
FIELDNAM: column
110-
LABLAXIS: column
111-
# TODO: come back to format
112-
UNITS: " "
113-
114-
spin:
115-
<<: *default
116-
CATDESC: Spin number at integration start.
117-
FIELDNAM: spin
118-
LABLAXIS: spin
119-
# TODO: come back to format
120-
UNITS: " "
121-
12282
shcoarse:
12383
<<: *default
12484
CATDESC: CCSDS packet timestamp.
@@ -127,14 +87,6 @@ shcoarse:
12787
# TODO: come back to format
12888
UNITS: seconds
12989

130-
packetdata:
131-
<<: *default
132-
CATDESC: A 2D numpy array representing pixel values. Each pixel is stored as an unsigned 16-bit integer.
133-
FIELDNAM: packetdata
134-
LABLAXIS: packet data
135-
# TODO: come back to format
136-
UNITS: " "
137-
13890
energy_bin_delta:
13991
<<: *default_float32
14092
CATDESC: Difference between the energy bin edges.

imap_processing/tests/ultra/unit/test_de.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,3 @@ def test_calculate_de(l1b_de_dataset, df_filt):
113113
len(l1b_de_dataset["epoch"]),
114114
3,
115115
)
116-
117-
# Event efficiency
118-
assert np.allclose(
119-
l1b_de_dataset["event_efficiency"],
120-
np.full(len(l1b_de_dataset["epoch"]), np.nan),
121-
equal_nan=True,
122-
)

imap_processing/tests/ultra/unit/test_lookup_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def test_get_egy_norm():
6666
def test_get_image_params():
6767
"""Tests function get_image_params."""
6868

69-
image_params = get_image_params("XFTLTOFF")
69+
image_params = get_image_params("XFTLTOFF", "ultra45")
7070

7171
assert image_params == 49.3
7272

imap_processing/tests/ultra/unit/test_spacecraft_pset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def test_pset():
3030
# This is just setting up the data so that it is in the format of l1b_de_dataset.
3131
test_path = TEST_PATH / "ultra-90_raw_event_data_shortened.csv"
3232
df = pd.read_csv(test_path)
33-
instrument_velocity = get_de_velocity(
33+
instrument_velocity, _, _ = get_de_velocity(
3434
(df["Xf"], df["Yf"]), (df["Xb"], df["Yb"]), df["d"], df["TOF"].values
3535
)
3636

imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def test_get_front_x_position(
6464
xf = get_front_x_position(
6565
de_dataset["start_type"].data,
6666
de_dataset["start_pos_tdc"].data,
67+
"ultra45",
6768
)
6869

6970
assert xf == pytest.approx(df_filt["Xf"].astype("float"), 1e-5)
@@ -121,7 +122,9 @@ def test_get_ssd_back_position_and_tof_offset(
121122
):
122123
"""Tests get_ssd_back_position function."""
123124
_, _, _, de_dataset = test_fixture
124-
yb, tof_offset, ssd_number = get_ssd_back_position_and_tof_offset(de_dataset)
125+
yb, tof_offset, ssd_number = get_ssd_back_position_and_tof_offset(
126+
de_dataset, "ultra45"
127+
)
125128

126129
df = pd.read_csv(events_fsw_comparison_theta_0)
127130
df_filt = df[(df["StartType"] != -1) & (df["StopType"] >= 8)]
@@ -238,7 +241,7 @@ def test_get_de_velocity(test_fixture):
238241
for col in ["Xf", "Yf", "Xb", "Yb", "d", "TOF"]
239242
)
240243

241-
v = get_de_velocity(
244+
v, vhat, r = get_de_velocity(
242245
(test_xf, test_yf),
243246
(test_xb, test_yb),
244247
test_d,
@@ -265,6 +268,42 @@ def test_get_de_velocity(test_fixture):
265268
atol=1e-01,
266269
rtol=0,
267270
)
271+
np.testing.assert_allclose(
272+
vhat[test_tof > 0][:, 0],
273+
df_ph["vhatX"].astype("float").values[test_tof > 0],
274+
atol=1e-01,
275+
rtol=0,
276+
)
277+
np.testing.assert_allclose(
278+
vhat[test_tof > 0][:, 1],
279+
df_ph["vhatY"].astype("float").values[test_tof > 0],
280+
atol=1e-01,
281+
rtol=0,
282+
)
283+
np.testing.assert_allclose(
284+
vhat[test_tof > 0][:, 2],
285+
df_ph["vhatZ"].astype("float").values[test_tof > 0],
286+
atol=1e-01,
287+
rtol=0,
288+
)
289+
np.testing.assert_allclose(
290+
r[test_tof > 0][:, 0],
291+
-df_ph["vhatX"].astype("float").values[test_tof > 0],
292+
atol=1e-01,
293+
rtol=0,
294+
)
295+
np.testing.assert_allclose(
296+
r[test_tof > 0][:, 1],
297+
-df_ph["vhatY"].astype("float").values[test_tof > 0],
298+
atol=1e-01,
299+
rtol=0,
300+
)
301+
np.testing.assert_allclose(
302+
r[test_tof > 0][:, 2],
303+
-df_ph["vhatZ"].astype("float").values[test_tof > 0],
304+
atol=1e-01,
305+
rtol=0,
306+
)
268307

269308

270309
def test_get_ssd_tof(test_fixture):
@@ -273,7 +312,7 @@ def test_get_ssd_tof(test_fixture):
273312
df_ssd = df_filt[np.isin(df_filt["StopType"], [StopType.SSD.value])]
274313
test_xf = df_filt["Xf"].astype("float").values
275314

276-
ssd_tof = get_ssd_tof(de_dataset, test_xf)
315+
ssd_tof = get_ssd_tof(de_dataset, test_xf, "ultra45")
277316

278317
np.testing.assert_allclose(
279318
ssd_tof, df_ssd["TOF"].astype("float"), atol=1e-05, rtol=0
@@ -296,7 +335,7 @@ def test_get_de_energy_kev(test_fixture):
296335
for col in ["Xf", "Yf", "Xb", "Yb", "d", "TOF"]
297336
)
298337

299-
v = get_de_velocity(
338+
v, v_hat, r_hat = get_de_velocity(
300339
(test_xf, test_yf),
301340
(test_xb, test_yb),
302341
test_d,
@@ -315,7 +354,7 @@ def test_get_energy_ssd(test_fixture):
315354
"""Tests get_energy_ssd function."""
316355
df_filt, _, _, de_dataset = test_fixture
317356
df_ssd = df_filt[np.isin(df_filt["StopType"], [StopType.SSD.value])]
318-
_, _, ssd_number = get_ssd_back_position_and_tof_offset(de_dataset)
357+
_, _, ssd_number = get_ssd_back_position_and_tof_offset(de_dataset, "ultra45")
319358
energy = get_energy_ssd(de_dataset, ssd_number)
320359
test_energy = df_ssd["Energy"].astype("float")
321360

@@ -334,7 +373,11 @@ def test_get_energy_pulse_height(test_fixture):
334373
test_yb = df_filt["Yb"].astype("float").values
335374

336375
energy = get_energy_pulse_height(
337-
de_dataset["stop_type"].data, de_dataset["energy_ph"].data, test_xb, test_yb
376+
de_dataset["stop_type"].data,
377+
de_dataset["energy_ph"].data,
378+
test_xb,
379+
test_yb,
380+
"ultra45",
338381
)
339382
test_energy = df_ph["Energy"].astype("float")
340383

imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
get_spacecraft_exposure_times,
1717
get_spacecraft_histogram,
1818
get_spacecraft_sensitivity,
19+
grid_sensitivity,
1920
)
2021

2122
BASE_PATH = imap_module_directory / "ultra" / "lookup_tables"
@@ -171,9 +172,12 @@ def test_get_spacecraft_sensitivity():
171172
df_efficiencies = pd.read_csv(efficiences)
172173
df_geometric_function = pd.read_csv(geometric_function)
173174

174-
sensitivity = get_spacecraft_sensitivity(df_efficiencies, df_geometric_function)
175+
sensitivity, energy_vals, right_ascension, declination = get_spacecraft_sensitivity(
176+
df_efficiencies, df_geometric_function
177+
)
175178

176-
assert sensitivity.shape == df_efficiencies.shape
179+
assert sensitivity.shape == (df_efficiencies.shape[0], df_efficiencies.shape[1] - 2)
180+
assert np.array_equal(energy_vals, np.arange(3.0, 80.5, 0.5))
177181

178182
df_efficiencies_test = pd.DataFrame(
179183
{"3.0keV": [1.0, 2.0], "3.5keV": [3.0, 4.0], "4.0keV": [5.0, 6.0]}
@@ -192,3 +196,26 @@ def test_get_spacecraft_sensitivity():
192196
assert np.allclose(
193197
df_sensitivity_test.to_numpy(), expected_sensitivity.to_numpy(), atol=1e-6
194198
)
199+
200+
201+
@pytest.mark.external_test_data
202+
def test_grid_sensitivity():
203+
"""Tests grid_sensitivity function."""
204+
efficiencies_path = TEST_PATH / "Ultra_90_DPS_efficiencies_all.csv"
205+
geometric_function_path = TEST_PATH / "ultra_90_dps_gf.csv"
206+
207+
df_efficiencies = pd.read_csv(efficiencies_path)
208+
df_geometric_function = pd.read_csv(geometric_function_path)
209+
210+
sensitivity, energy_vals, ra, dec = get_spacecraft_sensitivity(
211+
df_efficiencies, df_geometric_function
212+
)
213+
214+
expected_result = sensitivity["3.0keV"].values
215+
result = grid_sensitivity(df_efficiencies, df_geometric_function, 3.0)
216+
217+
assert np.allclose(result, expected_result, atol=1e-5)
218+
219+
# Check that out-of-bounds energy returns all NaNs
220+
result = grid_sensitivity(df_efficiencies, df_geometric_function, 2.5)
221+
assert np.isnan(result).all()

imap_processing/ultra/l1b/de.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
get_eventtimes,
2121
get_front_x_position,
2222
get_front_y_position,
23+
get_fwhm,
2324
get_path_length,
2425
get_ph_tof_and_back_positions,
2526
get_phi_theta,
@@ -104,11 +105,14 @@ def calculate_de(de_dataset: xr.Dataset, name: str) -> xr.Dataset:
104105
event_times = np.full(len(de_dataset["epoch"]), np.nan, dtype=np.float64)
105106
spin_starts = np.full(len(de_dataset["epoch"]), np.nan, dtype=np.float64)
106107
spin_period_sec = np.full(len(de_dataset["epoch"]), np.nan, dtype=np.float64)
108+
start_type = np.full(len(de_dataset["epoch"]), np.nan, dtype=np.uint8)
107109

108110
xf[valid_indices] = get_front_x_position(
109111
de_dataset["start_type"].data[valid_indices],
110112
de_dataset["start_pos_tdc"].data[valid_indices],
113+
f"ultra{sensor}",
111114
)
115+
start_type[valid_indices] = de_dataset["start_type"].data[valid_indices]
112116

113117
(
114118
event_times[valid_indices],
@@ -131,6 +135,7 @@ def calculate_de(de_dataset: xr.Dataset, name: str) -> xr.Dataset:
131135
de_dataset["energy_ph"].data[ph_indices],
132136
xb[ph_indices],
133137
yb[ph_indices],
138+
f"ultra{sensor}",
134139
)
135140
r[ph_indices] = get_path_length(
136141
(xf[ph_indices], yf[ph_indices]),
@@ -151,8 +156,10 @@ def calculate_de(de_dataset: xr.Dataset, name: str) -> xr.Dataset:
151156
)
152157

153158
# SSD
154-
tof[ssd_indices] = get_ssd_tof(de_dataset, xf)
155-
yb[ssd_indices], _, ssd_number = get_ssd_back_position_and_tof_offset(de_dataset)
159+
tof[ssd_indices] = get_ssd_tof(de_dataset, xf, f"ultra{sensor}")
160+
yb[ssd_indices], _, ssd_number = get_ssd_back_position_and_tof_offset(
161+
de_dataset, f"ultra{sensor}"
162+
)
156163
xc[ssd_indices] = np.zeros(len(ssd_indices))
157164
xb[ssd_indices] = np.zeros(len(ssd_indices))
158165
etof[ssd_indices] = np.zeros(len(ssd_indices))
@@ -195,13 +202,15 @@ def calculate_de(de_dataset: xr.Dataset, name: str) -> xr.Dataset:
195202
de_dict["phi"] = phi
196203
de_dict["theta"] = theta
197204

198-
v = get_de_velocity(
205+
v, vhat, r = get_de_velocity(
199206
(de_dict["x_front"], de_dict["y_front"]),
200207
(de_dict["x_back"], de_dict["y_back"]),
201208
de_dict["front_back_distance"],
202209
de_dict["tof_start_stop"],
203210
)
204211
de_dict["direct_event_velocity"] = v.astype(np.float32)
212+
de_dict["direct_event_unit_velocity"] = vhat.astype(np.float32)
213+
de_dict["direct_event_unit_position"] = r.astype(np.float32)
205214

206215
de_dict["tof_energy"] = get_de_energy_kev(v, species_bin)
207216
de_dict["energy"] = energy
@@ -224,9 +233,12 @@ def calculate_de(de_dataset: xr.Dataset, name: str) -> xr.Dataset:
224233
de_dict["energy_spacecraft"] = get_de_energy_kev(sc_dps_velocity, species_bin)
225234
de_dict["energy_heliosphere"] = get_de_energy_kev(helio_velocity, species_bin)
226235

227-
# TODO: TBD.
228-
de_dict["event_efficiency"] = np.full(
229-
len(de_dataset["epoch"]), np.nan, dtype=np.float32
236+
de_dict["phi_fwhm"], de_dict["theta_fwhm"] = get_fwhm(
237+
start_type,
238+
f"ultra{sensor}",
239+
de_dict["tof_energy"],
240+
de_dict["phi"],
241+
de_dict["theta"],
230242
)
231243

232244
dataset = create_dataset(de_dict, name, "l1b")

0 commit comments

Comments
 (0)