Skip to content

Commit 059e75c

Browse files
Harrison 3063/#36 - PMCL/KJON - Maps spx: Added uncertainty for scalar coefficient from spectral fitting
1 parent d60102d commit 059e75c

8 files changed

Lines changed: 172 additions & 18 deletions

File tree

imap_l3_processing/cdf/config/imap_hi_l3_variable_attrs.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,4 +400,29 @@ ena_spectral_scalar:
400400
LABL_PTR_1: energy_label
401401
LABL_PTR_2: longitude_label
402402
LABL_PTR_3: latitude_label
403+
SCALETYP: log
404+
DELTA_PLUS_VAR: ena_spectral_scalar_stat_uncert
405+
DELTA_MINUS_VAR: ena_spectral_scalar_stat_uncert
406+
ena_spectral_scalar_stat_uncert:
407+
NAME: ena_spectral_scalar_stat_uncert
408+
DATA_TYPE: CDF_REAL4
409+
CATDESC: ENA spectral index scalar coefficient statistical uncertainty.
410+
DEPEND_0: epoch
411+
DEPEND_1: energy
412+
DEPEND_2: longitude
413+
DEPEND_3: latitude
414+
VAR_TYPE: data
415+
RECORD_VARYING: RV
416+
DISPLAY_TYPE: map_image
417+
VARIABLE_PURPOSE: ' '
418+
FIELDNAM: Spectral scalar stat unc
419+
FORMAT: F12.6
420+
LABLAXIS: Statistical unc.
421+
UNITS: cm -2 s -1 sr -1 keV -1
422+
VALIDMIN: 0.0
423+
VALIDMAX: 1.0E+20
424+
FILLVAL: -1.00E+31
425+
LABL_PTR_1: energy_label
426+
LABL_PTR_2: longitude_label
427+
LABL_PTR_3: latitude_label
403428
SCALETYP: log

imap_l3_processing/cdf/config/imap_lo_l3_variable_attrs.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,4 +663,29 @@ ena_spectral_scalar:
663663
LABL_PTR_1: energy_label
664664
LABL_PTR_2: longitude_label
665665
LABL_PTR_3: latitude_label
666+
SCALETYP: log
667+
DELTA_PLUS_VAR: ena_spectral_scalar_stat_uncert
668+
DELTA_MINUS_VAR: ena_spectral_scalar_stat_uncert
669+
ena_spectral_scalar_stat_uncert:
670+
NAME: ena_spectral_scalar_stat_uncert
671+
DATA_TYPE: CDF_REAL4
672+
CATDESC: ENA spectral index scalar coefficient statistical uncertainty.
673+
DEPEND_0: epoch
674+
DEPEND_1: energy
675+
DEPEND_2: longitude
676+
DEPEND_3: latitude
677+
VAR_TYPE: data
678+
RECORD_VARYING: RV
679+
DISPLAY_TYPE: map_image
680+
VARIABLE_PURPOSE: ' '
681+
FIELDNAM: Spectral scalar stat unc
682+
FORMAT: F12.6
683+
LABLAXIS: Statistical unc.
684+
UNITS: cm -2 s -1 sr -1 keV -1
685+
VALIDMIN: 0.0
686+
VALIDMAX: 1.0E+20
687+
FILLVAL: -1.00E+31
688+
LABL_PTR_1: energy_label
689+
LABL_PTR_2: longitude_label
690+
LABL_PTR_3: latitude_label
666691
SCALETYP: log

imap_l3_processing/cdf/config/imap_ultra_l3_variable_attrs.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,4 +400,29 @@ ena_spectral_scalar:
400400
LABL_PTR_1: energy_label
401401
LABL_PTR_2: longitude_label
402402
LABL_PTR_3: latitude_label
403+
SCALETYP: log
404+
DELTA_PLUS_VAR: ena_spectral_scalar_stat_uncert
405+
DELTA_MINUS_VAR: ena_spectral_scalar_stat_uncert
406+
ena_spectral_scalar_stat_uncert:
407+
NAME: ena_spectral_scalar_stat_uncert
408+
DATA_TYPE: CDF_REAL4
409+
CATDESC: ENA spectral index scalar coefficient statistical uncertainty.
410+
DEPEND_0: epoch
411+
DEPEND_1: energy
412+
DEPEND_2: longitude
413+
DEPEND_3: latitude
414+
VAR_TYPE: data
415+
RECORD_VARYING: RV
416+
DISPLAY_TYPE: map_image
417+
VARIABLE_PURPOSE: ' '
418+
FIELDNAM: Spectral scalar stat unc
419+
FORMAT: F12.6
420+
LABLAXIS: Statistical unc.
421+
UNITS: cm -2 s -1 sr -1 keV -1
422+
VALIDMIN: 0.0
423+
VALIDMAX: 1.0E+20
424+
FILLVAL: -1.00E+31
425+
LABL_PTR_1: energy_label
426+
LABL_PTR_2: longitude_label
427+
LABL_PTR_3: latitude_label
403428
SCALETYP: log

imap_l3_processing/maps/map_models.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
ENA_SPECTRAL_INDEX_VAR_NAME = "ena_spectral_index"
3939
ENA_SPECTRAL_INDEX_STAT_UNC_VAR_NAME = "ena_spectral_index_stat_uncert"
4040
ENA_SPECTRAL_INDEX_SCALAR_COEFFICIENT_VAR_NAME = "ena_spectral_scalar"
41+
ENA_SPECTRAL_INDEX_SCALAR_COEFFICIENT_STAT_UNCERT_VAR_NAME = "ena_spectral_scalar_stat_uncert"
4142

4243
ENA_INTENSITY_VAR_NAME = "ena_intensity"
4344
ENA_INTENSITY_STAT_UNCERT_VAR_NAME = "ena_intensity_stat_uncert"
@@ -123,6 +124,7 @@ class SpectralIndexMapData(MapData):
123124
ena_spectral_index: np.ndarray
124125
ena_spectral_index_stat_uncert: np.ndarray
125126
ena_spectral_index_scalar_coefficient: np.ndarray
127+
ena_spectral_index_scalar_coefficient_stat_uncert: np.ndarray
126128

127129

128130
@dataclass
@@ -397,6 +399,8 @@ def to_healpix_skymap(self) -> HealpixSkyMap:
397399
"ena_spectral_index_stat_uncert": (
398400
full_shape, self.spectral_index_map_data.ena_spectral_index_stat_uncert),
399401
"ena_spectral_index_scalar_coefficient": (full_shape, self.spectral_index_map_data.ena_spectral_index_scalar_coefficient),
402+
"ena_spectral_index_scalar_coefficient_stat_uncert": (full_shape,
403+
self.spectral_index_map_data.ena_spectral_index_scalar_coefficient_stat_uncert),
400404
},
401405
coords={
402406
CoordNames.TIME.value: self.spectral_index_map_data.epoch,
@@ -506,6 +510,7 @@ def _spectral_index_data_variables(data: SpectralIndexMapData) -> list[DataProdu
506510
DataProductVariable(ENA_SPECTRAL_INDEX_VAR_NAME, data.ena_spectral_index),
507511
DataProductVariable(ENA_SPECTRAL_INDEX_STAT_UNC_VAR_NAME, data.ena_spectral_index_stat_uncert),
508512
DataProductVariable(ENA_SPECTRAL_INDEX_SCALAR_COEFFICIENT_VAR_NAME, data.ena_spectral_index_scalar_coefficient),
513+
DataProductVariable(ENA_SPECTRAL_INDEX_SCALAR_COEFFICIENT_STAT_UNCERT_VAR_NAME, data.ena_spectral_index_scalar_coefficient_stat_uncert),
509514
]
510515

511516

imap_l3_processing/maps/spectral_fit.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def calculate_spectral_index_for_multiple_ranges(intensity_data: IntensityMapDat
3232
ena_spectral_index=np.concat([m.ena_spectral_index for m in spectral_maps], axis=1),
3333
ena_spectral_index_stat_uncert=np.concat([m.ena_spectral_index_stat_uncert for m in spectral_maps], axis=1),
3434
ena_spectral_index_scalar_coefficient=np.concat([m.ena_spectral_index_scalar_coefficient for m in spectral_maps], axis=1),
35+
ena_spectral_index_scalar_coefficient_stat_uncert=np.concat([m.ena_spectral_index_scalar_coefficient_stat_uncert for m in spectral_maps], axis=1)
3536
)
3637

3738

@@ -81,7 +82,7 @@ def fit_spectral_index_map(intensity_data: IntensityMapData) -> SpectralIndexMap
8182
mean_energy = np.sqrt(min_energy * max_energy)
8283
new_energy_label = f"{min_energy} - {max_energy}"
8384

84-
output_scalar_coefficients, output_gammas, output_gamma_errors = fit_arrays_to_power_law(fluxes, uncertainty, energy)
85+
output_scalar_coefficients, output_scalar_errors, output_gammas, output_gamma_errors = fit_arrays_to_power_law(fluxes, uncertainty, energy)
8586
mean_obs_date = calculate_datetime_weighted_average(intensity_data.obs_date,
8687
weights=intensity_data.exposure_factor,
8788
axis=1, keepdims=True)
@@ -110,12 +111,13 @@ def fit_spectral_index_map(intensity_data: IntensityMapData) -> SpectralIndexMap
110111
solid_angle=intensity_data.solid_angle,
111112
ena_spectral_index=output_gammas,
112113
ena_spectral_index_stat_uncert=output_gamma_errors,
113-
ena_spectral_index_scalar_coefficient=output_scalar_coefficients
114+
ena_spectral_index_scalar_coefficient=output_scalar_coefficients,
115+
ena_spectral_index_scalar_coefficient_stat_uncert=output_scalar_errors,
114116
)
115117

116118

117119
def fit_arrays_to_power_law(fluxes: np.ndarray, uncertainties: np.ndarray, energy: np.ndarray) -> tuple[
118-
np.ndarray, np.ndarray, np.ndarray]:
120+
np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
119121
par_info = [
120122
{'limits': [0.0, 1000.0]},
121123
{'limits': [0.0, 1000.0]},
@@ -125,6 +127,7 @@ def fit_arrays_to_power_law(fluxes: np.ndarray, uncertainties: np.ndarray, energ
125127
output_gammas = np.full(output_shape, np.nan, dtype=float)
126128
output_gamma_errors = np.full_like(output_gammas, np.nan)
127129
output_scalar_coefficients = np.full_like(output_gammas, np.nan)
130+
output_scalar_coefficients_errors = np.full_like(output_gammas, np.nan)
128131

129132
for epoch in range(fluxes.shape[0]):
130133
intensity = fluxes[epoch].reshape((fluxes[epoch].shape[0], -1))
@@ -133,6 +136,7 @@ def fit_arrays_to_power_law(fluxes: np.ndarray, uncertainties: np.ndarray, energ
133136
gammas = np.full(intensity.shape[-1], np.nan, dtype=float)
134137
gamma_errors = np.full_like(gammas, np.nan)
135138
scalar_coefficients = np.full(intensity.shape[-1], np.nan, dtype=float)
139+
scalar_coefficient_errors = np.full(intensity.shape[-1], np.nan, dtype=float)
136140

137141
for i in range(intensity.shape[-1]):
138142
flux = intensity[:, i]
@@ -158,10 +162,12 @@ def fit_arrays_to_power_law(fluxes: np.ndarray, uncertainties: np.ndarray, energ
158162
gammas[i] = gamma
159163
scalar_coefficients[i] = a
160164
gamma_errors[i] = gamma_error
165+
scalar_coefficient_errors[i] = a_error
161166
output_gammas[epoch, 0] = gammas.reshape(fluxes.shape[2:])
162167
output_gamma_errors[epoch, 0] = gamma_errors.reshape(fluxes.shape[2:])
163168
output_scalar_coefficients[epoch, 0] = scalar_coefficients.reshape(fluxes.shape[2:])
164-
return output_scalar_coefficients, output_gammas, output_gamma_errors
169+
output_scalar_coefficients_errors[epoch, 0] = scalar_coefficient_errors.reshape(fluxes.shape[2:])
170+
return output_scalar_coefficients, output_scalar_coefficients_errors, output_gammas, output_gamma_errors
165171

166172

167173
def power_law(params, **kwargs):

tests/maps/test_map_models.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def test_rectangular_spectral_index_to_data_product_variables(self):
5252
ena_spectral_index=sentinel.ena_spectral_index,
5353
ena_spectral_index_stat_uncert=sentinel.ena_spectral_index_stat_uncert,
5454
ena_spectral_index_scalar_coefficient=sentinel.ena_spectral_index_scalar_coefficient,
55+
ena_spectral_index_scalar_coefficient_stat_uncert=sentinel.ena_spectral_index_scalar_coefficient_stat_uncert,
5556
),
5657
coords=RectangularCoords(
5758
latitude_delta=sentinel.latitude_delta,
@@ -82,6 +83,7 @@ def test_rectangular_spectral_index_to_data_product_variables(self):
8283
DataProductVariable(map_models.ENA_SPECTRAL_INDEX_STAT_UNC_VAR_NAME,
8384
sentinel.ena_spectral_index_stat_uncert),
8485
DataProductVariable(map_models.ENA_SPECTRAL_INDEX_SCALAR_COEFFICIENT_VAR_NAME, sentinel.ena_spectral_index_scalar_coefficient),
86+
DataProductVariable(map_models.ENA_SPECTRAL_INDEX_SCALAR_COEFFICIENT_STAT_UNCERT_VAR_NAME, sentinel.ena_spectral_index_scalar_coefficient_stat_uncert),
8587
DataProductVariable(map_models.LATITUDE_DELTA_VAR_NAME, sentinel.latitude_delta),
8688
DataProductVariable(map_models.LATITUDE_LABEL_VAR_NAME, sentinel.latitude_label),
8789
DataProductVariable(map_models.LONGITUDE_DELTA_VAR_NAME, sentinel.longitude_delta),
@@ -236,6 +238,7 @@ def test_healpix_spectral_index_to_data_product_variables(self):
236238
ena_spectral_index=sentinel.ena_spectral_index,
237239
ena_spectral_index_stat_uncert=sentinel.ena_spectral_index_stat_uncert,
238240
ena_spectral_index_scalar_coefficient=sentinel.ena_spectral_index_scalar_coefficient,
241+
ena_spectral_index_scalar_coefficient_stat_uncert=sentinel.ena_spectral_index_scalar_coefficient_stat_uncert,
239242
),
240243
coords=HealPixCoords(
241244
pixel_index=sentinel.pixel_index,
@@ -264,6 +267,7 @@ def test_healpix_spectral_index_to_data_product_variables(self):
264267
DataProductVariable(map_models.ENA_SPECTRAL_INDEX_STAT_UNC_VAR_NAME,
265268
sentinel.ena_spectral_index_stat_uncert),
266269
DataProductVariable(map_models.ENA_SPECTRAL_INDEX_SCALAR_COEFFICIENT_VAR_NAME, sentinel.ena_spectral_index_scalar_coefficient),
270+
DataProductVariable(map_models.ENA_SPECTRAL_INDEX_SCALAR_COEFFICIENT_STAT_UNCERT_VAR_NAME, sentinel.ena_spectral_index_scalar_coefficient_stat_uncert),
267271
DataProductVariable(map_models.PIXEL_INDEX_VAR_NAME, sentinel.pixel_index),
268272
DataProductVariable(map_models.PIXEL_INDEX_LABEL_VAR_NAME, sentinel.pixel_index_label),
269273
]
@@ -721,6 +725,7 @@ def test_healpix_spectral_index_map_data_to_skymap(self):
721725
ena_spectral_index=fake_data_per_energy_per_pixel * 2.2,
722726
ena_spectral_index_stat_uncert=fake_data_per_energy_per_pixel * 2.3,
723727
ena_spectral_index_scalar_coefficient=fake_data_per_energy_per_pixel * 2.4,
728+
ena_spectral_index_scalar_coefficient_stat_uncert=fake_data_per_energy_per_pixel * 2.5,
724729
)
725730

726731
healpix_spectral_index_map_data = HealPixSpectralIndexMapData(
@@ -755,9 +760,10 @@ def test_healpix_spectral_index_map_data_to_skymap(self):
755760
np.testing.assert_array_equal(actual_dataset.data_vars["ena_spectral_index_stat_uncert"].values, spectral_index_map_data.ena_spectral_index_stat_uncert)
756761

757762
np.testing.assert_array_equal(actual_dataset.data_vars["ena_spectral_index_scalar_coefficient"].values, spectral_index_map_data.ena_spectral_index_scalar_coefficient)
763+
np.testing.assert_array_equal(actual_dataset.data_vars["ena_spectral_index_scalar_coefficient_stat_uncert"].values, spectral_index_map_data.ena_spectral_index_scalar_coefficient_stat_uncert)
758764

759765
for key in [ "obs_date", "obs_date_range", "exposure_factor", "ena_spectral_index", "ena_spectral_index_stat_uncert",
760-
"ena_spectral_index_scalar_coefficient" ]:
766+
"ena_spectral_index_scalar_coefficient", "ena_spectral_index_scalar_coefficient_stat_uncert" ]:
761767
self.assertEqual((CoordNames.TIME.value, CoordNames.ENERGY_L2.value, CoordNames.GENERIC_PIXEL.value), actual_dataset.data_vars[key].dims)
762768
for key in [ "latitude", "longitude", "solid_angle" ]:
763769
self.assertEqual((CoordNames.GENERIC_PIXEL.value,), actual_dataset.data_vars[key].dims)

0 commit comments

Comments
 (0)