imap-processing 1.0.1__py3-none-any.whl → 1.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- imap_processing/_version.py +2 -2
- imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +18 -0
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +101 -258
- imap_processing/cdf/config/imap_enamaps_l2-common_variable_attrs.yaml +1 -1
- imap_processing/cdf/config/imap_hi_variable_attrs.yaml +12 -2
- imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +1 -8
- imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +16 -5
- imap_processing/cdf/config/imap_idex_l2a_variable_attrs.yaml +27 -25
- imap_processing/cdf/config/imap_idex_l2b_variable_attrs.yaml +16 -16
- imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml +2 -2
- imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +2 -13
- imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +12 -0
- imap_processing/cdf/utils.py +2 -2
- imap_processing/cli.py +4 -16
- imap_processing/codice/codice_l1a_lo_angular.py +362 -0
- imap_processing/codice/codice_l1a_lo_species.py +282 -0
- imap_processing/codice/codice_l1b.py +80 -97
- imap_processing/codice/codice_l2.py +270 -103
- imap_processing/codice/codice_new_l1a.py +64 -0
- imap_processing/codice/constants.py +37 -2
- imap_processing/codice/utils.py +270 -0
- imap_processing/ena_maps/ena_maps.py +51 -39
- imap_processing/ena_maps/utils/corrections.py +196 -14
- imap_processing/ena_maps/utils/naming.py +3 -1
- imap_processing/hi/hi_l1c.py +57 -19
- imap_processing/hi/hi_l2.py +89 -36
- imap_processing/ialirt/calculate_ingest.py +19 -1
- imap_processing/ialirt/constants.py +12 -6
- imap_processing/ialirt/generate_coverage.py +6 -1
- imap_processing/ialirt/l0/parse_mag.py +1 -0
- imap_processing/ialirt/l0/process_hit.py +1 -0
- imap_processing/ialirt/l0/process_swapi.py +1 -0
- imap_processing/ialirt/l0/process_swe.py +2 -0
- imap_processing/ialirt/process_ephemeris.py +6 -2
- imap_processing/ialirt/utils/create_xarray.py +3 -2
- imap_processing/lo/l1b/lo_l1b.py +12 -2
- imap_processing/lo/l1c/lo_l1c.py +4 -4
- imap_processing/lo/l2/lo_l2.py +101 -8
- imap_processing/quality_flags.py +1 -0
- imap_processing/swapi/constants.py +4 -0
- imap_processing/swapi/l1/swapi_l1.py +47 -20
- imap_processing/swapi/l2/swapi_l2.py +17 -3
- imap_processing/ultra/l1a/ultra_l1a.py +121 -72
- imap_processing/ultra/l1b/de.py +57 -1
- imap_processing/ultra/l1b/ultra_l1b_annotated.py +0 -1
- imap_processing/ultra/l1b/ultra_l1b_extended.py +24 -11
- imap_processing/ultra/l1c/helio_pset.py +34 -8
- imap_processing/ultra/l1c/l1c_lookup_utils.py +4 -2
- imap_processing/ultra/l1c/spacecraft_pset.py +13 -7
- imap_processing/ultra/l1c/ultra_l1c.py +6 -6
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +79 -20
- imap_processing/ultra/l2/ultra_l2.py +2 -2
- imap_processing/ultra/utils/ultra_l1_utils.py +6 -0
- {imap_processing-1.0.1.dist-info → imap_processing-1.0.3.dist-info}/METADATA +1 -1
- {imap_processing-1.0.1.dist-info → imap_processing-1.0.3.dist-info}/RECORD +58 -54
- {imap_processing-1.0.1.dist-info → imap_processing-1.0.3.dist-info}/LICENSE +0 -0
- {imap_processing-1.0.1.dist-info → imap_processing-1.0.3.dist-info}/WHEEL +0 -0
- {imap_processing-1.0.1.dist-info → imap_processing-1.0.3.dist-info}/entry_points.txt +0 -0
|
@@ -6,6 +6,7 @@ import astropy_healpix.healpy as hp
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
import xarray as xr
|
|
8
8
|
|
|
9
|
+
from imap_processing.cdf.utils import parse_filename_like
|
|
9
10
|
from imap_processing.quality_flags import ImapPSETUltraFlags
|
|
10
11
|
from imap_processing.spice.repoint import get_pointing_times
|
|
11
12
|
from imap_processing.spice.time import (
|
|
@@ -24,6 +25,7 @@ from imap_processing.ultra.l1c.ultra_l1c_pset_bins import (
|
|
|
24
25
|
get_efficiencies_and_geometric_function,
|
|
25
26
|
get_energy_delta_minus_plus,
|
|
26
27
|
get_helio_adjusted_data,
|
|
28
|
+
get_spacecraft_background_rates,
|
|
27
29
|
get_spacecraft_exposure_times,
|
|
28
30
|
get_spacecraft_histogram,
|
|
29
31
|
)
|
|
@@ -69,9 +71,14 @@ def calculate_helio_pset(
|
|
|
69
71
|
dataset : xarray.Dataset
|
|
70
72
|
Dataset containing the data.
|
|
71
73
|
"""
|
|
74
|
+
sensor = parse_filename_like(name)["sensor"][0:2]
|
|
72
75
|
pset_dict: dict[str, np.ndarray] = {}
|
|
73
76
|
# Select only the species we are interested in.
|
|
74
77
|
indices = np.where(np.isin(de_dataset["ebin"].values, species_id))[0]
|
|
78
|
+
if indices.size == 0:
|
|
79
|
+
logger.info(f"No data available for {name}")
|
|
80
|
+
return None
|
|
81
|
+
|
|
75
82
|
species_dataset = de_dataset.isel(epoch=indices)
|
|
76
83
|
|
|
77
84
|
rejected = get_de_rejection_mask(
|
|
@@ -120,17 +127,22 @@ def calculate_helio_pset(
|
|
|
120
127
|
)
|
|
121
128
|
healpix = np.arange(n_pix)
|
|
122
129
|
|
|
130
|
+
# Get midpoint timestamp for pointing.
|
|
131
|
+
pointing_range_met = get_pointing_times(
|
|
132
|
+
et_to_met(species_dataset["event_times"].mean())
|
|
133
|
+
)
|
|
123
134
|
logger.info("Calculating spacecraft exposure times with deadtime correction.")
|
|
124
135
|
exposure_time, deadtime_ratios = get_spacecraft_exposure_times(
|
|
125
136
|
rates_dataset,
|
|
126
137
|
params_dataset,
|
|
127
138
|
pixels_below_scattering,
|
|
128
139
|
boundary_scale_factors,
|
|
140
|
+
pointing_range_met,
|
|
129
141
|
n_pix=n_pix,
|
|
130
142
|
)
|
|
131
143
|
logger.info("Calculating spun efficiencies and geometric function.")
|
|
132
144
|
# calculate efficiency and geometric function as a function of energy
|
|
133
|
-
|
|
145
|
+
geometric_function, efficiencies = get_efficiencies_and_geometric_function(
|
|
134
146
|
pixels_below_scattering,
|
|
135
147
|
boundary_scale_factors,
|
|
136
148
|
theta_vals,
|
|
@@ -138,11 +150,20 @@ def calculate_helio_pset(
|
|
|
138
150
|
n_pix,
|
|
139
151
|
ancillary_files,
|
|
140
152
|
)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
153
|
+
|
|
154
|
+
logger.info("Calculating background rates.")
|
|
155
|
+
# TODO calculate helio background rates
|
|
156
|
+
# Calculate background rates
|
|
157
|
+
background_rates = get_spacecraft_background_rates(
|
|
158
|
+
rates_dataset,
|
|
159
|
+
sensor,
|
|
160
|
+
ancillary_files,
|
|
161
|
+
intervals,
|
|
162
|
+
goodtimes_dataset["spin_number"].values,
|
|
163
|
+
nside=nside,
|
|
144
164
|
)
|
|
145
|
-
|
|
165
|
+
|
|
166
|
+
mid_time = ttj2000ns_to_et(met_to_ttj2000ns((np.sum(pointing_range_met)) / 2))
|
|
146
167
|
|
|
147
168
|
logger.info("Adjusting data for helio frame.")
|
|
148
169
|
exposure_time, _efficiency, geometric_function = get_helio_adjusted_data(
|
|
@@ -169,14 +190,19 @@ def calculate_helio_pset(
|
|
|
169
190
|
helio_pset_quality_flags,
|
|
170
191
|
nside=nside,
|
|
171
192
|
)
|
|
172
|
-
|
|
193
|
+
# Convert pointing start and end time to ttj2000ns
|
|
194
|
+
pointing_range_ns = met_to_ttj2000ns(pointing_range_met)
|
|
173
195
|
# Epoch should be the start of the pointing
|
|
174
|
-
pset_dict["epoch"] = np.atleast_1d(
|
|
196
|
+
pset_dict["epoch"] = np.atleast_1d(pointing_range_ns[0]).astype(np.int64)
|
|
197
|
+
pset_dict["epoch_delta"] = np.atleast_1d(np.diff(pointing_range_ns)).astype(
|
|
198
|
+
np.int64
|
|
199
|
+
)
|
|
175
200
|
pset_dict["counts"] = counts[np.newaxis, ...]
|
|
176
201
|
pset_dict["latitude"] = latitude[np.newaxis, ...]
|
|
177
202
|
pset_dict["longitude"] = longitude[np.newaxis, ...]
|
|
178
203
|
pset_dict["energy_bin_geometric_mean"] = energy_bin_geometric_means
|
|
179
|
-
pset_dict["
|
|
204
|
+
pset_dict["background_rates"] = background_rates[np.newaxis, ...]
|
|
205
|
+
pset_dict["exposure_factor"] = exposure_time[np.newaxis, ...]
|
|
180
206
|
pset_dict["pixel_index"] = healpix
|
|
181
207
|
pset_dict["energy_bin_delta"] = np.diff(intervals, axis=1).squeeze()[
|
|
182
208
|
np.newaxis, ...
|
|
@@ -174,8 +174,10 @@ def calculate_fwhm_spun_scattering(
|
|
|
174
174
|
fwhm_phi_sum[:, for_inds] += fwhm_phi.T
|
|
175
175
|
sample_count[:, for_inds] += 1
|
|
176
176
|
|
|
177
|
-
fwhm_phi_avg = np.
|
|
178
|
-
fwhm_theta_avg = np.
|
|
177
|
+
fwhm_phi_avg = np.zeros_like(fwhm_phi_sum)
|
|
178
|
+
fwhm_theta_avg = np.zeros_like(fwhm_theta_sum)
|
|
179
|
+
np.divide(fwhm_phi_sum, sample_count, out=fwhm_phi_avg, where=sample_count != 0)
|
|
180
|
+
np.divide(fwhm_theta_sum, sample_count, out=fwhm_theta_avg, where=sample_count != 0)
|
|
179
181
|
return (
|
|
180
182
|
pixels_below_scattering,
|
|
181
183
|
fwhm_theta_avg,
|
|
@@ -77,6 +77,7 @@ def calculate_spacecraft_pset(
|
|
|
77
77
|
|
|
78
78
|
# If there are no species return None.
|
|
79
79
|
if indices.size == 0:
|
|
80
|
+
logger.info(f"No data available for {name}")
|
|
80
81
|
return None
|
|
81
82
|
|
|
82
83
|
# Before we use the de_dataset to calculate the pointing set grid we need to filter.
|
|
@@ -126,7 +127,7 @@ def calculate_spacecraft_pset(
|
|
|
126
127
|
|
|
127
128
|
logger.info("Calculating spun efficiencies and geometric function.")
|
|
128
129
|
# calculate efficiency and geometric function as a function of energy
|
|
129
|
-
|
|
130
|
+
geometric_function, efficiencies = get_efficiencies_and_geometric_function(
|
|
130
131
|
pixels_below_scattering,
|
|
131
132
|
boundary_scale_factors,
|
|
132
133
|
theta_vals,
|
|
@@ -136,6 +137,10 @@ def calculate_spacecraft_pset(
|
|
|
136
137
|
)
|
|
137
138
|
sensitivity = efficiencies * geometric_function
|
|
138
139
|
|
|
140
|
+
# Get the start and stop times of the pointing period
|
|
141
|
+
pointing_range_met = get_pointing_times(
|
|
142
|
+
float(et_to_met(species_dataset["event_times"].mean()))
|
|
143
|
+
)
|
|
139
144
|
# Calculate exposure times
|
|
140
145
|
logger.info("Calculating spacecraft exposure times with deadtime correction.")
|
|
141
146
|
exposure_pointing, deadtime_ratios = get_spacecraft_exposure_times(
|
|
@@ -143,6 +148,7 @@ def calculate_spacecraft_pset(
|
|
|
143
148
|
params_dataset,
|
|
144
149
|
pixels_below_scattering,
|
|
145
150
|
boundary_scale_factors,
|
|
151
|
+
pointing_range_met,
|
|
146
152
|
n_pix=n_pix,
|
|
147
153
|
)
|
|
148
154
|
logger.info("Calculating background rates.")
|
|
@@ -172,13 +178,13 @@ def calculate_spacecraft_pset(
|
|
|
172
178
|
spacecraft_pset_quality_flags,
|
|
173
179
|
nside=nside,
|
|
174
180
|
)
|
|
175
|
-
#
|
|
176
|
-
|
|
177
|
-
float(et_to_met(species_dataset["event_times"].data[0]))
|
|
178
|
-
)
|
|
179
|
-
pointing_start = met_to_ttj2000ns(pointing_start)
|
|
181
|
+
# Convert pointing start and end time to ttj2000ns
|
|
182
|
+
pointing_range_ns = met_to_ttj2000ns(pointing_range_met)
|
|
180
183
|
# Epoch should be the start of the pointing
|
|
181
|
-
pset_dict["epoch"] = np.atleast_1d(
|
|
184
|
+
pset_dict["epoch"] = np.atleast_1d(pointing_range_ns[0]).astype(np.int64)
|
|
185
|
+
pset_dict["epoch_delta"] = np.atleast_1d(np.diff(pointing_range_ns)).astype(
|
|
186
|
+
np.int64
|
|
187
|
+
)
|
|
182
188
|
pset_dict["counts"] = counts[np.newaxis, ...]
|
|
183
189
|
pset_dict["latitude"] = latitude[np.newaxis, ...]
|
|
184
190
|
pset_dict["longitude"] = longitude[np.newaxis, ...]
|
|
@@ -8,7 +8,7 @@ from imap_processing.ultra.l1c.spacecraft_pset import calculate_spacecraft_pset
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def ultra_l1c(
|
|
11
|
-
data_dict: dict, ancillary_files: dict,
|
|
11
|
+
data_dict: dict, ancillary_files: dict, descriptor: str
|
|
12
12
|
) -> list[xr.Dataset]:
|
|
13
13
|
"""
|
|
14
14
|
Will process ULTRA L1A and L1B data into L1C CDF files at output_filepath.
|
|
@@ -19,8 +19,8 @@ def ultra_l1c(
|
|
|
19
19
|
The data itself and its dependent data.
|
|
20
20
|
ancillary_files : dict
|
|
21
21
|
Ancillary files.
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
descriptor : str
|
|
23
|
+
Job descriptor.
|
|
24
24
|
|
|
25
25
|
Returns
|
|
26
26
|
-------
|
|
@@ -28,15 +28,15 @@ def ultra_l1c(
|
|
|
28
28
|
List of xarray.Dataset.
|
|
29
29
|
"""
|
|
30
30
|
output_datasets = []
|
|
31
|
-
|
|
32
|
-
# Account for possibility of having 45 and 90 in dictionary.
|
|
31
|
+
create_helio_pset = True if "helio" in descriptor else False
|
|
32
|
+
# Account for the possibility of having 45 and 90 in the dictionary.
|
|
33
33
|
for instrument_id in [45, 90]:
|
|
34
34
|
if (
|
|
35
35
|
f"imap_ultra_l1b_{instrument_id}sensor-goodtimes" in data_dict
|
|
36
36
|
and f"imap_ultra_l1b_{instrument_id}sensor-de" in data_dict
|
|
37
37
|
and f"imap_ultra_l1a_{instrument_id}sensor-rates" in data_dict
|
|
38
38
|
and f"imap_ultra_l1a_{instrument_id}sensor-params" in data_dict
|
|
39
|
-
and
|
|
39
|
+
and create_helio_pset
|
|
40
40
|
):
|
|
41
41
|
helio_pset = calculate_helio_pset(
|
|
42
42
|
data_dict[f"imap_ultra_l1b_{instrument_id}sensor-de"],
|
|
@@ -13,7 +13,11 @@ from imap_processing.spice.geometry import (
|
|
|
13
13
|
cartesian_to_spherical,
|
|
14
14
|
imap_state,
|
|
15
15
|
)
|
|
16
|
-
from imap_processing.spice.spin import
|
|
16
|
+
from imap_processing.spice.spin import (
|
|
17
|
+
get_spacecraft_spin_phase,
|
|
18
|
+
get_spin_angle,
|
|
19
|
+
get_spin_data,
|
|
20
|
+
)
|
|
17
21
|
from imap_processing.spice.time import ttj2000ns_to_met
|
|
18
22
|
from imap_processing.ultra.constants import UltraConstants
|
|
19
23
|
from imap_processing.ultra.l1b.lookup_utils import (
|
|
@@ -381,7 +385,7 @@ def calculate_exposure_time(
|
|
|
381
385
|
# Get energy bin geometric means
|
|
382
386
|
energy_bin_geometric_means = build_energy_bins()[2]
|
|
383
387
|
# Exposure time should now be of shape (energy, npix)
|
|
384
|
-
|
|
388
|
+
counts = np.zeros((len(energy_bin_geometric_means), n_pix))
|
|
385
389
|
# nominal spin phase step.
|
|
386
390
|
nominal_ms_step = 15 / len(pixels_below_scattering) # time step
|
|
387
391
|
# Query the dead-time ratio and apply the nominal exposure time to pixels in the FOR
|
|
@@ -396,12 +400,13 @@ def calculate_exposure_time(
|
|
|
396
400
|
continue
|
|
397
401
|
# Apply the nominal exposure time (1 ms) scaled by the deadtime ratio to
|
|
398
402
|
# every pixel in the FOR, that is below the FWHM scattering threshold,
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
* deadtime_ratios[i]
|
|
403
|
+
counts[energy_bin_idx, pixels_at_energy_and_spin] += (
|
|
404
|
+
deadtime_ratios[i]
|
|
402
405
|
* boundary_scale_factors[pixels_at_energy_and_spin, i]
|
|
403
406
|
)
|
|
404
407
|
|
|
408
|
+
# Multiply by the nominal spin step to get the exposure time in ms
|
|
409
|
+
exposure_pointing = counts * nominal_ms_step
|
|
405
410
|
return exposure_pointing
|
|
406
411
|
|
|
407
412
|
|
|
@@ -410,6 +415,7 @@ def get_spacecraft_exposure_times(
|
|
|
410
415
|
params_dataset: xr.Dataset,
|
|
411
416
|
pixels_below_scattering: list[list],
|
|
412
417
|
boundary_scale_factors: NDArray,
|
|
418
|
+
pointing_range_met: tuple[float, float],
|
|
413
419
|
n_pix: int,
|
|
414
420
|
) -> tuple[NDArray, NDArray]:
|
|
415
421
|
"""
|
|
@@ -428,6 +434,8 @@ def get_spacecraft_exposure_times(
|
|
|
428
434
|
below the FWHM scattering threshold.
|
|
429
435
|
boundary_scale_factors : np.ndarray
|
|
430
436
|
Boundary scale factors for each pixel at each spin phase.
|
|
437
|
+
pointing_range_met : tuple
|
|
438
|
+
Start and stop time of the pointing period in mission elapsed time.
|
|
431
439
|
n_pix : int
|
|
432
440
|
Number of HEALPix pixels.
|
|
433
441
|
|
|
@@ -440,13 +448,36 @@ def get_spacecraft_exposure_times(
|
|
|
440
448
|
nominal_deadtime_ratios : np.ndarray
|
|
441
449
|
Deadtime ratios at each spin phase step (1ms res).
|
|
442
450
|
"""
|
|
443
|
-
# TODO: use the universal spin table and
|
|
444
|
-
# universal pointing table here to determine actual number of spins
|
|
445
451
|
sectored_rates = get_sectored_rates(rates_dataset, params_dataset)
|
|
446
452
|
nominal_deadtime_ratios = get_deadtime_ratios_by_spin_phase(sectored_rates)
|
|
447
|
-
|
|
453
|
+
# The exposure time will be approximately the same per spin, so to save
|
|
454
|
+
# computation time, calculate the exposure time for a single spin and then scale it
|
|
455
|
+
# by the number of spins in the pointing. For more information, see section 3.4.3
|
|
456
|
+
# of the Ultra Algorithm Document.
|
|
457
|
+
exposure_time = calculate_exposure_time(
|
|
448
458
|
nominal_deadtime_ratios, pixels_below_scattering, boundary_scale_factors, n_pix
|
|
449
459
|
)
|
|
460
|
+
# Use the universal spin table to determine the actual number of spins
|
|
461
|
+
nominal_spin_seconds = 15.0
|
|
462
|
+
spin_data = get_spin_data()
|
|
463
|
+
# Filter for spins only in pointing
|
|
464
|
+
spin_data = spin_data[
|
|
465
|
+
(spin_data["spin_start_met"] >= pointing_range_met[0])
|
|
466
|
+
& (spin_data["spin_start_met"] <= pointing_range_met[1])
|
|
467
|
+
]
|
|
468
|
+
# Get only valid spin data
|
|
469
|
+
valid_mask = (spin_data["spin_phase_valid"].values == 1) & (
|
|
470
|
+
spin_data["spin_period_valid"].values == 1
|
|
471
|
+
)
|
|
472
|
+
n_spins_in_pointing: float = np.sum(
|
|
473
|
+
spin_data[valid_mask].spin_period_sec / nominal_spin_seconds
|
|
474
|
+
)
|
|
475
|
+
logger.info(
|
|
476
|
+
f"Calculated total spins universal spin table. Found {n_spins_in_pointing} "
|
|
477
|
+
f"valid spins."
|
|
478
|
+
)
|
|
479
|
+
# Adjust exposure time by the actual number of valid spins in the pointing
|
|
480
|
+
exposure_pointing_adjusted = n_spins_in_pointing * exposure_time
|
|
450
481
|
return exposure_pointing_adjusted, nominal_deadtime_ratios
|
|
451
482
|
|
|
452
483
|
|
|
@@ -483,13 +514,17 @@ def get_efficiencies_and_geometric_function(
|
|
|
483
514
|
|
|
484
515
|
Returns
|
|
485
516
|
-------
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
517
|
+
gf_averaged : np.ndarray
|
|
518
|
+
Averaged geometric factors across all spin phases.
|
|
519
|
+
Shape = (n_energy_bins, npix).
|
|
520
|
+
eff_averaged : np.ndarray
|
|
521
|
+
Averaged efficiencies across all spin phases.
|
|
522
|
+
Shape = (n_energy_bins, npix).
|
|
490
523
|
"""
|
|
491
524
|
# Load callable efficiency interpolator function
|
|
492
|
-
eff_interpolator = get_efficiency_interpolator(
|
|
525
|
+
eff_interpolator, theta_min_max, phi_min_max = get_efficiency_interpolator(
|
|
526
|
+
ancillary_files
|
|
527
|
+
)
|
|
493
528
|
# load geometric factor lookup table
|
|
494
529
|
geometric_lookup_table = load_geometric_factor_tables(
|
|
495
530
|
ancillary_files, "l1b-sensor-gf-blades"
|
|
@@ -497,6 +532,24 @@ def get_efficiencies_and_geometric_function(
|
|
|
497
532
|
# Get energy bin geometric means
|
|
498
533
|
energy_bin_geometric_means = build_energy_bins()[2]
|
|
499
534
|
energy_bins = len(energy_bin_geometric_means)
|
|
535
|
+
# clip arrays to avoid out of bounds errors
|
|
536
|
+
logger.info(
|
|
537
|
+
"Clipping Theta and Phi values to valid ranges for the efficiency "
|
|
538
|
+
"interpolation. \n"
|
|
539
|
+
f"Theta valid range: {theta_min_max}, Phi valid range: {phi_min_max}. \n "
|
|
540
|
+
f"Found "
|
|
541
|
+
f"{np.sum((theta_vals < theta_min_max[0]) | (theta_vals > theta_min_max[1]))}"
|
|
542
|
+
f" Theta values out of range. \n"
|
|
543
|
+
f"Found "
|
|
544
|
+
f"{np.sum((phi_vals < phi_min_max[0]) | (phi_vals > phi_min_max[1]))}"
|
|
545
|
+
f" Phi values out of range. \n"
|
|
546
|
+
f"Theta min and max values before clipping: "
|
|
547
|
+
f"{theta_vals.min()}, {theta_vals.max()} \n"
|
|
548
|
+
f"Phi min and max values before clipping:"
|
|
549
|
+
f" {phi_vals.min()}, {phi_vals.max()} \n"
|
|
550
|
+
)
|
|
551
|
+
theta_vals_clipped = np.clip(theta_vals, theta_min_max[0], theta_min_max[1])
|
|
552
|
+
phi_vals_clipped = np.clip(phi_vals, phi_min_max[0], phi_min_max[1])
|
|
500
553
|
# Initialize summation arrays for geometric factors and efficiencies
|
|
501
554
|
gf_summation = np.zeros((energy_bins, npix))
|
|
502
555
|
eff_summation = np.zeros((energy_bins, npix))
|
|
@@ -507,6 +560,8 @@ def get_efficiencies_and_geometric_function(
|
|
|
507
560
|
# Compute gf and eff for these theta/phi pairs
|
|
508
561
|
theta_at_spin = theta_vals[:, i]
|
|
509
562
|
phi_at_spin = phi_vals[:, i]
|
|
563
|
+
theta_at_spin_clipped = theta_vals_clipped[:, i]
|
|
564
|
+
phi_at_spin_clipped = phi_vals_clipped[:, i]
|
|
510
565
|
gf_values = get_geometric_factor(
|
|
511
566
|
phi=phi_at_spin,
|
|
512
567
|
theta=theta_at_spin,
|
|
@@ -518,10 +573,12 @@ def get_efficiencies_and_geometric_function(
|
|
|
518
573
|
if pixel_inds.size == 0:
|
|
519
574
|
continue
|
|
520
575
|
energy = energy_bin_geometric_means[energy_bin_idx]
|
|
576
|
+
# Clip energy to calibrated range
|
|
577
|
+
energy_clipped = np.clip(energy, 3.0, 80.0)
|
|
521
578
|
eff_values = get_efficiency(
|
|
522
|
-
np.full(phi_at_spin[pixel_inds].shape,
|
|
523
|
-
|
|
524
|
-
|
|
579
|
+
np.full(phi_at_spin[pixel_inds].shape, energy_clipped),
|
|
580
|
+
phi_at_spin_clipped[pixel_inds],
|
|
581
|
+
theta_at_spin_clipped[pixel_inds],
|
|
525
582
|
ancillary_files,
|
|
526
583
|
interpolator=eff_interpolator,
|
|
527
584
|
)
|
|
@@ -536,8 +593,10 @@ def get_efficiencies_and_geometric_function(
|
|
|
536
593
|
|
|
537
594
|
# return averaged geometric factors and efficiencies across all spin phases
|
|
538
595
|
# These are now energy dependent.
|
|
539
|
-
gf_averaged = np.
|
|
540
|
-
eff_averaged = np.
|
|
596
|
+
gf_averaged = np.zeros_like(gf_summation)
|
|
597
|
+
eff_averaged = np.zeros_like(eff_summation)
|
|
598
|
+
np.divide(gf_summation, sample_count, out=gf_averaged, where=sample_count != 0)
|
|
599
|
+
np.divide(eff_summation, sample_count, out=eff_averaged, where=sample_count != 0)
|
|
541
600
|
return gf_averaged, eff_averaged
|
|
542
601
|
|
|
543
602
|
|
|
@@ -698,8 +757,8 @@ def get_spacecraft_background_rates(
|
|
|
698
757
|
"""
|
|
699
758
|
pulses = get_pulses_per_spin(rates_dataset)
|
|
700
759
|
# Pulses for the pointing.
|
|
701
|
-
etof_min = get_image_params("eTOFMin", sensor, ancillary_files)
|
|
702
|
-
etof_max = get_image_params("eTOFMax", sensor, ancillary_files)
|
|
760
|
+
etof_min = get_image_params("eTOFMin", f"ultra{sensor}", ancillary_files)
|
|
761
|
+
etof_max = get_image_params("eTOFMax", f"ultra{sensor}", ancillary_files)
|
|
703
762
|
spin_number, _ = get_spin_and_duration(
|
|
704
763
|
rates_dataset["shcoarse"], rates_dataset["spin"]
|
|
705
764
|
)
|
|
@@ -364,8 +364,8 @@ def generate_ultra_healpix_skymap( # noqa: PLR0912
|
|
|
364
364
|
for var in pointing_indep_vars:
|
|
365
365
|
skymap.data_1d[var] = skymap.data_1d[var].squeeze("epoch", drop=True)
|
|
366
366
|
|
|
367
|
-
# Background rates must be scaled by
|
|
368
|
-
# map pixel / pointing set pixel
|
|
367
|
+
# Background rates must be scaled by
|
|
368
|
+
# the ratio of the solid angles of the map pixel / pointing set pixel
|
|
369
369
|
skymap.data_1d["background_rates"] *= skymap.solid_angle / pointing_set.solid_angle
|
|
370
370
|
|
|
371
371
|
# Get the energy bin widths from a PointingSet (they will all be the same)
|
|
@@ -102,6 +102,12 @@ def create_dataset( # noqa: PLR0912
|
|
|
102
102
|
"spin_phase_step",
|
|
103
103
|
]:
|
|
104
104
|
continue
|
|
105
|
+
elif key == "epoch_delta":
|
|
106
|
+
dataset[key] = xr.DataArray(
|
|
107
|
+
data,
|
|
108
|
+
dims=["epoch"],
|
|
109
|
+
attrs=cdf_manager.get_variable_attributes(key, check_schema=False),
|
|
110
|
+
)
|
|
105
111
|
elif key in velocity_keys:
|
|
106
112
|
dataset[key] = xr.DataArray(
|
|
107
113
|
data,
|