Skip to content

Commit 804b7f3

Browse files
authored
BUG - Lo Hist Rate L1B - Swap ESA Step and Az dims, intialize exposure factor to 1 instead of 0 (#2466)
* swapped esa step and az dims, inititalize exposure factor to 1 * minor xarray usage fixes
1 parent da17246 commit 804b7f3

File tree

2 files changed

+74
-69
lines changed

2 files changed

+74
-69
lines changed

imap_processing/lo/l1b/lo_l1b.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,12 +1177,12 @@ def initialize_l1b_histrates(
11771177
"""
11781178
l1b_histrates = xr.Dataset(
11791179
coords={
1180-
"epoch": l1a_hist["epoch"],
1180+
"epoch": xr.DataArray(l1a_hist["epoch"].values, dims=["epoch"]),
1181+
"esa_step": l1a_hist["esa_step"],
11811182
"spin_bin_6": xr.DataArray(
11821183
l1a_hist["azimuth_6"].values,
11831184
dims=["spin_bin_6"],
11841185
),
1185-
"esa_step": l1a_hist["esa_step"],
11861186
},
11871187
attrs=attr_mgr_l1b.get_global_attributes(logical_source),
11881188
)
@@ -1195,13 +1195,13 @@ def initialize_l1b_histrates(
11951195
# Copy over fields from L1A DE that will not change in L1B processing
11961196
l1b_histrates["h_counts"] = xr.DataArray(
11971197
l1a_hist["hydrogen"].values,
1198-
dims=["epoch", "spin_bin_6", "esa_step"],
1198+
dims=["epoch", "esa_step", "spin_bin_6"],
11991199
# TODO: Add hydrogen to YAML file
12001200
# attrs=attr_mgr.get_variable_attributes("hydrogen"),
12011201
)
12021202
l1b_histrates["o_counts"] = xr.DataArray(
12031203
l1a_hist["oxygen"].values,
1204-
dims=["epoch", "spin_bin_6", "esa_step"],
1204+
dims=["epoch", "esa_step", "spin_bin_6"],
12051205
# TODO: Add oxygen to YAML file
12061206
# attrs=attr_mgr.get_variable_attributes("oxygen"),
12071207
)
@@ -1254,8 +1254,12 @@ def resweep_histogram_data(
12541254
o_counts_reswept = np.zeros_like(l1b_histrates["o_counts"].values)
12551255

12561256
# Get the number of azimuth bins from the l1b_histrates dataset
1257-
num_azimuth = l1b_histrates["h_counts"].shape[1]
1258-
exposure_factor = np.zeros((len(epochs), num_azimuth, 7), dtype=int)
1257+
num_azimuth = l1b_histrates.sizes["spin_bin_6"]
1258+
# initialize exposure factor to 1 as this will be used to scale (multiply)
1259+
# the exposure time later
1260+
exposure_factor = np.full(
1261+
(len(epochs), l1b_histrates.sizes["esa_step"], num_azimuth), 1, dtype=int
1262+
)
12591263

12601264
for epoch_idx, epoch in enumerate(epoch_utc):
12611265
# Get only the date portion of the epoch string for comparison with the
@@ -1289,7 +1293,6 @@ def resweep_histogram_data(
12891293
logger.warning(f"No LUT entries found for table index {lut_table_idx}")
12901294
h_counts_reswept[epoch_idx] = l1b_histrates["h_counts"].values[epoch_idx]
12911295
o_counts_reswept[epoch_idx] = l1b_histrates["o_counts"].values[epoch_idx]
1292-
exposure_factor[epoch_idx] = 1
12931296
continue
12941297

12951298
# Sort the LUT entries by E-Step_Idx to ensure correct mapping order
@@ -1309,8 +1312,8 @@ def resweep_histogram_data(
13091312
# TODO: Change all instances of azimuth to spin bin
13101313
# Resweep the counts for each spin bin using the energy step mapping
13111314
for az_idx in range(num_azimuth):
1312-
h_original = l1b_histrates["h_counts"].values[epoch_idx, az_idx, :]
1313-
o_original = l1b_histrates["o_counts"].values[epoch_idx, az_idx, :]
1315+
h_original = l1b_histrates["h_counts"].values[epoch_idx, :, az_idx]
1316+
o_original = l1b_histrates["o_counts"].values[epoch_idx, :, az_idx]
13141317

13151318
# Loop through the original ESA step indices and map to the true ESA steps
13161319
for orig_idx, true_esa_step in energy_step_mapping.items():
@@ -1319,16 +1322,17 @@ def resweep_histogram_data(
13191322
# Resweep the counts into the true ESA step
13201323
# (convert to 0-based index)
13211324
reswept_idx = true_esa_step - 1
1322-
h_counts_reswept[epoch_idx, az_idx, reswept_idx] += h_original[
1325+
h_counts_reswept[epoch_idx, reswept_idx, az_idx] += h_original[
13231326
orig_idx
13241327
]
1325-
o_counts_reswept[epoch_idx, az_idx, reswept_idx] += o_original[
1328+
o_counts_reswept[epoch_idx, reswept_idx, az_idx] += o_original[
13261329
orig_idx
13271330
]
13281331
# If a reswept was needed for this index, increment the exposure
13291332
# factor to so the exposure time can be scaled accordingly
13301333
if orig_idx != reswept_idx:
1331-
exposure_factor[epoch_idx, az_idx, reswept_idx] += 1
1334+
exposure_factor[epoch_idx, reswept_idx, az_idx] += 1
1335+
13321336
else:
13331337
logger.warning(
13341338
f"Original ESA index {orig_idx} or "
@@ -1386,8 +1390,8 @@ def calculate_histogram_rates(
13861390

13871391
h_rates = np.zeros_like(h_counts, dtype=float)
13881392
o_rates = np.zeros_like(o_counts, dtype=float)
1389-
num_azimuth = h_counts.shape[1]
1390-
exposure_times = np.zeros((len(epochs), num_azimuth, 7), dtype=float)
1393+
num_azimuth = h_counts.shape[2]
1394+
exposure_times = np.zeros((len(epochs), 7, num_azimuth), dtype=float)
13911395

13921396
# Calculate rates for each epoch
13931397
for epoch_idx, epoch in enumerate(epochs):
@@ -1409,7 +1413,6 @@ def calculate_histogram_rates(
14091413
base_exposure_time = (
14101414
4 * avg_spin_durations_per_cycle.values[spin_cycle_idx] / 60
14111415
)
1412-
14131416
# Scale the exposure time by the exposure factor from resweeping
14141417
scaled_exposure = base_exposure_time * exposure_factor[epoch_idx, ...]
14151418
# Avoid division by zero by setting zero exposure times to NaN
@@ -1420,7 +1423,7 @@ def calculate_histogram_rates(
14201423

14211424
l1b_histrates["exposure_time"] = xr.DataArray(
14221425
exposure_times,
1423-
dims=["epoch", "spin_bin_6", "esa_step"],
1426+
dims=["epoch", "esa_step", "spin_bin_6"],
14241427
)
14251428
l1b_histrates["h_rates"] = xr.DataArray(
14261429
h_rates,

imap_processing/tests/lo/test_lo_l1b.py

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,13 @@ def l1b_histrates():
9696
)
9797
l1b_histrates = xr.Dataset(
9898
{
99-
"h_counts": (("epoch", "azimuth_6", "esa_step"), np.zeros((2, 60, 7))),
100-
"o_counts": (("epoch", "azimuth_6", "esa_step"), np.zeros((2, 60, 7))),
99+
"h_counts": (("epoch", "esa_step", "azimuth_6"), np.zeros((2, 7, 60))),
100+
"o_counts": (("epoch", "esa_step", "azimuth_6"), np.zeros((2, 7, 60))),
101101
},
102102
coords={
103103
"epoch": epoch_date,
104-
"azimuth_6": np.arange(60),
105104
"esa_step": np.arange(1, 8),
105+
"azimuth_6": np.arange(60),
106106
},
107107
)
108108

@@ -114,13 +114,13 @@ def l1a_hist():
114114
epoch_date = et_to_ttj2000ns(str_to_et(["2025-04-15T02:00:00"]))
115115
l1a_hist = xr.Dataset(
116116
{
117-
"hydrogen": (("epoch", "azimuth_6", "esa_step"), np.zeros((1, 60, 7))),
118-
"oxygen": (("epoch", "azimuth_6", "esa_step"), np.zeros((1, 60, 7))),
117+
"hydrogen": (("epoch", "esa_step", "azimuth_6"), np.zeros((1, 7, 60))),
118+
"oxygen": (("epoch", "esa_step", "azimuth_6"), np.zeros((1, 7, 60))),
119119
},
120120
coords={
121121
"epoch": epoch_date,
122-
"azimuth_6": np.arange(60),
123122
"esa_step": np.arange(1, 8),
123+
"azimuth_6": np.arange(60),
124124
},
125125
)
126126
return l1a_hist
@@ -787,37 +787,39 @@ def test_resweep_histogram_success(anc_dependencies):
787787
epoch_date = et_to_ttj2000ns(
788788
str_to_et(["2025-04-15T02:00:00", "2025-04-15T03:00:00"])
789789
)
790-
l1b_de = xr.Dataset(
790+
l1b_histrate = xr.Dataset(
791791
{
792-
"h_counts": (("epoch", "azimuth_6", "esa_step"), np.zeros((2, 60, 7))),
793-
"o_counts": (("epoch", "azimuth_6", "esa_step"), np.zeros((2, 60, 7))),
792+
"h_counts": (("epoch", "esa_step", "azimuth_6"), np.zeros((2, 7, 60))),
793+
"o_counts": (("epoch", "esa_step", "azimuth_6"), np.zeros((2, 7, 60))),
794794
},
795795
coords={
796796
"epoch": epoch_date,
797-
"azimuth_6": np.arange(60),
798797
"esa_step": np.arange(1, 8),
798+
"spin_bin_6": np.arange(60),
799799
},
800800
)
801-
exposure_factor_expected = np.zeros((2, 60, 7))
802-
exposure_factor_expected[:, :, 0] = 1
801+
exposure_factor_expected = np.full((2, 7, 60), 1)
802+
exposure_factor_expected[:, 0, :] = 2
803803

804-
l1b_de.h_counts[0, 0, 0] = 5
805-
l1b_de.h_counts[0, 0, 1] = 10
806-
l1b_de.h_counts[0, 0, 2] = 2
804+
l1b_histrate.h_counts[0, 0, 0] = 5
805+
l1b_histrate.h_counts[0, 1, 0] = 10
806+
l1b_histrate.h_counts[0, 2, 0] = 2
807807

808-
l1b_de.o_counts[1, 0, 0] = 2
809-
l1b_de.o_counts[1, 0, 1] = 3
810-
l1b_de.o_counts[1, 0, 2] = 4
808+
l1b_histrate.o_counts[1, 0, 0] = 2
809+
l1b_histrate.o_counts[1, 1, 0] = 3
810+
l1b_histrate.o_counts[1, 2, 0] = 4
811811

812-
l1b_histrates, exposure_factor = resweep_histogram_data(l1b_de, anc_dependencies)
812+
l1b_histrates, exposure_factor = resweep_histogram_data(
813+
l1b_histrate, anc_dependencies
814+
)
813815

814816
assert l1b_histrates.h_counts[0, 0, 0] == 15
815-
assert l1b_histrates.h_counts[0, 0, 1] == 0
816-
assert l1b_histrates.h_counts[0, 0, 2] == 2
817+
assert l1b_histrates.h_counts[0, 1, 0] == 0
818+
assert l1b_histrates.h_counts[0, 2, 0] == 2
817819

818820
assert l1b_histrates.o_counts[1, 0, 0] == 5
819-
assert l1b_histrates.o_counts[1, 0, 1] == 0
820-
assert l1b_histrates.o_counts[1, 0, 2] == 4
821+
assert l1b_histrates.o_counts[1, 1, 0] == 0
822+
assert l1b_histrates.o_counts[1, 2, 0] == 4
821823

822824
assert np.array_equal(exposure_factor, exposure_factor_expected)
823825

@@ -827,43 +829,43 @@ def test_resweep_histogram_no_date(anc_dependencies):
827829
epoch_date = et_to_ttj2000ns(
828830
str_to_et(["2025-04-25T02:00:00", "2025-04-25T03:00:00"])
829831
)
830-
l1b_de = xr.Dataset(
832+
l1b_histrate = xr.Dataset(
831833
{
832-
"h_counts": (("epoch", "azimuth_6", "esa_step"), np.zeros((2, 60, 7))),
833-
"o_counts": (("epoch", "azimuth_6", "esa_step"), np.zeros((2, 60, 7))),
834+
"h_counts": (("epoch", "esa_step", "azimuth_6"), np.zeros((2, 7, 60))),
835+
"o_counts": (("epoch", "esa_step", "azimuth_6"), np.zeros((2, 7, 60))),
834836
},
835837
coords={
836838
"epoch": epoch_date,
837-
"azimuth_6": np.arange(60),
838839
"esa_step": np.arange(1, 8),
840+
"spin_bin_6": np.arange(60),
839841
},
840842
)
841843

842-
l1b_de.h_counts[0, 0, 0] = 5
843-
l1b_de.h_counts[0, 0, 1] = 10
844-
l1b_de.h_counts[0, 0, 2] = 2
844+
l1b_histrate.h_counts[0, 0, 0] = 5
845+
l1b_histrate.h_counts[0, 1, 0] = 10
846+
l1b_histrate.h_counts[0, 2, 0] = 2
845847

846848
with pytest.raises(
847849
ValueError,
848850
match="No sweep table entry found for date "
849851
"2025-04-25T02:00:00.000 at epoch idx 0",
850852
):
851-
resweep_histogram_data(l1b_de, anc_dependencies)
853+
resweep_histogram_data(l1b_histrate, anc_dependencies)
852854

853855

854856
def test_resweep_histogram_multiple_lut(anc_dependencies):
855857
epoch_date = et_to_ttj2000ns(
856858
str_to_et(["2025-04-16T02:00:00", "2025-04-16T03:00:00"])
857859
)
858-
l1b_de = xr.Dataset(
860+
l1b_histrate = xr.Dataset(
859861
{
860-
"h_counts": (("epoch", "azimuth_6", "esa_step"), np.zeros((2, 60, 7))),
861-
"o_counts": (("epoch", "azimuth_6", "esa_step"), np.zeros((2, 60, 7))),
862+
"h_counts": (("epoch", "esa_step", "azimuth_6"), np.zeros((2, 7, 60))),
863+
"o_counts": (("epoch", "esa_step", "azimuth_6"), np.zeros((2, 7, 60))),
862864
},
863865
coords={
864866
"epoch": epoch_date,
865-
"azimuth_6": np.arange(60),
866867
"esa_step": np.arange(1, 8),
868+
"spin_bin_6": np.arange(60),
867869
},
868870
)
869871

@@ -872,7 +874,7 @@ def test_resweep_histogram_multiple_lut(anc_dependencies):
872874
match=f"Expected exactly 1 unique LUT_table "
873875
f"value for date 2025-04-16, but found 2:{[1, 2]}",
874876
):
875-
resweep_histogram_data(l1b_de, anc_dependencies)
877+
resweep_histogram_data(l1b_histrate, anc_dependencies)
876878

877879

878880
def test_calculate_histogram_rates(l1b_histrates):
@@ -889,32 +891,32 @@ def test_calculate_histogram_rates(l1b_histrates):
889891
]
890892
)
891893
avg_spin_durations_per_cycle = xr.DataArray([30, 15])
892-
exposure_factor = np.zeros((2, 60, 7))
894+
exposure_factor = np.zeros((2, 7, 60))
893895
exposure_factor[0, 0, 0] = 1
894896
l1b_histrates.h_counts[0, 0, 0] = 30
895-
l1b_histrates.h_counts[0, 0, 1] = 10
896-
l1b_histrates.h_counts[0, 0, 2] = 2
897+
l1b_histrates.h_counts[0, 1, 0] = 10
898+
l1b_histrates.h_counts[0, 2, 0] = 2
897899
l1b_histrates.h_counts[1, 0, 0] = 15
898-
l1b_histrates.h_counts[1, 0, 1] = 30
899-
l1b_histrates.h_counts[1, 0, 2] = 45
900+
l1b_histrates.h_counts[1, 1, 0] = 30
901+
l1b_histrates.h_counts[1, 2, 0] = 45
900902

901903
l1b_histrates.o_counts[0, 0, 0] = 100
902-
l1b_histrates.o_counts[0, 0, 1] = 50
903-
l1b_histrates.o_counts[0, 0, 2] = 25
904+
l1b_histrates.o_counts[0, 1, 0] = 50
905+
l1b_histrates.o_counts[0, 2, 0] = 25
904906
l1b_histrates.o_counts[1, 0, 0] = 2
905-
l1b_histrates.o_counts[1, 0, 1] = 3
906-
l1b_histrates.o_counts[1, 0, 2] = 4
907+
l1b_histrates.o_counts[1, 1, 0] = 3
908+
l1b_histrates.o_counts[1, 2, 0] = 4
907909

908910
l1b_histrate = calculate_histogram_rates(
909911
l1b_histrates, acq_start, acq_end, avg_spin_durations_per_cycle, exposure_factor
910912
)
911913

912914
hist_rates_h_epoch_0 = l1b_histrate["h_rates"]
913915
hist_rates_h_epoch_0[0, :, :] = hist_rates_h_epoch_0[0, :, :] / 2
914-
hist_rates_h_epoch_0[0, 0, :] = hist_rates_h_epoch_0[0, 0, :] / 2
916+
hist_rates_h_epoch_0[0, :, 0] = hist_rates_h_epoch_0[0, :, 0] / 2
915917
hist_rates_o_epoch_0 = l1b_histrate["o_rates"]
916918
hist_rates_o_epoch_0[0, :, :] = hist_rates_o_epoch_0[0, :, :] / 2
917-
hist_rates_o_epoch_0[0, 0, :] = hist_rates_o_epoch_0[0, 0, :] / 2
919+
hist_rates_o_epoch_0[0, :, 0] = hist_rates_o_epoch_0[0, :, 0] / 2
918920

919921
np.testing.assert_array_equal(
920922
l1b_histrate["h_rates"][0, :, :], hist_rates_h_epoch_0[0, :, :]
@@ -944,13 +946,13 @@ def test_calculate_histogram_rates_no_interval_found(l1b_histrates):
944946
]
945947
)
946948
avg_spin_durations_per_cycle = xr.DataArray([30, 15])
947-
exposure_factor = np.zeros((2, 60, 7))
949+
exposure_factor = np.zeros((2, 7, 60))
948950
l1b_histrate = calculate_histogram_rates(
949951
l1b_histrates, acq_start, acq_end, avg_spin_durations_per_cycle, exposure_factor
950952
)
951953

952-
np.testing.assert_array_equal(l1b_histrate["h_rates"], np.full((2, 60, 7), np.nan))
953-
np.testing.assert_array_equal(l1b_histrate["o_rates"], np.full((2, 60, 7), np.nan))
954+
np.testing.assert_array_equal(l1b_histrate["h_rates"], np.full((2, 7, 60), np.nan))
955+
np.testing.assert_array_equal(l1b_histrate["o_rates"], np.full((2, 7, 60), np.nan))
954956

955957

956958
def test_calculate_histogram_rates_zero_exposure_time(l1b_histrates):
@@ -967,10 +969,10 @@ def test_calculate_histogram_rates_zero_exposure_time(l1b_histrates):
967969
]
968970
)
969971
avg_spin_durations_per_cycle = xr.DataArray([0, 15])
970-
exposure_factor = np.zeros((2, 60, 7))
972+
exposure_factor = np.zeros((2, 7, 60))
971973
l1b_histrate = calculate_histogram_rates(
972974
l1b_histrates, acq_start, acq_end, avg_spin_durations_per_cycle, exposure_factor
973975
)
974976

975-
np.testing.assert_array_equal(l1b_histrate["h_rates"], np.full((2, 60, 7), np.nan))
976-
np.testing.assert_array_equal(l1b_histrate["o_rates"], np.full((2, 60, 7), np.nan))
977+
np.testing.assert_array_equal(l1b_histrate["h_rates"], np.full((2, 7, 60), np.nan))
978+
np.testing.assert_array_equal(l1b_histrate["o_rates"], np.full((2, 7, 60), np.nan))

0 commit comments

Comments
 (0)