imap-processing 0.17.0__py3-none-any.whl → 0.19.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 (141) hide show
  1. imap_processing/_version.py +2 -2
  2. imap_processing/ancillary/ancillary_dataset_combiner.py +161 -1
  3. imap_processing/ccsds/excel_to_xtce.py +12 -0
  4. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +6 -6
  5. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +312 -274
  6. imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +39 -28
  7. imap_processing/cdf/config/imap_codice_l2_variable_attrs.yaml +1048 -183
  8. imap_processing/cdf/config/imap_constant_attrs.yaml +4 -2
  9. imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +12 -0
  10. imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +5 -0
  11. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +10 -4
  12. imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +163 -100
  13. imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml +4 -4
  14. imap_processing/cdf/config/imap_ialirt_l1_variable_attrs.yaml +97 -54
  15. imap_processing/cdf/config/imap_idex_l2a_variable_attrs.yaml +33 -4
  16. imap_processing/cdf/config/imap_idex_l2b_variable_attrs.yaml +44 -44
  17. imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml +77 -61
  18. imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +30 -0
  19. imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +4 -15
  20. imap_processing/cdf/config/imap_lo_l1c_variable_attrs.yaml +189 -98
  21. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +99 -2
  22. imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +24 -1
  23. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +60 -0
  24. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +99 -11
  25. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +50 -7
  26. imap_processing/cli.py +121 -44
  27. imap_processing/codice/codice_l1a.py +165 -77
  28. imap_processing/codice/codice_l1b.py +1 -1
  29. imap_processing/codice/codice_l2.py +118 -19
  30. imap_processing/codice/constants.py +1217 -1089
  31. imap_processing/decom.py +1 -4
  32. imap_processing/ena_maps/ena_maps.py +32 -25
  33. imap_processing/ena_maps/utils/naming.py +8 -2
  34. imap_processing/glows/ancillary/imap_glows_exclusions-by-instr-team_20250923_v002.dat +10 -0
  35. imap_processing/glows/ancillary/imap_glows_map-of-excluded-regions_20250923_v002.dat +393 -0
  36. imap_processing/glows/ancillary/imap_glows_map-of-uv-sources_20250923_v002.dat +593 -0
  37. imap_processing/glows/ancillary/imap_glows_pipeline_settings_20250923_v002.json +54 -0
  38. imap_processing/glows/ancillary/imap_glows_suspected-transients_20250923_v002.dat +10 -0
  39. imap_processing/glows/l1b/glows_l1b.py +99 -9
  40. imap_processing/glows/l1b/glows_l1b_data.py +350 -38
  41. imap_processing/glows/l2/glows_l2.py +11 -0
  42. imap_processing/hi/hi_l1a.py +124 -3
  43. imap_processing/hi/hi_l1b.py +154 -71
  44. imap_processing/hi/hi_l2.py +84 -51
  45. imap_processing/hi/utils.py +153 -8
  46. imap_processing/hit/l0/constants.py +3 -0
  47. imap_processing/hit/l0/decom_hit.py +5 -8
  48. imap_processing/hit/l1a/hit_l1a.py +375 -45
  49. imap_processing/hit/l1b/constants.py +5 -0
  50. imap_processing/hit/l1b/hit_l1b.py +61 -131
  51. imap_processing/hit/l2/constants.py +1 -1
  52. imap_processing/hit/l2/hit_l2.py +10 -11
  53. imap_processing/ialirt/calculate_ingest.py +219 -0
  54. imap_processing/ialirt/constants.py +32 -1
  55. imap_processing/ialirt/generate_coverage.py +201 -0
  56. imap_processing/ialirt/l0/ialirt_spice.py +5 -2
  57. imap_processing/ialirt/l0/parse_mag.py +337 -29
  58. imap_processing/ialirt/l0/process_hit.py +5 -3
  59. imap_processing/ialirt/l0/process_swapi.py +41 -25
  60. imap_processing/ialirt/l0/process_swe.py +23 -7
  61. imap_processing/ialirt/process_ephemeris.py +70 -14
  62. imap_processing/ialirt/utils/constants.py +22 -16
  63. imap_processing/ialirt/utils/create_xarray.py +42 -19
  64. imap_processing/idex/idex_constants.py +1 -5
  65. imap_processing/idex/idex_l0.py +2 -2
  66. imap_processing/idex/idex_l1a.py +2 -3
  67. imap_processing/idex/idex_l1b.py +2 -3
  68. imap_processing/idex/idex_l2a.py +130 -4
  69. imap_processing/idex/idex_l2b.py +313 -119
  70. imap_processing/idex/idex_utils.py +1 -3
  71. imap_processing/lo/l0/lo_apid.py +1 -0
  72. imap_processing/lo/l0/lo_science.py +25 -24
  73. imap_processing/lo/l1a/lo_l1a.py +44 -0
  74. imap_processing/lo/l1b/lo_l1b.py +3 -3
  75. imap_processing/lo/l1c/lo_l1c.py +116 -50
  76. imap_processing/lo/l2/lo_l2.py +29 -29
  77. imap_processing/lo/lo_ancillary.py +55 -0
  78. imap_processing/lo/packet_definitions/lo_xtce.xml +5359 -106
  79. imap_processing/mag/constants.py +1 -0
  80. imap_processing/mag/l1a/mag_l1a.py +1 -0
  81. imap_processing/mag/l1a/mag_l1a_data.py +26 -0
  82. imap_processing/mag/l1b/mag_l1b.py +3 -2
  83. imap_processing/mag/l1c/interpolation_methods.py +14 -15
  84. imap_processing/mag/l1c/mag_l1c.py +23 -6
  85. imap_processing/mag/l1d/__init__.py +0 -0
  86. imap_processing/mag/l1d/mag_l1d.py +176 -0
  87. imap_processing/mag/l1d/mag_l1d_data.py +725 -0
  88. imap_processing/mag/l2/__init__.py +0 -0
  89. imap_processing/mag/l2/mag_l2.py +25 -20
  90. imap_processing/mag/l2/mag_l2_data.py +199 -130
  91. imap_processing/quality_flags.py +28 -2
  92. imap_processing/spice/geometry.py +101 -36
  93. imap_processing/spice/pointing_frame.py +1 -7
  94. imap_processing/spice/repoint.py +29 -2
  95. imap_processing/spice/spin.py +32 -8
  96. imap_processing/spice/time.py +60 -19
  97. imap_processing/swapi/l1/swapi_l1.py +10 -4
  98. imap_processing/swapi/l2/swapi_l2.py +66 -24
  99. imap_processing/swapi/swapi_utils.py +1 -1
  100. imap_processing/swe/l1b/swe_l1b.py +3 -6
  101. imap_processing/ultra/constants.py +28 -3
  102. imap_processing/ultra/l0/decom_tools.py +15 -8
  103. imap_processing/ultra/l0/decom_ultra.py +35 -11
  104. imap_processing/ultra/l0/ultra_utils.py +102 -12
  105. imap_processing/ultra/l1a/ultra_l1a.py +26 -6
  106. imap_processing/ultra/l1b/cullingmask.py +6 -3
  107. imap_processing/ultra/l1b/de.py +122 -26
  108. imap_processing/ultra/l1b/extendedspin.py +29 -2
  109. imap_processing/ultra/l1b/lookup_utils.py +424 -50
  110. imap_processing/ultra/l1b/quality_flag_filters.py +23 -0
  111. imap_processing/ultra/l1b/ultra_l1b_culling.py +356 -5
  112. imap_processing/ultra/l1b/ultra_l1b_extended.py +534 -90
  113. imap_processing/ultra/l1c/helio_pset.py +127 -7
  114. imap_processing/ultra/l1c/l1c_lookup_utils.py +256 -0
  115. imap_processing/ultra/l1c/spacecraft_pset.py +90 -15
  116. imap_processing/ultra/l1c/ultra_l1c.py +6 -0
  117. imap_processing/ultra/l1c/ultra_l1c_culling.py +85 -0
  118. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +446 -341
  119. imap_processing/ultra/l2/ultra_l2.py +0 -1
  120. imap_processing/ultra/utils/ultra_l1_utils.py +40 -3
  121. imap_processing/utils.py +3 -4
  122. {imap_processing-0.17.0.dist-info → imap_processing-0.19.0.dist-info}/METADATA +3 -3
  123. {imap_processing-0.17.0.dist-info → imap_processing-0.19.0.dist-info}/RECORD +126 -126
  124. imap_processing/idex/idex_l2c.py +0 -250
  125. imap_processing/spice/kernels.py +0 -187
  126. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_LeftSlit.csv +0 -526
  127. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_RightSlit.csv +0 -526
  128. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_LeftSlit.csv +0 -526
  129. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_RightSlit.csv +0 -524
  130. imap_processing/ultra/lookup_tables/EgyNorm.mem.csv +0 -32769
  131. imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +0 -2
  132. imap_processing/ultra/lookup_tables/FM90_Startup1_ULTRA_IMGPARAMS_20240719.csv +0 -2
  133. imap_processing/ultra/lookup_tables/dps_grid45_compressed.cdf +0 -0
  134. imap_processing/ultra/lookup_tables/ultra45_back-pos-luts.csv +0 -4097
  135. imap_processing/ultra/lookup_tables/ultra45_tdc_norm.csv +0 -2050
  136. imap_processing/ultra/lookup_tables/ultra90_back-pos-luts.csv +0 -4097
  137. imap_processing/ultra/lookup_tables/ultra90_tdc_norm.csv +0 -2050
  138. imap_processing/ultra/lookup_tables/yadjust.csv +0 -257
  139. {imap_processing-0.17.0.dist-info → imap_processing-0.19.0.dist-info}/LICENSE +0 -0
  140. {imap_processing-0.17.0.dist-info → imap_processing-0.19.0.dist-info}/WHEEL +0 -0
  141. {imap_processing-0.17.0.dist-info → imap_processing-0.19.0.dist-info}/entry_points.txt +0 -0
@@ -4,12 +4,20 @@ import numpy as np
4
4
  import xarray as xr
5
5
 
6
6
  from imap_processing.cdf.utils import parse_filename_like
7
+ from imap_processing.quality_flags import (
8
+ ImapDEOutliersUltraFlags,
9
+ ImapDEScatteringUltraFlags,
10
+ )
7
11
  from imap_processing.spice.geometry import SpiceFrame
12
+ from imap_processing.ultra.l1b.lookup_utils import get_geometric_factor
8
13
  from imap_processing.ultra.l1b.ultra_l1b_annotated import (
9
14
  get_annotated_particle_velocity,
10
15
  )
16
+ from imap_processing.ultra.l1b.ultra_l1b_culling import flag_scattering
11
17
  from imap_processing.ultra.l1b.ultra_l1b_extended import (
12
18
  StopType,
19
+ determine_ebin_pulse_height,
20
+ determine_ebin_ssd,
13
21
  determine_species,
14
22
  get_coincidence_positions,
15
23
  get_ctof,
@@ -25,8 +33,11 @@ from imap_processing.ultra.l1b.ultra_l1b_extended import (
25
33
  get_path_length,
26
34
  get_ph_tof_and_back_positions,
27
35
  get_phi_theta,
36
+ get_spin_number,
28
37
  get_ssd_back_position_and_tof_offset,
29
38
  get_ssd_tof,
39
+ is_back_tof_valid,
40
+ is_coin_ph_valid,
30
41
  )
31
42
  from imap_processing.ultra.utils.ultra_l1_utils import create_dataset
32
43
 
@@ -59,7 +70,10 @@ def calculate_de(
59
70
 
60
71
  # Define epoch and spin.
61
72
  de_dict["epoch"] = de_dataset["epoch"].data
62
- de_dict["spin"] = de_dataset["spin"].data
73
+ spin_number = get_spin_number(
74
+ de_dataset["shcoarse"].values, de_dataset["spin"].values
75
+ )
76
+ de_dict["spin"] = spin_number
63
77
 
64
78
  # Add already populated fields.
65
79
  keys = [
@@ -80,7 +94,10 @@ def calculate_de(
80
94
  ]
81
95
 
82
96
  de_dict.update(
83
- {key: de_dataset[dataset_key] for key, dataset_key in zip(keys, dataset_keys)}
97
+ {
98
+ key: de_dataset[dataset_key]
99
+ for key, dataset_key in zip(keys, dataset_keys, strict=False)
100
+ }
84
101
  )
85
102
 
86
103
  valid_mask = de_dataset["start_type"].data != FILLVAL_UINT8
@@ -106,8 +123,10 @@ def calculate_de(
106
123
  tof = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32)
107
124
  etof = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32)
108
125
  ctof = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32)
126
+ tof_energy = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32)
109
127
  magnitude_v = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32)
110
128
  energy = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32)
129
+ e_bin = np.full(len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8)
111
130
  species_bin = np.full(len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8)
112
131
  t2 = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32)
113
132
  event_times = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32)
@@ -116,40 +135,56 @@ def calculate_de(
116
135
  sc_dps_velocity = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32)
117
136
  helio_velocity = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32)
118
137
  spin_starts = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float64)
119
- spin_period_sec = np.full(
120
- len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float64
121
- )
138
+ velocities = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32)
139
+ v_hat = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32)
140
+ r_hat = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32)
141
+
122
142
  start_type = np.full(len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8)
143
+ quality_flags = np.full(
144
+ de_dataset["epoch"].shape, ImapDEOutliersUltraFlags.NONE.value, dtype=np.uint16
145
+ )
146
+ scattering_quality_flags = np.full(
147
+ de_dataset["epoch"].shape,
148
+ ImapDEScatteringUltraFlags.NONE.value,
149
+ dtype=np.uint16,
150
+ )
123
151
 
124
152
  xf[valid_indices] = get_front_x_position(
125
153
  de_dataset["start_type"].data[valid_indices],
126
154
  de_dataset["start_pos_tdc"].data[valid_indices],
127
155
  f"ultra{sensor}",
156
+ ancillary_files,
128
157
  )
129
158
  start_type[valid_indices] = de_dataset["start_type"].data[valid_indices]
130
159
 
131
160
  (
132
161
  event_times[valid_indices],
133
162
  spin_starts[valid_indices],
134
- spin_period_sec[valid_indices],
163
+ _,
135
164
  ) = get_eventtimes(
136
- de_dataset["spin"].data[valid_indices],
165
+ de_dict["spin"][valid_indices],
137
166
  de_dataset["phase_angle"].data[valid_indices],
138
167
  )
139
168
 
140
169
  # Pulse height
141
- tof[ph_indices], t2[ph_indices], xb[ph_indices], yb[ph_indices] = (
142
- get_ph_tof_and_back_positions(de_dataset, xf, f"ultra{sensor}")
170
+ ph_result = get_ph_tof_and_back_positions(
171
+ de_dataset, xf, f"ultra{sensor}", ancillary_files
143
172
  )
173
+ tof[ph_indices] = ph_result.tof
174
+ t2[ph_indices] = ph_result.t2
175
+ xb[ph_indices] = ph_result.xb
176
+ yb[ph_indices] = ph_result.yb
144
177
  d[ph_indices], yf[ph_indices] = get_front_y_position(
145
- de_dataset["start_type"].data[ph_indices], yb[ph_indices]
178
+ de_dataset["start_type"].data[ph_indices], yb[ph_indices], ancillary_files
146
179
  )
147
- energy[ph_indices] = get_energy_pulse_height(
180
+ energy[ph_indices], _ = get_energy_pulse_height(
148
181
  de_dataset["stop_type"].data[ph_indices],
149
182
  de_dataset["energy_ph"].data[ph_indices],
150
183
  xb[ph_indices],
151
184
  yb[ph_indices],
152
185
  f"ultra{sensor}",
186
+ ancillary_files,
187
+ quality_flags[ph_indices],
153
188
  )
154
189
  r[ph_indices] = get_path_length(
155
190
  (xf[ph_indices], yf[ph_indices]),
@@ -163,24 +198,48 @@ def calculate_de(
163
198
  )
164
199
  species_bin[ph_indices] = determine_species(tof[ph_indices], r[ph_indices], "PH")
165
200
  etof[ph_indices], xc[ph_indices] = get_coincidence_positions(
166
- de_dataset.isel(epoch=ph_indices), t2[ph_indices], f"ultra{sensor}"
201
+ de_dataset.isel(epoch=ph_indices),
202
+ t2[ph_indices],
203
+ f"ultra{sensor}",
204
+ ancillary_files,
205
+ )
206
+ backtofvalid = is_back_tof_valid(
207
+ de_dataset,
208
+ xf,
209
+ f"ultra{sensor}",
210
+ ancillary_files,
211
+ )
212
+ coinphvalid = is_coin_ph_valid(
213
+ etof[ph_indices],
214
+ xc[ph_indices],
215
+ xb[ph_indices],
216
+ f"ultra{sensor}",
217
+ ancillary_files,
218
+ )
219
+ e_bin[ph_indices] = determine_ebin_pulse_height(
220
+ energy[ph_indices],
221
+ tof[ph_indices],
222
+ r[ph_indices],
223
+ backtofvalid,
224
+ coinphvalid,
225
+ ancillary_files,
167
226
  )
168
227
  ctof[ph_indices], magnitude_v[ph_indices] = get_ctof(
169
228
  tof[ph_indices], r[ph_indices], "PH"
170
229
  )
171
230
 
172
231
  # SSD
173
- tof[ssd_indices] = get_ssd_tof(de_dataset, xf, f"ultra{sensor}")
232
+ tof[ssd_indices] = get_ssd_tof(de_dataset, xf, f"ultra{sensor}", ancillary_files)
174
233
  yb[ssd_indices], _, ssd_number = get_ssd_back_position_and_tof_offset(
175
- de_dataset, f"ultra{sensor}"
234
+ de_dataset, f"ultra{sensor}", ancillary_files
176
235
  )
177
236
  xc[ssd_indices] = np.zeros(len(ssd_indices))
178
237
  xb[ssd_indices] = np.zeros(len(ssd_indices))
179
238
  etof[ssd_indices] = np.zeros(len(ssd_indices))
180
239
  d[ssd_indices], yf[ssd_indices] = get_front_y_position(
181
- de_dataset["start_type"].data[ssd_indices], yb[ssd_indices]
240
+ de_dataset["start_type"].data[ssd_indices], yb[ssd_indices], ancillary_files
182
241
  )
183
- energy[ssd_indices] = get_energy_ssd(de_dataset, ssd_number)
242
+ energy[ssd_indices] = get_energy_ssd(de_dataset, ssd_number, ancillary_files)
184
243
  r[ssd_indices] = get_path_length(
185
244
  (xf[ssd_indices], yf[ssd_indices]),
186
245
  (xb[ssd_indices], yb[ssd_indices]),
@@ -191,6 +250,13 @@ def calculate_de(
191
250
  (xb[ssd_indices], yb[ssd_indices]),
192
251
  d[ssd_indices],
193
252
  )
253
+ e_bin[ssd_indices] = determine_ebin_ssd(
254
+ energy[ssd_indices],
255
+ tof[ssd_indices],
256
+ r[ssd_indices],
257
+ f"ultra{sensor}",
258
+ ancillary_files,
259
+ )
194
260
  species_bin[ssd_indices] = determine_species(
195
261
  tof[ssd_indices], r[ssd_indices], "SSD"
196
262
  )
@@ -202,7 +268,6 @@ def calculate_de(
202
268
  de_dict["x_front"] = xf.astype(np.float32)
203
269
  de_dict["event_times"] = event_times
204
270
  de_dict["spin_starts"] = spin_starts
205
- de_dict["spin_period"] = spin_period_sec
206
271
  de_dict["y_front"] = yf
207
272
  de_dict["x_back"] = xb
208
273
  de_dict["y_back"] = yb
@@ -216,18 +281,24 @@ def calculate_de(
216
281
  de_dict["phi"] = phi
217
282
  de_dict["theta"] = theta
218
283
 
219
- v, vhat, r = get_de_velocity(
220
- (de_dict["x_front"], de_dict["y_front"]),
221
- (de_dict["x_back"], de_dict["y_back"]),
222
- de_dict["front_back_distance"],
223
- de_dict["tof_start_stop"],
284
+ velocities[valid_indices], v_hat[valid_indices], r_hat[valid_indices] = (
285
+ get_de_velocity(
286
+ (de_dict["x_front"][valid_indices], de_dict["y_front"][valid_indices]),
287
+ (de_dict["x_back"][valid_indices], de_dict["y_back"][valid_indices]),
288
+ de_dict["front_back_distance"][valid_indices],
289
+ de_dict["tof_start_stop"][valid_indices],
290
+ )
224
291
  )
225
- de_dict["direct_event_velocity"] = v.astype(np.float32)
226
- de_dict["direct_event_unit_velocity"] = vhat.astype(np.float32)
227
- de_dict["direct_event_unit_position"] = r.astype(np.float32)
292
+ de_dict["direct_event_velocity"] = velocities.astype(np.float32)
293
+ de_dict["direct_event_unit_velocity"] = v_hat.astype(np.float32)
294
+ de_dict["direct_event_unit_position"] = r_hat.astype(np.float32)
228
295
 
229
- de_dict["tof_energy"] = get_de_energy_kev(v, species_bin)
296
+ tof_energy[valid_indices] = get_de_energy_kev(
297
+ velocities[valid_indices], species_bin[valid_indices]
298
+ )
299
+ de_dict["tof_energy"] = tof_energy
230
300
  de_dict["energy"] = energy
301
+ de_dict["ebin"] = e_bin
231
302
  de_dict["species"] = species_bin
232
303
 
233
304
  # Annotated Events.
@@ -261,10 +332,35 @@ def calculate_de(
261
332
  de_dict["tof_energy"],
262
333
  de_dict["phi"],
263
334
  de_dict["theta"],
335
+ ancillary_files,
264
336
  )
265
337
  de_dict["event_efficiency"] = get_efficiency(
266
338
  de_dict["tof_energy"], de_dict["phi"], de_dict["theta"], ancillary_files
267
339
  )
340
+ de_dict["geometric_factor_blades"] = get_geometric_factor(
341
+ de_dict["phi"],
342
+ de_dict["theta"],
343
+ quality_flags,
344
+ ancillary_files,
345
+ "l1b-sensor-gf-blades",
346
+ )
347
+ de_dict["geometric_factor_noblades"] = get_geometric_factor(
348
+ de_dict["phi"],
349
+ de_dict["theta"],
350
+ quality_flags,
351
+ ancillary_files,
352
+ "l1b-sensor-gf-noblades",
353
+ )
354
+ de_dict["quality_outliers"] = quality_flags
355
+ flag_scattering(
356
+ de_dict["tof_energy"],
357
+ de_dict["theta"],
358
+ de_dict["phi"],
359
+ ancillary_files,
360
+ sensor,
361
+ scattering_quality_flags,
362
+ )
363
+ de_dict["quality_scattering"] = scattering_quality_flags
268
364
 
269
365
  dataset = create_dataset(de_dict, name, "l1b")
270
366
 
@@ -4,12 +4,18 @@ import numpy as np
4
4
  import xarray as xr
5
5
 
6
6
  from imap_processing.ultra.l1b.ultra_l1b_culling import (
7
+ count_rejected_events_per_spin,
7
8
  flag_attitude,
8
- flag_spin,
9
+ flag_hk,
10
+ flag_imap_instruments,
11
+ flag_rates,
9
12
  get_energy_histogram,
13
+ get_pulses_per_spin,
10
14
  )
11
15
  from imap_processing.ultra.utils.ultra_l1_utils import create_dataset
12
16
 
17
+ FILLVAL_UINT16 = 65535
18
+
13
19
 
14
20
  def calculate_extendedspin(
15
21
  dict_datasets: dict[str, xr.Dataset],
@@ -34,10 +40,11 @@ def calculate_extendedspin(
34
40
  Dataset containing the data.
35
41
  """
36
42
  aux_dataset = dict_datasets[f"imap_ultra_l1a_{instrument_id}sensor-aux"]
43
+ rates_dataset = dict_datasets[f"imap_ultra_l1a_{instrument_id}sensor-rates"]
37
44
  de_dataset = dict_datasets[f"imap_ultra_l1b_{instrument_id}sensor-de"]
38
45
 
39
46
  extendedspin_dict = {}
40
- rates_qf, spin, energy_midpoints, n_sigma_per_energy = flag_spin(
47
+ rates_qf, spin, energy_midpoints, n_sigma_per_energy = flag_rates(
41
48
  de_dataset["spin"].values,
42
49
  de_dataset["energy"].values,
43
50
  )
@@ -47,12 +54,26 @@ def calculate_extendedspin(
47
54
  attitude_qf, spin_rates, spin_period, spin_starttime = flag_attitude(
48
55
  de_dataset["spin"].values, aux_dataset
49
56
  )
57
+ # TODO: We will add to this later
58
+ hk_qf = flag_hk(de_dataset["spin"].values)
59
+ inst_qf = flag_imap_instruments(de_dataset["spin"].values)
60
+
50
61
  # Get the first epoch for each spin.
51
62
  mask = xr.DataArray(np.isin(de_dataset["spin"], spin), dims="epoch")
52
63
  filtered_dataset = de_dataset.where(mask, drop=True)
53
64
  _, first_indices = np.unique(filtered_dataset["spin"].values, return_index=True)
54
65
  first_epochs = filtered_dataset["epoch"].values[first_indices]
55
66
 
67
+ # Get the number of pulses per spin.
68
+ pulses = get_pulses_per_spin(rates_dataset)
69
+
70
+ # Track rejected events in each spin based on
71
+ # quality flags in de l1b data.
72
+ rejected_counts = count_rejected_events_per_spin(
73
+ de_dataset["spin"].values,
74
+ de_dataset["quality_scattering"].values,
75
+ de_dataset["quality_outliers"].values,
76
+ )
56
77
  # These will be the coordinates.
57
78
  extendedspin_dict["epoch"] = first_epochs
58
79
  extendedspin_dict["spin_number"] = spin
@@ -63,8 +84,14 @@ def calculate_extendedspin(
63
84
  extendedspin_dict["spin_start_time"] = spin_starttime
64
85
  extendedspin_dict["spin_period"] = spin_period
65
86
  extendedspin_dict["spin_rate"] = spin_rates
87
+ extendedspin_dict["start_pulses_per_spin"] = pulses.start_per_spin
88
+ extendedspin_dict["stop_pulses_per_spin"] = pulses.stop_per_spin
89
+ extendedspin_dict["coin_pulses_per_spin"] = pulses.coin_per_spin
90
+ extendedspin_dict["rejected_events_per_spin"] = rejected_counts
66
91
  extendedspin_dict["quality_attitude"] = attitude_qf
67
92
  extendedspin_dict["quality_ena_rates"] = rates_qf
93
+ extendedspin_dict["quality_hk"] = hk_qf
94
+ extendedspin_dict["quality_instruments"] = inst_qf
68
95
 
69
96
  extendedspin_dataset = create_dataset(extendedspin_dict, name, "l1b")
70
97