imap-processing 0.17.0__py3-none-any.whl → 0.18.0__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.

Potentially problematic release.


This version of imap-processing might be problematic. Click here for more details.

Files changed (89) hide show
  1. imap_processing/_version.py +2 -2
  2. imap_processing/ccsds/excel_to_xtce.py +12 -0
  3. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +6 -6
  4. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +11 -0
  5. imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +11 -0
  6. imap_processing/cdf/config/imap_codice_l2_variable_attrs.yaml +24 -0
  7. imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +163 -100
  8. imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml +4 -4
  9. imap_processing/cdf/config/imap_ialirt_l1_variable_attrs.yaml +97 -54
  10. imap_processing/cdf/config/imap_idex_l2b_variable_attrs.yaml +119 -36
  11. imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml +16 -90
  12. imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +30 -0
  13. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +15 -1
  14. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +60 -0
  15. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +91 -11
  16. imap_processing/cli.py +28 -5
  17. imap_processing/codice/codice_l1a.py +36 -48
  18. imap_processing/codice/codice_l1b.py +1 -1
  19. imap_processing/codice/codice_l2.py +0 -9
  20. imap_processing/codice/constants.py +481 -498
  21. imap_processing/hit/l0/decom_hit.py +2 -2
  22. imap_processing/hit/l1a/hit_l1a.py +64 -24
  23. imap_processing/hit/l1b/constants.py +5 -0
  24. imap_processing/hit/l1b/hit_l1b.py +18 -16
  25. imap_processing/hit/l2/constants.py +1 -1
  26. imap_processing/hit/l2/hit_l2.py +4 -5
  27. imap_processing/ialirt/constants.py +21 -0
  28. imap_processing/ialirt/generate_coverage.py +188 -0
  29. imap_processing/ialirt/l0/parse_mag.py +62 -5
  30. imap_processing/ialirt/l0/process_swapi.py +1 -1
  31. imap_processing/ialirt/l0/process_swe.py +23 -7
  32. imap_processing/ialirt/utils/constants.py +22 -16
  33. imap_processing/ialirt/utils/create_xarray.py +42 -19
  34. imap_processing/idex/idex_constants.py +1 -5
  35. imap_processing/idex/idex_l2b.py +246 -67
  36. imap_processing/idex/idex_l2c.py +30 -196
  37. imap_processing/lo/l0/lo_apid.py +1 -0
  38. imap_processing/lo/l1a/lo_l1a.py +44 -0
  39. imap_processing/lo/packet_definitions/lo_xtce.xml +5359 -106
  40. imap_processing/mag/constants.py +1 -0
  41. imap_processing/mag/l1d/__init__.py +0 -0
  42. imap_processing/mag/l1d/mag_l1d.py +133 -0
  43. imap_processing/mag/l1d/mag_l1d_data.py +588 -0
  44. imap_processing/mag/l2/__init__.py +0 -0
  45. imap_processing/mag/l2/mag_l2.py +25 -20
  46. imap_processing/mag/l2/mag_l2_data.py +191 -130
  47. imap_processing/quality_flags.py +20 -2
  48. imap_processing/spice/geometry.py +25 -3
  49. imap_processing/spice/pointing_frame.py +1 -1
  50. imap_processing/spice/spin.py +4 -0
  51. imap_processing/spice/time.py +51 -0
  52. imap_processing/swapi/l2/swapi_l2.py +52 -8
  53. imap_processing/swapi/swapi_utils.py +1 -1
  54. imap_processing/swe/l1b/swe_l1b.py +2 -4
  55. imap_processing/ultra/constants.py +49 -1
  56. imap_processing/ultra/l0/decom_tools.py +15 -8
  57. imap_processing/ultra/l0/decom_ultra.py +35 -11
  58. imap_processing/ultra/l0/ultra_utils.py +97 -5
  59. imap_processing/ultra/l1a/ultra_l1a.py +25 -4
  60. imap_processing/ultra/l1b/cullingmask.py +3 -3
  61. imap_processing/ultra/l1b/de.py +53 -15
  62. imap_processing/ultra/l1b/extendedspin.py +26 -2
  63. imap_processing/ultra/l1b/lookup_utils.py +171 -50
  64. imap_processing/ultra/l1b/quality_flag_filters.py +14 -0
  65. imap_processing/ultra/l1b/ultra_l1b_culling.py +198 -5
  66. imap_processing/ultra/l1b/ultra_l1b_extended.py +304 -66
  67. imap_processing/ultra/l1c/helio_pset.py +54 -7
  68. imap_processing/ultra/l1c/spacecraft_pset.py +9 -1
  69. imap_processing/ultra/l1c/ultra_l1c.py +2 -0
  70. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +106 -109
  71. imap_processing/ultra/utils/ultra_l1_utils.py +13 -1
  72. {imap_processing-0.17.0.dist-info → imap_processing-0.18.0.dist-info}/METADATA +2 -2
  73. {imap_processing-0.17.0.dist-info → imap_processing-0.18.0.dist-info}/RECORD +76 -83
  74. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_LeftSlit.csv +0 -526
  75. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_RightSlit.csv +0 -526
  76. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_LeftSlit.csv +0 -526
  77. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_RightSlit.csv +0 -524
  78. imap_processing/ultra/lookup_tables/EgyNorm.mem.csv +0 -32769
  79. imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +0 -2
  80. imap_processing/ultra/lookup_tables/FM90_Startup1_ULTRA_IMGPARAMS_20240719.csv +0 -2
  81. imap_processing/ultra/lookup_tables/dps_grid45_compressed.cdf +0 -0
  82. imap_processing/ultra/lookup_tables/ultra45_back-pos-luts.csv +0 -4097
  83. imap_processing/ultra/lookup_tables/ultra45_tdc_norm.csv +0 -2050
  84. imap_processing/ultra/lookup_tables/ultra90_back-pos-luts.csv +0 -4097
  85. imap_processing/ultra/lookup_tables/ultra90_tdc_norm.csv +0 -2050
  86. imap_processing/ultra/lookup_tables/yadjust.csv +0 -257
  87. {imap_processing-0.17.0.dist-info → imap_processing-0.18.0.dist-info}/LICENSE +0 -0
  88. {imap_processing-0.17.0.dist-info → imap_processing-0.18.0.dist-info}/WHEEL +0 -0
  89. {imap_processing-0.17.0.dist-info → imap_processing-0.18.0.dist-info}/entry_points.txt +0 -0
@@ -1,10 +1,17 @@
1
1
  """Calculate Pointing Set Grids."""
2
2
 
3
- import astropy_healpix.healpy as hp
4
3
  import numpy as np
4
+ import pandas as pd
5
5
  import xarray as xr
6
6
 
7
- from imap_processing.ultra.l1c.ultra_l1c_pset_bins import build_energy_bins
7
+ from imap_processing.spice.time import sct_to_et
8
+ from imap_processing.ultra.l1c.ultra_l1c_pset_bins import (
9
+ build_energy_bins,
10
+ get_helio_background_rates,
11
+ get_helio_exposure_times,
12
+ get_helio_sensitivity,
13
+ get_spacecraft_histogram,
14
+ )
8
15
  from imap_processing.ultra.utils.ultra_l1_utils import create_dataset
9
16
 
10
17
 
@@ -36,17 +43,57 @@ def calculate_helio_pset(
36
43
  dataset : xarray.Dataset
37
44
  Dataset containing the data.
38
45
  """
39
- # TODO: Fill in the rest of this later.
40
46
  pset_dict: dict[str, np.ndarray] = {}
41
- healpix = np.arange(hp.nside2npix(128))
42
- _, _, energy_bin_geometric_means = build_energy_bins()
43
47
 
48
+ v_mag_helio_spacecraft = np.linalg.norm(
49
+ de_dataset["velocity_dps_helio"].values, axis=1
50
+ )
51
+ vhat_dps_helio = (
52
+ de_dataset["velocity_dps_helio"].values / v_mag_helio_spacecraft[:, np.newaxis]
53
+ )
54
+ intervals, _, energy_bin_geometric_means = build_energy_bins()
55
+ counts, latitude, longitude, n_pix = get_spacecraft_histogram(
56
+ vhat_dps_helio,
57
+ de_dataset["energy_heliosphere"].values,
58
+ intervals,
59
+ nside=128,
60
+ )
61
+
62
+ healpix = np.arange(n_pix)
63
+
64
+ # calculate background rates
65
+ background_rates = get_helio_background_rates()
66
+
67
+ efficiencies = ancillary_files["l1c-90sensor-efficiencies"]
68
+ geometric_function = ancillary_files["l1c-90sensor-gf"]
69
+
70
+ df_efficiencies = pd.read_csv(efficiencies)
71
+ df_geometric_function = pd.read_csv(geometric_function)
72
+ mid_time = sct_to_et(np.median(de_dataset["event_times"].data))
73
+ sensitivity = get_helio_sensitivity(
74
+ mid_time,
75
+ df_efficiencies,
76
+ df_geometric_function,
77
+ )
78
+
79
+ # Calculate exposure
80
+ constant_exposure = ancillary_files["l1c-90sensor-dps-exposure"]
81
+ df_exposure = pd.read_csv(constant_exposure)
82
+ exposure_pointing = get_helio_exposure_times(mid_time, df_exposure)
83
+
84
+ # For ISTP, epoch should be the center of the time bin.
44
85
  pset_dict["epoch"] = de_dataset.epoch.data[:1].astype(np.int64)
45
- pset_dict["pixel_index"] = healpix
86
+ pset_dict["counts"] = counts[np.newaxis, ...]
87
+ pset_dict["latitude"] = latitude[np.newaxis, ...]
88
+ pset_dict["longitude"] = longitude[np.newaxis, ...]
46
89
  pset_dict["energy_bin_geometric_mean"] = energy_bin_geometric_means
47
- pset_dict["exposure_factor"] = np.zeros(len(healpix), dtype=np.uint8)[
90
+ pset_dict["background_rates"] = background_rates[np.newaxis, ...]
91
+ pset_dict["helio_exposure_factor"] = exposure_pointing[np.newaxis, ...]
92
+ pset_dict["pixel_index"] = healpix
93
+ pset_dict["energy_bin_delta"] = np.diff(intervals, axis=1).squeeze()[
48
94
  np.newaxis, ...
49
95
  ]
96
+ pset_dict["sensitivity"] = sensitivity[np.newaxis, ...]
50
97
 
51
98
  dataset = create_dataset(pset_dict, name, "l1c")
52
99
 
@@ -18,6 +18,8 @@ def calculate_spacecraft_pset(
18
18
  de_dataset: xr.Dataset,
19
19
  extendedspin_dataset: xr.Dataset,
20
20
  cullingmask_dataset: xr.Dataset,
21
+ rates_dataset: xr.Dataset,
22
+ params_dataset: xr.Dataset,
21
23
  name: str,
22
24
  ancillary_files: dict,
23
25
  ) -> xr.Dataset:
@@ -32,6 +34,10 @@ def calculate_spacecraft_pset(
32
34
  Dataset containing extendedspin data.
33
35
  cullingmask_dataset : xarray.Dataset
34
36
  Dataset containing cullingmask data.
37
+ rates_dataset : xarray.Dataset
38
+ Dataset containing image rates data.
39
+ params_dataset : xarray.Dataset
40
+ Dataset containing image parameters data.
35
41
  name : str
36
42
  Name of the dataset.
37
43
  ancillary_files : dict
@@ -71,7 +77,9 @@ def calculate_spacecraft_pset(
71
77
  # Calculate exposure
72
78
  constant_exposure = ancillary_files["l1c-90sensor-dps-exposure"]
73
79
  df_exposure = pd.read_csv(constant_exposure)
74
- exposure_pointing = get_spacecraft_exposure_times(df_exposure)
80
+ exposure_pointing = get_spacecraft_exposure_times(
81
+ df_exposure, rates_dataset, params_dataset
82
+ )
75
83
 
76
84
  # For ISTP, epoch should be the center of the time bin.
77
85
  pset_dict["epoch"] = de_dataset.epoch.data[:1].astype(np.int64)
@@ -63,6 +63,8 @@ def ultra_l1c(
63
63
  data_dict[f"imap_ultra_l1b_{instrument_id}sensor-de"],
64
64
  data_dict[f"imap_ultra_l1b_{instrument_id}sensor-extendedspin"],
65
65
  data_dict[f"imap_ultra_l1b_{instrument_id}sensor-cullingmask"],
66
+ data_dict[f"imap_ultra_{instrument_id}sensor-rates"],
67
+ data_dict[f"imap_ultra_{instrument_id}sensor-params"],
66
68
  f"imap_ultra_l1c_{instrument_id}sensor-spacecraftpset",
67
69
  ancillary_files,
68
70
  )
@@ -4,6 +4,7 @@ import astropy_healpix.healpy as hp
4
4
  import numpy as np
5
5
  import pandas
6
6
  import pandas as pd
7
+ import xarray as xr
7
8
  from numpy.typing import NDArray
8
9
  from scipy.interpolate import interp1d
9
10
 
@@ -151,110 +152,6 @@ def get_spacecraft_histogram(
151
152
  return hist, latitude, longitude, n_pix
152
153
 
153
154
 
154
- def get_helio_histogram(
155
- time: NDArray,
156
- vhat: NDArray,
157
- energy: NDArray,
158
- energy_bin_edges: list[tuple[float, float]],
159
- nside: int = 128,
160
- nested: bool = False,
161
- ) -> tuple[NDArray, NDArray, NDArray, NDArray]:
162
- """
163
- Compute a 3D histogram of the particle data using HEALPix binning.
164
-
165
- Parameters
166
- ----------
167
- time : np.ndarray
168
- Median time of pointing in et.
169
- vhat : tuple[np.ndarray, np.ndarray, np.ndarray]
170
- The x,y,z-components of the unit velocity vector.
171
- energy : np.ndarray
172
- The particle energy.
173
- energy_bin_edges : list[tuple[float, float]]
174
- Array of energy bin edges.
175
- nside : int, optional
176
- The nside parameter of the Healpix tessellation.
177
- Default is 128.
178
- nested : bool, optional
179
- Whether the Healpix tessellation is nested. Default is False.
180
-
181
- Returns
182
- -------
183
- hist : np.ndarray
184
- A 3D histogram array with shape (n_pix, n_energy_bins).
185
- latitude : np.ndarray
186
- Array of latitude values.
187
- longitude : np.ndarray
188
- Array of longitude values.
189
- n_pix : int
190
- Number of healpix pixels.
191
-
192
- Notes
193
- -----
194
- The histogram will work properly for overlapping energy bins, i.e.
195
- the same energy value can fall into multiple bins if the intervals overlap.
196
-
197
- azimuthal angle [0, 360], elevation angle [-90, 90]
198
- """
199
- # Compute number of HEALPix pixels that cover the sphere
200
- n_pix = hp.nside2npix(nside)
201
-
202
- # Calculate the corresponding longitude (az) latitude (el)
203
- # center coordinates
204
- longitude, latitude = hp.pix2ang(nside, np.arange(n_pix), lonlat=True)
205
-
206
- # The Cartesian state vector representing the position and velocity of the
207
- # IMAP spacecraft.
208
- state = imap_state(time, ref_frame=SpiceFrame.IMAP_DPS)
209
-
210
- # Extract the velocity part of the state vector
211
- spacecraft_velocity = state[3:6]
212
-
213
- # Initialize histogram: (n_energy_bins, n_HEALPix pixels)
214
- hist = np.zeros((len(energy_bin_edges), n_pix))
215
-
216
- # Bin data in energy & HEALPix space
217
- for i, (e_min, e_max) in enumerate(energy_bin_edges):
218
- # Convert the midpoint energy to a velocity (km/s).
219
- # Based on kinetic energy equation: E = 1/2 * m * v^2.
220
- energy_midpoint = (e_min + e_max) / 2
221
- energy_velocity = (
222
- np.sqrt(2 * energy_midpoint * UltraConstants.KEV_J / UltraConstants.MASS_H)
223
- / 1e3
224
- )
225
-
226
- # Use Galilean Transform to transform the velocity wrt spacecraft
227
- # to the velocity wrt heliosphere.
228
- # energy_velocity * cartesian -> apply the magnitude of the velocity
229
- # to every position on the grid in the despun grid.
230
- mask = (energy >= e_min) & (energy < e_max)
231
- vx, vy, vz = vhat.T
232
-
233
- # Select only the particles that fall within the energy bin.
234
- vx_bin, vy_bin, vz_bin = vx[mask], vy[mask], vz[mask]
235
- vhat_bin = np.stack((vx_bin, vy_bin, vz_bin), axis=1)
236
- helio_velocity = spacecraft_velocity.reshape(1, 3) + energy_velocity * vhat_bin
237
-
238
- # Normalized vectors representing the direction of the heliocentric velocity.
239
- helio_normalized = -helio_velocity / np.linalg.norm(
240
- helio_velocity, axis=1, keepdims=True
241
- )
242
-
243
- # Convert Cartesian heliocentric vectors into spherical coordinates.
244
- # Result: azimuth (longitude) and elevation (latitude) in degrees.
245
- helio_spherical = cartesian_to_spherical(np.squeeze(helio_normalized))
246
- helio_spherical = np.atleast_2d(helio_spherical)
247
- az, el = helio_spherical[:, 1], helio_spherical[:, 2]
248
-
249
- # Convert azimuth/elevation directions to HEALPix pixel indices.
250
- hpix_idx = hp.ang2pix(nside, az, el, nest=nested, lonlat=True)
251
-
252
- # Only count the events that fall within the energy bin
253
- hist[i, :] += np.bincount(hpix_idx, minlength=n_pix).astype(np.float64)
254
-
255
- return hist, latitude, longitude, n_pix
256
-
257
-
258
155
  def get_spacecraft_background_rates(
259
156
  nside: int = 128,
260
157
  ) -> NDArray:
@@ -309,7 +206,98 @@ def get_helio_background_rates(
309
206
  return background
310
207
 
311
208
 
312
- def get_spacecraft_exposure_times(constant_exposure: pandas.DataFrame) -> NDArray:
209
+ def get_deadtime_correction_factors(sectored_rates_ds: xr.Dataset) -> xr.DataArray:
210
+ """
211
+ Compute the dead time correction factor at each sector.
212
+
213
+ Further description is available in section 3.4.3 of the IMAP-Ultra Algorithm
214
+ Document.
215
+
216
+ Parameters
217
+ ----------
218
+ sectored_rates_ds : xarray.Dataset
219
+ Dataset containing sector mode image rates data.
220
+
221
+ Returns
222
+ -------
223
+ dead_time_ratio : xarray.DataArray
224
+ Dead time correction factor for each sector.
225
+ """
226
+ # Compute the correction factor at each sector
227
+ a = sectored_rates_ds.fifo_valid_events / (
228
+ 1
229
+ - (sectored_rates_ds.event_active_time + 2 * sectored_rates_ds.start_pos) * 1e-7
230
+ )
231
+
232
+ start_full = sectored_rates_ds.start_rf + sectored_rates_ds.start_lf
233
+ b = a * np.exp(start_full * 1e-7 * 5)
234
+
235
+ coin_stop_nd = (
236
+ sectored_rates_ds.coin_tn
237
+ + sectored_rates_ds.coin_bn
238
+ - sectored_rates_ds.stop_tn
239
+ - sectored_rates_ds.stop_bn
240
+ )
241
+
242
+ corrected_valid_events = b * np.exp(1e-7 * 8 * coin_stop_nd)
243
+
244
+ # Compute dead time ratio
245
+ dead_time_ratios = sectored_rates_ds.fifo_valid_events / corrected_valid_events
246
+
247
+ return dead_time_ratios
248
+
249
+
250
+ def get_sectored_rates(rates_ds: xr.Dataset, params_ds: xr.Dataset) -> xr.Dataset:
251
+ """
252
+ Filter rates dataset to only include sector mode data.
253
+
254
+ Parameters
255
+ ----------
256
+ rates_ds : xarray.Dataset
257
+ Dataset containing image rates data.
258
+ params_ds : xarray.Dataset
259
+ Dataset containing image parameters data.
260
+
261
+ Returns
262
+ -------
263
+ rates : xarray.Dataset
264
+ Rates dataset with only the sector mode data.
265
+ """
266
+ # Find indices in which the parameters dataset, indicates that ULTRA was in
267
+ # sector mode. At the normal 15-second spin period, each 24° sector takes ~1 second.
268
+
269
+ # This means that data was collected as a function of spin allowing for fine grained
270
+ # rate analysis.
271
+ sector_mode_start_inds = np.where(params_ds["imageratescadence"] == 3)[0]
272
+ # get the sector mode start and stop indices
273
+ sector_mode_stop_inds = sector_mode_start_inds + 1
274
+ # get the sector mode start and stop times
275
+ mode_3_start = params_ds["epoch"].values[sector_mode_start_inds]
276
+
277
+ # if the last mode is a sector mode, we can assume that the sector data goes through
278
+ # the end of the dataset, so we append np.inf to the end of the last time range.
279
+ if sector_mode_stop_inds[-1] == len(params_ds["epoch"]):
280
+ mode_3_end = np.append(
281
+ params_ds["epoch"].values[sector_mode_stop_inds[:-1]], np.inf
282
+ )
283
+ else:
284
+ mode_3_end = params_ds["epoch"].values[sector_mode_stop_inds]
285
+
286
+ # Build a list of conditions for each sector mode time range
287
+ conditions = [
288
+ (rates_ds["epoch"] >= start) & (rates_ds["epoch"] < end)
289
+ for start, end in zip(mode_3_start, mode_3_end)
290
+ ]
291
+
292
+ sector_mode_mask = np.logical_or.reduce(conditions)
293
+ return rates_ds.isel(epoch=sector_mode_mask)
294
+
295
+
296
+ def get_spacecraft_exposure_times(
297
+ constant_exposure: pandas.DataFrame,
298
+ rates_dataset: xr.Dataset,
299
+ params_dataset: xr.Dataset,
300
+ ) -> NDArray:
313
301
  """
314
302
  Compute exposure times for HEALPix pixels.
315
303
 
@@ -317,6 +305,10 @@ def get_spacecraft_exposure_times(constant_exposure: pandas.DataFrame) -> NDArra
317
305
  ----------
318
306
  constant_exposure : pandas.DataFrame
319
307
  Exposure data.
308
+ rates_dataset : xarray.Dataset
309
+ Dataset containing image rates data.
310
+ params_dataset : xarray.Dataset
311
+ Dataset containing image parameters data.
320
312
 
321
313
  Returns
322
314
  -------
@@ -325,6 +317,11 @@ def get_spacecraft_exposure_times(constant_exposure: pandas.DataFrame) -> NDArra
325
317
  Healpix tessellation of the sky
326
318
  in the pointing (dps) frame.
327
319
  """
320
+ # TODO: uncomment these lines when the deadtime correction is implemented
321
+ # sectored_rates = get_sectored_rates(rates_dataset, params_dataset)
322
+ # get_deadtime_correction_factors(sectored_rates)
323
+ # TODO: calculate the deadtime correction function
324
+ # TODO: Apply the deadtime correction to the exposure times
328
325
  # TODO: use the universal spin table and
329
326
  # universal pointing table here to determine actual number of spins
330
327
  exposure_pointing = (
@@ -384,7 +381,7 @@ def get_helio_exposure_times(
384
381
  # Initialize output array.
385
382
  # Each row corresponds to a HEALPix pixel, and each column to an energy bin.
386
383
  npix = hp.nside2npix(nside)
387
- helio_exposure = np.zeros((npix, len(energy_midpoints)))
384
+ helio_exposure = np.zeros((len(energy_midpoints), npix))
388
385
 
389
386
  # Loop through energy bins and compute transformed exposure.
390
387
  for i, energy_midpoint in enumerate(energy_midpoints):
@@ -415,7 +412,7 @@ def get_helio_exposure_times(
415
412
  hpix_idx = hp.ang2pix(nside, az, el, nest=nested, lonlat=True)
416
413
 
417
414
  # Accumulate exposure values into HEALPix pixels for this energy bin.
418
- helio_exposure[:, i] = np.bincount(
415
+ helio_exposure[i, :] = np.bincount(
419
416
  hpix_idx, weights=exposure_flat, minlength=npix
420
417
  )
421
418
 
@@ -597,7 +594,7 @@ def get_helio_sensitivity(
597
594
  # Initialize output array.
598
595
  # Each row corresponds to a HEALPix pixel, and each column to an energy bin.
599
596
  npix = hp.nside2npix(nside)
600
- helio_sensitivity = np.zeros((npix, len(energy_midpoints)))
597
+ helio_sensitivity = np.zeros((len(energy_midpoints), npix))
601
598
 
602
599
  # Loop through energy bins and compute transformed sensitivity.
603
600
  for i, energy in enumerate(energy_midpoints):
@@ -628,7 +625,7 @@ def get_helio_sensitivity(
628
625
  gridded_sensitivity = grid_sensitivity(efficiencies, geometric_function, energy)
629
626
 
630
627
  # Accumulate sensitivity values into HEALPix pixels for this energy bin.
631
- helio_sensitivity[:, i] = np.bincount(
628
+ helio_sensitivity[i, :] = np.bincount(
632
629
  hpix_idx, weights=gridded_sensitivity, minlength=npix
633
630
  )
634
631
 
@@ -91,6 +91,7 @@ def create_dataset( # noqa: PLR0912
91
91
  "ena_rates_threshold",
92
92
  "quality_ena_rates",
93
93
  }
94
+ rates_pulse_keys = {"start_per_spin", "stop_per_spin", "coin_per_spin"}
94
95
 
95
96
  for key, data in data_dict.items():
96
97
  # Skip keys that are coordinates.
@@ -114,6 +115,12 @@ def create_dataset( # noqa: PLR0912
114
115
  dims=["epoch", "energy_bin_geometric_mean"],
115
116
  attrs=cdf_manager.get_variable_attributes(key, check_schema=False),
116
117
  )
118
+ elif key in rates_pulse_keys:
119
+ dataset[key] = xr.DataArray(
120
+ data,
121
+ dims=["spin_number"],
122
+ attrs=cdf_manager.get_variable_attributes(key, check_schema=False),
123
+ )
117
124
  elif key in rates_keys:
118
125
  dataset[key] = xr.DataArray(
119
126
  data,
@@ -126,7 +133,12 @@ def create_dataset( # noqa: PLR0912
126
133
  dims=["epoch", "pixel_index"],
127
134
  attrs=cdf_manager.get_variable_attributes(key, check_schema=False),
128
135
  )
129
- elif key in {"counts", "background_rates", "sensitivity"}:
136
+ elif key in {
137
+ "counts",
138
+ "background_rates",
139
+ "helio_exposure_factor",
140
+ "sensitivity",
141
+ }:
130
142
  dataset[key] = xr.DataArray(
131
143
  data,
132
144
  dims=["epoch", "energy_bin_geometric_mean", "pixel_index"],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: imap-processing
3
- Version: 0.17.0
3
+ Version: 0.18.0
4
4
  Summary: IMAP Science Operations Center Processing
5
5
  License: MIT
6
6
  Keywords: IMAP,SDC,SOC,Science Operations
@@ -30,7 +30,7 @@ Provides-Extra: tools
30
30
  Requires-Dist: astropy-healpix (>=1.0)
31
31
  Requires-Dist: cdflib (>=1.3.1,<2.0.0)
32
32
  Requires-Dist: healpy (>=1.18.0,<2.0.0) ; extra == "map-visualization"
33
- Requires-Dist: imap-data-access (>=0.31.0)
33
+ Requires-Dist: imap-data-access (>=0.32.0)
34
34
  Requires-Dist: mypy (==1.10.1) ; extra == "dev"
35
35
  Requires-Dist: netcdf4 (>=1.7.2,<2.0.0) ; extra == "test"
36
36
  Requires-Dist: numpy (<=3)