imap-processing 0.18.0__py3-none-any.whl → 0.19.2__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 (122) hide show
  1. imap_processing/_version.py +2 -2
  2. imap_processing/ancillary/ancillary_dataset_combiner.py +161 -1
  3. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +6 -0
  4. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +221 -1057
  5. imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +307 -283
  6. imap_processing/cdf/config/imap_codice_l2_variable_attrs.yaml +1044 -203
  7. imap_processing/cdf/config/imap_constant_attrs.yaml +4 -2
  8. imap_processing/cdf/config/imap_enamaps_l2-common_variable_attrs.yaml +11 -0
  9. imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +15 -1
  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_idex_l2a_variable_attrs.yaml +33 -4
  13. imap_processing/cdf/config/imap_idex_l2b_variable_attrs.yaml +8 -91
  14. imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml +106 -16
  15. imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +5 -4
  16. imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +4 -15
  17. imap_processing/cdf/config/imap_lo_l1c_variable_attrs.yaml +189 -98
  18. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +85 -2
  19. imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +24 -1
  20. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +20 -8
  21. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +45 -35
  22. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +110 -7
  23. imap_processing/cli.py +138 -93
  24. imap_processing/codice/codice_l0.py +2 -1
  25. imap_processing/codice/codice_l1a.py +167 -69
  26. imap_processing/codice/codice_l1b.py +42 -32
  27. imap_processing/codice/codice_l2.py +215 -9
  28. imap_processing/codice/constants.py +790 -603
  29. imap_processing/codice/data/lo_stepping_values.csv +1 -1
  30. imap_processing/decom.py +1 -4
  31. imap_processing/ena_maps/ena_maps.py +71 -43
  32. imap_processing/ena_maps/utils/corrections.py +291 -0
  33. imap_processing/ena_maps/utils/map_utils.py +20 -4
  34. imap_processing/ena_maps/utils/naming.py +8 -2
  35. imap_processing/glows/ancillary/imap_glows_exclusions-by-instr-team_20250923_v002.dat +10 -0
  36. imap_processing/glows/ancillary/imap_glows_map-of-excluded-regions_20250923_v002.dat +393 -0
  37. imap_processing/glows/ancillary/imap_glows_map-of-uv-sources_20250923_v002.dat +593 -0
  38. imap_processing/glows/ancillary/imap_glows_pipeline-settings_20250923_v002.json +54 -0
  39. imap_processing/glows/ancillary/imap_glows_suspected-transients_20250923_v002.dat +10 -0
  40. imap_processing/glows/l1b/glows_l1b.py +123 -18
  41. imap_processing/glows/l1b/glows_l1b_data.py +358 -47
  42. imap_processing/glows/l2/glows_l2.py +11 -0
  43. imap_processing/hi/hi_l1a.py +124 -3
  44. imap_processing/hi/hi_l1b.py +154 -71
  45. imap_processing/hi/hi_l1c.py +4 -109
  46. imap_processing/hi/hi_l2.py +104 -60
  47. imap_processing/hi/utils.py +262 -8
  48. imap_processing/hit/l0/constants.py +3 -0
  49. imap_processing/hit/l0/decom_hit.py +3 -6
  50. imap_processing/hit/l1a/hit_l1a.py +311 -21
  51. imap_processing/hit/l1b/hit_l1b.py +54 -126
  52. imap_processing/hit/l2/hit_l2.py +6 -6
  53. imap_processing/ialirt/calculate_ingest.py +219 -0
  54. imap_processing/ialirt/constants.py +12 -2
  55. imap_processing/ialirt/generate_coverage.py +15 -2
  56. imap_processing/ialirt/l0/ialirt_spice.py +6 -2
  57. imap_processing/ialirt/l0/parse_mag.py +293 -42
  58. imap_processing/ialirt/l0/process_hit.py +5 -3
  59. imap_processing/ialirt/l0/process_swapi.py +41 -25
  60. imap_processing/ialirt/process_ephemeris.py +70 -14
  61. imap_processing/ialirt/utils/create_xarray.py +1 -1
  62. imap_processing/idex/idex_l0.py +2 -2
  63. imap_processing/idex/idex_l1a.py +2 -3
  64. imap_processing/idex/idex_l1b.py +2 -3
  65. imap_processing/idex/idex_l2a.py +130 -4
  66. imap_processing/idex/idex_l2b.py +158 -143
  67. imap_processing/idex/idex_utils.py +1 -3
  68. imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv +75 -0
  69. imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv +75 -0
  70. imap_processing/lo/l0/lo_science.py +25 -24
  71. imap_processing/lo/l1b/lo_l1b.py +93 -19
  72. imap_processing/lo/l1c/lo_l1c.py +273 -93
  73. imap_processing/lo/l2/lo_l2.py +949 -135
  74. imap_processing/lo/lo_ancillary.py +55 -0
  75. imap_processing/mag/l1a/mag_l1a.py +1 -0
  76. imap_processing/mag/l1a/mag_l1a_data.py +26 -0
  77. imap_processing/mag/l1b/mag_l1b.py +3 -2
  78. imap_processing/mag/l1c/interpolation_methods.py +14 -15
  79. imap_processing/mag/l1c/mag_l1c.py +23 -6
  80. imap_processing/mag/l1d/mag_l1d.py +57 -14
  81. imap_processing/mag/l1d/mag_l1d_data.py +202 -32
  82. imap_processing/mag/l2/mag_l2.py +2 -0
  83. imap_processing/mag/l2/mag_l2_data.py +14 -5
  84. imap_processing/quality_flags.py +23 -1
  85. imap_processing/spice/geometry.py +89 -39
  86. imap_processing/spice/pointing_frame.py +4 -8
  87. imap_processing/spice/repoint.py +78 -2
  88. imap_processing/spice/spin.py +28 -8
  89. imap_processing/spice/time.py +12 -22
  90. imap_processing/swapi/l1/swapi_l1.py +10 -4
  91. imap_processing/swapi/l2/swapi_l2.py +15 -17
  92. imap_processing/swe/l1b/swe_l1b.py +1 -2
  93. imap_processing/ultra/constants.py +30 -24
  94. imap_processing/ultra/l0/ultra_utils.py +9 -11
  95. imap_processing/ultra/l1a/ultra_l1a.py +1 -2
  96. imap_processing/ultra/l1b/badtimes.py +35 -11
  97. imap_processing/ultra/l1b/de.py +95 -31
  98. imap_processing/ultra/l1b/extendedspin.py +31 -16
  99. imap_processing/ultra/l1b/goodtimes.py +112 -0
  100. imap_processing/ultra/l1b/lookup_utils.py +281 -28
  101. imap_processing/ultra/l1b/quality_flag_filters.py +10 -1
  102. imap_processing/ultra/l1b/ultra_l1b.py +7 -7
  103. imap_processing/ultra/l1b/ultra_l1b_culling.py +169 -7
  104. imap_processing/ultra/l1b/ultra_l1b_extended.py +311 -69
  105. imap_processing/ultra/l1c/helio_pset.py +139 -37
  106. imap_processing/ultra/l1c/l1c_lookup_utils.py +289 -0
  107. imap_processing/ultra/l1c/spacecraft_pset.py +140 -29
  108. imap_processing/ultra/l1c/ultra_l1c.py +33 -24
  109. imap_processing/ultra/l1c/ultra_l1c_culling.py +92 -0
  110. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +400 -292
  111. imap_processing/ultra/l2/ultra_l2.py +54 -11
  112. imap_processing/ultra/utils/ultra_l1_utils.py +37 -7
  113. imap_processing/utils.py +3 -4
  114. {imap_processing-0.18.0.dist-info → imap_processing-0.19.2.dist-info}/METADATA +2 -2
  115. {imap_processing-0.18.0.dist-info → imap_processing-0.19.2.dist-info}/RECORD +118 -109
  116. imap_processing/idex/idex_l2c.py +0 -84
  117. imap_processing/spice/kernels.py +0 -187
  118. imap_processing/ultra/l1b/cullingmask.py +0 -87
  119. imap_processing/ultra/l1c/histogram.py +0 -36
  120. {imap_processing-0.18.0.dist-info → imap_processing-0.19.2.dist-info}/LICENSE +0 -0
  121. {imap_processing-0.18.0.dist-info → imap_processing-0.19.2.dist-info}/WHEEL +0 -0
  122. {imap_processing-0.18.0.dist-info → imap_processing-0.19.2.dist-info}/entry_points.txt +0 -0
@@ -10,6 +10,7 @@ import xarray as xr
10
10
  from numpy.typing import NDArray
11
11
 
12
12
  from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
13
+ from imap_processing.cdf.utils import load_cdf
13
14
  from imap_processing.ena_maps import ena_maps
14
15
  from imap_processing.ena_maps.utils.coordinates import CoordNames
15
16
  from imap_processing.ena_maps.utils.naming import (
@@ -17,10 +18,10 @@ from imap_processing.ena_maps.utils.naming import (
17
18
  MapDescriptor,
18
19
  ns_to_duration_months,
19
20
  )
21
+ from imap_processing.quality_flags import ImapPSETUltraFlags
20
22
  from imap_processing.ultra.l1c.ultra_l1c_pset_bins import get_energy_delta_minus_plus
21
23
 
22
24
  logger = logging.getLogger(__name__)
23
- logger.info("Importing ultra_l2 module")
24
25
 
25
26
  # Default properties for the Ultra L2 map
26
27
  DEFAULT_ULTRA_L2_MAP_STRUCTURE: ena_maps.RectangularSkyMap | ena_maps.HealpixSkyMap = (
@@ -59,7 +60,15 @@ REQUIRED_L1C_VARIABLES_PULL = [
59
60
  "background_rates",
60
61
  "obs_date",
61
62
  ]
62
-
63
+ # These variables are expected but not strictly required. In certain test scenarios,
64
+ # they may be missing, in which case we will raise a warning and continue.
65
+ # All psets must be consistent and either have these variables or not.
66
+ EXPECTED_L1C_VARIABLES_PULL = [
67
+ "geometric_function",
68
+ "efficiency",
69
+ "scatter_theta",
70
+ "scatter_phi",
71
+ ]
63
72
  # These variables are projected to the map as the mean of pointing set pixels value,
64
73
  # weighted by that pointing set pixel's exposure and solid angle
65
74
  VARIABLES_TO_WEIGHT_BY_POINTING_SET_EXPOSURE_TIMES_SOLID_ANGLE = [
@@ -72,12 +81,9 @@ VARIABLES_TO_WEIGHT_BY_POINTING_SET_EXPOSURE_TIMES_SOLID_ANGLE = [
72
81
  # calculate ena_intensity and its statistical uncertainty
73
82
  # They will not be present in the final map
74
83
  VARIABLES_TO_DROP_AFTER_INTENSITY_CALCULATION = [
75
- "counts",
76
- "background_rates",
77
84
  "pointing_set_exposure_times_solid_angle",
78
85
  "num_pointing_set_pixel_members",
79
86
  "corrected_count_rate",
80
- "obs_date_for_std",
81
87
  "obs_date_squared_for_std",
82
88
  ]
83
89
 
@@ -128,6 +134,8 @@ def get_variable_attributes_optional_energy_dependence(
128
134
  and (CoordNames.ENERGY_ULTRA_L1C.value not in variable_dims)
129
135
  ):
130
136
  variable_name = f"{variable_name}_energy_independent"
137
+ if variable_name == "counts":
138
+ variable_name = "ena_count"
131
139
 
132
140
  metadata = cdf_attrs.get_variable_attributes(
133
141
  variable_name=variable_name,
@@ -206,7 +214,7 @@ def generate_ultra_healpix_skymap(
206
214
  output_map_structure.values_to_push_project.extend(
207
215
  [
208
216
  "num_pointing_set_pixel_members",
209
- "obs_date_for_std",
217
+ "obs_date_range",
210
218
  "obs_date_squared_for_std",
211
219
  ]
212
220
  )
@@ -236,6 +244,27 @@ def generate_ultra_healpix_skymap(
236
244
  f"PUSH Variables: {output_map_structure.values_to_push_project} \n"
237
245
  f"PULL Variables: {output_map_structure.values_to_pull_project}"
238
246
  )
247
+ # TODO remove this in the future once all test data includes these variables
248
+ # Add expected but not required variables to the pull projection list
249
+ # Log a warning if they are missing from any PSET but continue processing.
250
+ expected_present_vars = []
251
+ first_pset = (
252
+ load_cdf(ultra_l1c_psets[0])
253
+ if isinstance(ultra_l1c_psets[0], (str, Path))
254
+ else ultra_l1c_psets[0]
255
+ )
256
+ for var in EXPECTED_L1C_VARIABLES_PULL:
257
+ if var not in first_pset.variables:
258
+ logger.warning(
259
+ f"Expected variable {var} not found in the first L1C PSET. "
260
+ "This variable will not be projected to the map."
261
+ )
262
+ else:
263
+ expected_present_vars.append(var)
264
+
265
+ output_map_structure.values_to_pull_project = list(
266
+ set(output_map_structure.values_to_pull_project + expected_present_vars)
267
+ )
239
268
 
240
269
  all_pset_epochs = []
241
270
  for ultra_l1c_pset in ultra_l1c_psets:
@@ -249,9 +278,15 @@ def generate_ultra_healpix_skymap(
249
278
  "\nThese values will be pull projected: "
250
279
  f">> {output_map_structure.values_to_pull_project}",
251
280
  )
281
+ flags_1d = pointing_set.data["quality_flags"].isel(epoch=0)
282
+ # This is a good pixel mask where zero is when the earth is not in the FOV.
283
+ good_pixel_mask = (
284
+ (flags_1d & ImapPSETUltraFlags.EARTH_FOV.value) == 0
285
+ ).to_numpy()
252
286
 
287
+ # Only count the number of pointing set pixels which are not flagged.
253
288
  pointing_set.data["num_pointing_set_pixel_members"] = xr.DataArray(
254
- np.ones(pointing_set.num_points, dtype=int),
289
+ good_pixel_mask.astype(int),
255
290
  dims=(CoordNames.HEALPIX_INDEX.value),
256
291
  )
257
292
 
@@ -262,11 +297,11 @@ def generate_ultra_healpix_skymap(
262
297
  fill_value=pointing_set.epoch,
263
298
  dtype=np.int64,
264
299
  )
265
- pointing_set.data["obs_date_for_std"] = pointing_set.data["obs_date"].astype(
300
+ pointing_set.data["obs_date_range"] = pointing_set.data["obs_date"].astype(
266
301
  np.float64
267
302
  )
268
303
  pointing_set.data["obs_date_squared_for_std"] = (
269
- pointing_set.data["obs_date_for_std"] ** 2
304
+ pointing_set.data["obs_date_range"] ** 2
270
305
  )
271
306
 
272
307
  # Add solid_angle * exposure of pointing set as data_var
@@ -277,15 +312,22 @@ def generate_ultra_healpix_skymap(
277
312
 
278
313
  # Initial processing for weighted quantities at PSET level
279
314
  # Weight the values by exposure and solid angle
315
+ # Ensure only valid pointing set pixels contribute to the weighted mean.
280
316
  pointing_set.data[
281
317
  VARIABLES_TO_WEIGHT_BY_POINTING_SET_EXPOSURE_TIMES_SOLID_ANGLE
282
- ] *= pointing_set.data["pointing_set_exposure_times_solid_angle"]
318
+ ] = (
319
+ pointing_set.data[
320
+ VARIABLES_TO_WEIGHT_BY_POINTING_SET_EXPOSURE_TIMES_SOLID_ANGLE
321
+ ]
322
+ * pointing_set.data["pointing_set_exposure_times_solid_angle"]
323
+ ).where(good_pixel_mask)
283
324
 
284
325
  # Project values such as counts via the PUSH method
285
326
  skymap.project_pset_values_to_map(
286
327
  pointing_set=pointing_set,
287
328
  value_keys=output_map_structure.values_to_push_project,
288
329
  index_match_method=ena_maps.IndexMatchMethod.PUSH,
330
+ pset_valid_mask=good_pixel_mask,
289
331
  )
290
332
 
291
333
  # Project values such as exposure_factor via the PULL method
@@ -293,6 +335,7 @@ def generate_ultra_healpix_skymap(
293
335
  pointing_set=pointing_set,
294
336
  value_keys=output_map_structure.values_to_pull_project,
295
337
  index_match_method=ena_maps.IndexMatchMethod.PULL,
338
+ pset_valid_mask=good_pixel_mask,
296
339
  )
297
340
 
298
341
  # Subsequent processing for weighted quantities at SkyMap level
@@ -348,7 +391,7 @@ def generate_ultra_healpix_skymap(
348
391
  )
349
392
  - (
350
393
  (
351
- skymap.data_1d["obs_date_for_std"]
394
+ skymap.data_1d["obs_date_range"]
352
395
  / (skymap.data_1d["num_pointing_set_pixel_members"])
353
396
  )
354
397
  ** 2
@@ -1,6 +1,5 @@
1
1
  """Create dataset."""
2
2
 
3
- import numpy as np
4
3
  import xarray as xr
5
4
 
6
5
  from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
@@ -32,7 +31,7 @@ def create_dataset( # noqa: PLR0912
32
31
  cdf_manager.add_instrument_global_attrs("ultra")
33
32
  cdf_manager.add_instrument_variable_attrs("ultra", level)
34
33
 
35
- # L1b extended spin, badtimes, and cullingmask data products
34
+ # L1b extended spin, badtimes, and goodtimes data products
36
35
  if "spin_number" in data_dict.keys():
37
36
  coords = {
38
37
  "spin_number": ("spin_number", data_dict["spin_number"]),
@@ -40,7 +39,6 @@ def create_dataset( # noqa: PLR0912
40
39
  "energy_bin_geometric_mean",
41
40
  data_dict["energy_bin_geometric_mean"],
42
41
  ),
43
- "epoch": ("spin_number", np.asarray(data_dict["epoch"])),
44
42
  }
45
43
  default_dimension = "spin_number"
46
44
  # L1c pset data products
@@ -49,6 +47,7 @@ def create_dataset( # noqa: PLR0912
49
47
  "epoch": data_dict["epoch"],
50
48
  "pixel_index": data_dict["pixel_index"],
51
49
  "energy_bin_geometric_mean": data_dict["energy_bin_geometric_mean"],
50
+ "spin_phase_step": data_dict["spin_phase_step"],
52
51
  }
53
52
  default_dimension = "pixel_index"
54
53
  # L1b de data product
@@ -95,7 +94,13 @@ def create_dataset( # noqa: PLR0912
95
94
 
96
95
  for key, data in data_dict.items():
97
96
  # Skip keys that are coordinates.
98
- if key in ["epoch", "spin_number", "energy_bin_geometric_mean", "pixel_index"]:
97
+ if key in [
98
+ "epoch",
99
+ "spin_number",
100
+ "energy_bin_geometric_mean",
101
+ "pixel_index",
102
+ "spin_phase_step",
103
+ ]:
99
104
  continue
100
105
  elif key in velocity_keys:
101
106
  dataset[key] = xr.DataArray(
@@ -103,7 +108,12 @@ def create_dataset( # noqa: PLR0912
103
108
  dims=["epoch", "component"],
104
109
  attrs=cdf_manager.get_variable_attributes(key, check_schema=False),
105
110
  )
106
- elif key == "ena_rates_threshold":
111
+ elif key in [
112
+ "ena_rates_threshold",
113
+ "scatter_threshold",
114
+ "energy_delta_minus",
115
+ "energy_delta_plus",
116
+ ]:
107
117
  dataset[key] = xr.DataArray(
108
118
  data,
109
119
  dims=["energy_bin_geometric_mean"],
@@ -127,7 +137,7 @@ def create_dataset( # noqa: PLR0912
127
137
  dims=["energy_bin_geometric_mean", "spin_number"],
128
138
  attrs=cdf_manager.get_variable_attributes(key, check_schema=False),
129
139
  )
130
- elif key in {"latitude", "longitude", "exposure_factor"}:
140
+ elif key in {"quality_flags", "latitude", "longitude"}:
131
141
  dataset[key] = xr.DataArray(
132
142
  data,
133
143
  dims=["epoch", "pixel_index"],
@@ -136,12 +146,32 @@ def create_dataset( # noqa: PLR0912
136
146
  elif key in {
137
147
  "counts",
138
148
  "background_rates",
149
+ }:
150
+ dataset[key] = xr.DataArray(
151
+ data,
152
+ dims=["epoch", "energy_bin_geometric_mean", "pixel_index"],
153
+ attrs=cdf_manager.get_variable_attributes(key, check_schema=False),
154
+ )
155
+ elif key in {
156
+ "exposure_factor",
139
157
  "helio_exposure_factor",
140
158
  "sensitivity",
159
+ "efficiency",
160
+ "geometric_function",
161
+ "scatter_theta",
162
+ "scatter_phi",
141
163
  }:
142
164
  dataset[key] = xr.DataArray(
143
165
  data,
144
- dims=["epoch", "energy_bin_geometric_mean", "pixel_index"],
166
+ dims=["energy_bin_geometric_mean", "pixel_index"],
167
+ attrs=cdf_manager.get_variable_attributes(key, check_schema=False),
168
+ )
169
+ elif key in {
170
+ "dead_time_ratio",
171
+ }:
172
+ dataset[key] = xr.DataArray(
173
+ data,
174
+ dims=["spin_phase_step"],
145
175
  attrs=cdf_manager.get_variable_attributes(key, check_schema=False),
146
176
  )
147
177
  else:
imap_processing/utils.py CHANGED
@@ -3,7 +3,6 @@
3
3
  import collections
4
4
  import logging
5
5
  from pathlib import Path
6
- from typing import Optional, Union
7
6
 
8
7
  import numpy as np
9
8
  import pandas as pd
@@ -141,7 +140,7 @@ def _get_minimum_numpy_datatype( # noqa: PLR0912 - Too many branches
141
140
  name: str,
142
141
  definition: definitions.XtcePacketDefinition,
143
142
  use_derived_value: bool = True,
144
- ) -> Optional[str]:
143
+ ) -> str | None:
145
144
  """
146
145
  Get the minimum datatype for a given variable.
147
146
 
@@ -209,8 +208,8 @@ def _get_minimum_numpy_datatype( # noqa: PLR0912 - Too many branches
209
208
 
210
209
 
211
210
  def packet_file_to_datasets(
212
- packet_file: Union[str, Path],
213
- xtce_packet_definition: Union[str, Path],
211
+ packet_file: str | Path,
212
+ xtce_packet_definition: str | Path,
214
213
  use_derived_value: bool = False,
215
214
  ) -> dict[int, xr.Dataset]:
216
215
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: imap-processing
3
- Version: 0.18.0
3
+ Version: 0.19.2
4
4
  Summary: IMAP Science Operations Center Processing
5
5
  License: MIT
6
6
  Keywords: IMAP,SDC,SOC,Science Operations
@@ -28,7 +28,7 @@ Provides-Extra: map-visualization
28
28
  Provides-Extra: test
29
29
  Provides-Extra: tools
30
30
  Requires-Dist: astropy-healpix (>=1.0)
31
- Requires-Dist: cdflib (>=1.3.1,<2.0.0)
31
+ Requires-Dist: cdflib (>=1.3.6,<2.0.0)
32
32
  Requires-Dist: healpy (>=1.18.0,<2.0.0) ; extra == "map-visualization"
33
33
  Requires-Dist: imap-data-access (>=0.32.0)
34
34
  Requires-Dist: mypy (==1.10.1) ; extra == "dev"