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
@@ -20,231 +20,65 @@ Examples
20
20
 
21
21
  import logging
22
22
 
23
- import astropy_healpix.healpy as hp
24
- import numpy as np
25
23
  import xarray as xr
26
24
 
27
- from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
28
25
  from imap_processing.ena_maps.ena_maps import SkyTilingType
29
- from imap_processing.ena_maps.utils.coordinates import CoordNames
30
- from imap_processing.ena_maps.utils.spatial_utils import AzElSkyGrid
31
26
  from imap_processing.idex.idex_constants import (
32
27
  IDEX_EVENT_REFERENCE_FRAME,
33
- IDEX_HEALPIX_NESTED,
34
- IDEX_HEALPIX_NSIDE,
35
28
  IDEX_SPACING_DEG,
36
29
  )
37
- from imap_processing.idex.idex_utils import get_idex_attrs
30
+ from imap_processing.idex.idex_utils import get_idex_attrs, setup_dataset
38
31
 
39
32
  logger = logging.getLogger(__name__)
40
33
 
41
34
 
42
- def idex_l2c(l2b_dataset: xr.Dataset) -> list[xr.Dataset]:
35
+ def idex_l2c(l2b_datasets: list[xr.Dataset]) -> xr.Dataset:
43
36
  """
44
37
  Will process IDEX l2b data to create l2c data products.
45
38
 
46
39
  Parameters
47
40
  ----------
48
- l2b_dataset : xarray.Dataset
49
- IDEX L2b dataset.
41
+ l2b_datasets : list[xarray.Dataset]
42
+ IDEX L2b datasets.
50
43
 
51
44
  Returns
52
45
  -------
53
- l2b_dataset : list[xarray.Dataset]
46
+ l2b_dataset : xarray.Dataset
54
47
  The``xarray`` dataset containing the science data and supporting metadata.
55
48
  """
56
- logger.info(
57
- f"Running IDEX L2C processing on datasets: "
58
- f"{l2b_dataset.attrs['Logical_source']}"
59
- )
49
+ logger.info("Running IDEX L2C processing")
60
50
  # create the attribute manager for this data level
61
51
  idex_attrs = get_idex_attrs("l2c")
62
- # Epoch should be the start of the collection period.
63
- # TODO should epoch be start of sci acquisition?
64
- epoch = xr.DataArray(
65
- l2b_dataset["epoch"].data[0:1].astype(np.int64),
66
- name="epoch",
67
- dims=["epoch"],
68
- attrs=idex_attrs.get_variable_attributes(
69
- "epoch_collection_set", check_schema=False
70
- ),
71
- )
72
- l2c_healpix_dataset = idex_healpix_map(l2b_dataset, epoch, idex_attrs)
73
- l2c_rectangular_dataset = idex_rectangular_map(l2b_dataset, epoch, idex_attrs)
74
-
75
- # TODO exposure time
76
- logger.info("IDEX L2C science data processing completed.")
77
- return [l2c_healpix_dataset, l2c_rectangular_dataset]
78
-
79
-
80
- def idex_healpix_map(
81
- l1b_dataset: xr.Dataset,
82
- epoch_da: xr.DataArray,
83
- idex_attrs: ImapCdfAttributes,
84
- nside: int = IDEX_HEALPIX_NSIDE,
85
- nested: bool = IDEX_HEALPIX_NESTED,
86
- ) -> xr.Dataset:
87
- """
88
- Create a healpix map out of a l1b dataset.
89
-
90
- Parameters
91
- ----------
92
- l1b_dataset : xarray.Dataset
93
- IDEX L2b dataset.
94
- epoch_da : xarray.DataArray
95
- Epoch data array of the collection. Size: (1,).
96
- idex_attrs : ImapCdfAttributes
97
- The attribute manager for this data level.
98
- nside : int
99
- Healpix nside parameter.
100
- nested : bool
101
- Healpix nested parameter.
102
-
103
- Returns
104
- -------
105
- map : xarray.Dataset
106
- Spatially binned dust counts in a healpix map format.
107
- """
108
- longitude = l1b_dataset["longitude"]
109
- latitude = l1b_dataset["latitude"]
110
-
111
- # Get the healpix indices
112
- hpix_idx = hp.ang2pix(
113
- nside, nest=nested, lonlat=True, theta=longitude, phi=latitude
114
- )
115
-
116
- n_pix = hp.nside2npix(nside)
117
- healpix = xr.DataArray(
118
- np.arange(n_pix),
119
- name=CoordNames.HEALPIX_INDEX.value,
120
- dims=CoordNames.HEALPIX_INDEX.value,
121
- attrs=idex_attrs.get_variable_attributes("pixel_index", check_schema=False),
122
- )
123
-
124
- # Create a histogram of the raw dust event counts for each pixel
125
- counts = np.histogram(hpix_idx, bins=n_pix, range=(0, n_pix))[0]
126
- # Add epoch dimension
127
- counts_da = xr.DataArray(
128
- counts[np.newaxis, :].astype(np.int64),
129
- name="counts",
130
- dims=("epoch", CoordNames.HEALPIX_INDEX.value),
131
- attrs=idex_attrs.get_variable_attributes("healpix_counts"),
132
- )
133
- pixel_label = xr.DataArray(
134
- healpix.astype(str),
135
- name="pixel_label",
136
- dims="pixel_index",
137
- attrs=idex_attrs.get_variable_attributes("pixel_label", check_schema=False),
138
- )
139
- l2c_dataset = xr.Dataset(
140
- coords={CoordNames.HEALPIX_INDEX.value: healpix, "epoch": epoch_da},
141
- data_vars={
142
- "counts": counts_da,
143
- "longitude": longitude,
144
- "latitude": latitude,
145
- "pixel_label": pixel_label,
146
- },
52
+ # Concat the list of l2b datasets into a single dataset
53
+ # Only concat the variables that have "epoch" as a dimension
54
+ l2b_dataset = xr.concat(
55
+ l2b_datasets, "epoch", data_vars="minimal", coords="minimal"
147
56
  )
148
- map_attrs = {
149
- "Sky_tiling_type": SkyTilingType.HEALPIX.value,
150
- "HEALPix_nside": str(nside),
151
- "HEALPix_nest": str(nested),
152
- "Spice_reference_frame": IDEX_EVENT_REFERENCE_FRAME.name,
153
- "num_points": str(n_pix),
154
- } | idex_attrs.get_global_attributes("imap_idex_l2c_sci-healpix")
155
- l2c_dataset.attrs.update(map_attrs)
156
-
157
- return l2c_dataset
158
-
159
57
 
160
- def idex_rectangular_map(
161
- l1b_dataset: xr.Dataset,
162
- epoch_da: xr.DataArray,
163
- idex_attrs: ImapCdfAttributes,
164
- spacing_deg: int = IDEX_SPACING_DEG,
165
- ) -> xr.Dataset:
166
- """
167
- Create a rectangular map out of a l1b dataset.
168
-
169
- Parameters
170
- ----------
171
- l1b_dataset : xarray.Dataset
172
- IDEX L2b dataset.
173
- epoch_da : xarray.DataArray
174
- Epoch data array of the collection. Size: (1,).
175
- idex_attrs : ImapCdfAttributes
176
- The attribute manager for this data level.
177
- spacing_deg : int
178
- The spacing in degrees for the rectangular grid.
179
-
180
- Returns
181
- -------
182
- map : xarray.Dataset
183
- Spatially binned dust counts in a rectangular map format.
184
- """
185
- # Get the rectangular grid with the specified spacing
186
- grid = AzElSkyGrid(spacing_deg)
187
- # Make sure longitude values are in the range [0, 360)
188
- longitude_wrapped = np.mod(l1b_dataset["longitude"], 360)
189
- latitude = l1b_dataset["latitude"]
190
- # Create a 2d histogram of the raw dust event counts for each pixel using the grid
191
- # bin edges
192
- counts, _, _ = np.histogram2d(
193
- longitude_wrapped, latitude, bins=[grid.az_bin_edges, grid.el_bin_edges]
194
- )
195
- counts_da = xr.DataArray(
196
- counts[np.newaxis, :, :].astype(np.int64),
197
- name="counts",
198
- dims=("epoch", "rectangular_lon_pixel", "rectangular_lat_pixel"),
199
- attrs=idex_attrs.get_variable_attributes("rectangular_counts"),
200
- )
201
- rec_lon_pixels = xr.DataArray(
202
- name="rectangular_lon_pixel",
203
- data=grid.az_bin_midpoints,
204
- dims="rectangular_lon_pixel",
205
- attrs=idex_attrs.get_variable_attributes(
206
- "rectangular_lon_pixel", check_schema=False
207
- ),
208
- )
209
- rec_lat_pixels = xr.DataArray(
210
- name="rectangular_lat_pixel",
211
- data=grid.el_bin_midpoints,
212
- dims="rectangular_lat_pixel",
213
- attrs=idex_attrs.get_variable_attributes(
214
- "rectangular_lat_pixel", check_schema=False
215
- ),
216
- )
217
-
218
- l2c_dataset = xr.Dataset(
219
- coords={
220
- "epoch": epoch_da,
221
- "rectangular_lon_pixel": rec_lon_pixels,
222
- "rectangular_lat_pixel": rec_lat_pixels,
223
- },
224
- data_vars={
225
- "counts": counts_da,
226
- "longitude": longitude_wrapped,
227
- "latitude": latitude,
228
- "rectangular_lon_pixel_label": rec_lon_pixels.astype(str),
229
- "rectangular_lat_pixel_label": rec_lat_pixels.astype(str),
230
- },
231
- )
232
- l2c_dataset[
233
- "rectangular_lon_pixel_label"
234
- ].attrs = idex_attrs.get_variable_attributes(
235
- "rectangular_lon_pixel_label", check_schema=False
236
- )
237
- l2c_dataset[
238
- "rectangular_lat_pixel_label"
239
- ].attrs = idex_attrs.get_variable_attributes(
240
- "rectangular_lat_pixel_label", check_schema=False
241
- )
58
+ arrays_to_copy = [
59
+ "counts_by_charge_map",
60
+ "counts_by_mass_map",
61
+ "rate_by_charge_map",
62
+ "rate_by_mass_map",
63
+ "epoch",
64
+ "impact_day_of_year",
65
+ "impact_charge_bins",
66
+ "mass_bins",
67
+ "charge_labels",
68
+ "mass_labels",
69
+ "rectangular_lon_pixel_label",
70
+ "rectangular_lat_pixel_label",
71
+ ]
72
+
73
+ l2c_dataset = setup_dataset(l2b_dataset, arrays_to_copy, idex_attrs)
74
+
75
+ # Add map attributes
242
76
  map_attrs = {
243
77
  "sky_tiling_type": SkyTilingType.RECTANGULAR.value,
244
- "Spacing_degrees": str(spacing_deg),
78
+ "Spacing_degrees": str(IDEX_SPACING_DEG),
245
79
  "Spice_reference_frame": IDEX_EVENT_REFERENCE_FRAME.name,
246
- "num_points": str(counts.size),
247
80
  } | idex_attrs.get_global_attributes("imap_idex_l2c_sci-rectangular")
248
81
 
249
82
  l2c_dataset.attrs.update(map_attrs)
83
+ logger.info("IDEX L2C science data processing completed.")
250
84
  return l2c_dataset
@@ -13,3 +13,4 @@ class LoAPID(IntEnum):
13
13
  ILO_SCI_DE = 706 # Science direct event data
14
14
  ILO_STAR = 707 # Science star sensor data, every spin
15
15
  ILO_SPIN = 708 # Spin information for each science cycle (28 spins)
16
+ ILO_DIAG_PCC = 725 # Diagnostic pivot platform information
@@ -45,6 +45,11 @@ def lo_l1a(dependency: Path) -> list[xr.Dataset]:
45
45
  xtce_packet_definition=xtce_file.resolve(),
46
46
  use_derived_value=False,
47
47
  )
48
+ datasets_by_apid_derived = packet_file_to_datasets(
49
+ packet_file=dependency.resolve(),
50
+ xtce_packet_definition=xtce_file.resolve(),
51
+ use_derived_value=True,
52
+ )
48
53
 
49
54
  # create the attribute manager for this data level
50
55
  attr_mgr = ImapCdfAttributes()
@@ -101,6 +106,45 @@ def lo_l1a(dependency: Path) -> list[xr.Dataset]:
101
106
  ds = process_star_sensor(ds)
102
107
  ds = add_dataset_attrs(ds, attr_mgr, logical_source)
103
108
  datasets_to_return.append(ds)
109
+ if LoAPID.ILO_DIAG_PCC in datasets_by_apid:
110
+ logger.info(
111
+ f"\nProcessing {LoAPID(LoAPID.ILO_DIAG_PCC).name} "
112
+ f"packet (APID: {LoAPID.ILO_DIAG_PCC.value})"
113
+ )
114
+ logical_source = "imap_lo_l1a_pcc"
115
+ ds = datasets_by_apid[LoAPID.ILO_DIAG_PCC]
116
+ ds = add_dataset_attrs(ds, attr_mgr, logical_source)
117
+ datasets_to_return.append(ds)
118
+ if LoAPID.ILO_APP_NHK in datasets_by_apid:
119
+ logger.info(
120
+ f"\nProcessing {LoAPID(LoAPID.ILO_APP_NHK).name} "
121
+ f"packet (APID: {LoAPID.ILO_APP_NHK.value})"
122
+ )
123
+ logical_source = "imap_lo_l1a_nhk"
124
+ ds = datasets_by_apid[LoAPID.ILO_APP_NHK]
125
+ ds = add_dataset_attrs(ds, attr_mgr, logical_source)
126
+ datasets_to_return.append(ds)
127
+
128
+ # Engineering units conversion
129
+ logical_source = "imap_lo_l1b_nhk"
130
+ ds = datasets_by_apid_derived[LoAPID.ILO_APP_NHK]
131
+ ds = add_dataset_attrs(ds, attr_mgr, logical_source)
132
+ datasets_to_return.append(ds)
133
+ if LoAPID.ILO_APP_SHK in datasets_by_apid:
134
+ logger.info(
135
+ f"\nProcessing {LoAPID(LoAPID.ILO_APP_SHK).name} "
136
+ f"packet (APID: {LoAPID.ILO_APP_SHK.value})"
137
+ )
138
+ logical_source = "imap_lo_l1a_shk"
139
+ ds = datasets_by_apid[LoAPID.ILO_APP_SHK]
140
+ ds = add_dataset_attrs(ds, attr_mgr, logical_source)
141
+ datasets_to_return.append(ds)
142
+
143
+ # Engineering units conversion
144
+ logical_source = "imap_lo_l1b_shk"
145
+ ds = datasets_by_apid_derived[LoAPID.ILO_APP_SHK]
146
+ ds = add_dataset_attrs(ds, attr_mgr, logical_source)
147
+ datasets_to_return.append(ds)
104
148
 
105
149
  logger.info(f"Returning [{len(datasets_to_return)}] datasets")
106
150
  return datasets_to_return