imap-processing 0.8.0__py3-none-any.whl → 0.9.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 (99) hide show
  1. imap_processing/_version.py +2 -2
  2. imap_processing/ccsds/excel_to_xtce.py +2 -0
  3. imap_processing/cdf/config/imap_hi_variable_attrs.yaml +100 -1
  4. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +14 -0
  5. imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +63 -1
  6. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +7 -0
  7. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +574 -231
  8. imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +326 -0
  9. imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +33 -23
  10. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +7 -4
  11. imap_processing/cdf/utils.py +3 -5
  12. imap_processing/cli.py +13 -4
  13. imap_processing/codice/codice_l1a.py +5 -5
  14. imap_processing/codice/constants.py +9 -9
  15. imap_processing/codice/decompress.py +6 -2
  16. imap_processing/glows/l1a/glows_l1a.py +1 -2
  17. imap_processing/hi/l1a/hi_l1a.py +4 -4
  18. imap_processing/hi/l1a/histogram.py +106 -108
  19. imap_processing/hi/l1a/science_direct_event.py +91 -224
  20. imap_processing/hi/packet_definitions/TLM_HI_COMBINED_SCI.xml +3994 -0
  21. imap_processing/hit/l0/constants.py +2 -2
  22. imap_processing/hit/l0/decom_hit.py +12 -101
  23. imap_processing/hit/l1a/hit_l1a.py +164 -23
  24. imap_processing/ialirt/l0/process_codicelo.py +153 -0
  25. imap_processing/ialirt/l0/process_hit.py +5 -5
  26. imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +281 -0
  27. imap_processing/ialirt/process_ephemeris.py +212 -0
  28. imap_processing/idex/idex_l1a.py +55 -75
  29. imap_processing/idex/idex_l1b.py +192 -0
  30. imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +33 -0
  31. imap_processing/idex/packet_definitions/idex_packet_definition.xml +97 -595
  32. imap_processing/lo/l0/decompression_tables/decompression_tables.py +16 -0
  33. imap_processing/lo/l0/lo_science.py +44 -12
  34. imap_processing/lo/l1a/lo_l1a.py +76 -8
  35. imap_processing/lo/packet_definitions/lo_xtce.xml +9877 -87
  36. imap_processing/mag/l1a/mag_l1a.py +1 -2
  37. imap_processing/mag/l1a/mag_l1a_data.py +1 -2
  38. imap_processing/mag/l1b/mag_l1b.py +2 -1
  39. imap_processing/spice/geometry.py +37 -19
  40. imap_processing/spice/time.py +144 -2
  41. imap_processing/swapi/l1/swapi_l1.py +3 -3
  42. imap_processing/swapi/packet_definitions/swapi_packet_definition.xml +1535 -446
  43. imap_processing/swe/l2/swe_l2.py +134 -17
  44. imap_processing/tests/ccsds/test_data/expected_output.xml +1 -1
  45. imap_processing/tests/codice/test_codice_l1a.py +8 -8
  46. imap_processing/tests/codice/test_decompress.py +4 -4
  47. imap_processing/tests/conftest.py +46 -43
  48. imap_processing/tests/hi/test_data/l0/H90_NHK_20241104.bin +0 -0
  49. imap_processing/tests/hi/test_data/l0/H90_sci_cnt_20241104.bin +0 -0
  50. imap_processing/tests/hi/test_data/l0/H90_sci_de_20241104.bin +0 -0
  51. imap_processing/tests/hi/test_hi_l1b.py +2 -2
  52. imap_processing/tests/hi/test_l1a.py +31 -58
  53. imap_processing/tests/hi/test_science_direct_event.py +58 -0
  54. imap_processing/tests/hit/test_data/sci_sample1.ccsds +0 -0
  55. imap_processing/tests/hit/test_decom_hit.py +60 -50
  56. imap_processing/tests/hit/test_hit_l1a.py +327 -12
  57. imap_processing/tests/hit/test_hit_l1b.py +76 -0
  58. imap_processing/tests/hit/validation_data/hskp_sample_eu.csv +89 -0
  59. imap_processing/tests/hit/validation_data/sci_sample_raw1.csv +29 -0
  60. imap_processing/tests/ialirt/test_data/l0/apid01152.tlm +0 -0
  61. imap_processing/tests/ialirt/test_data/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  62. imap_processing/tests/ialirt/unit/test_process_codicelo.py +106 -0
  63. imap_processing/tests/ialirt/unit/test_process_ephemeris.py +109 -0
  64. imap_processing/tests/ialirt/unit/test_process_hit.py +9 -6
  65. imap_processing/tests/idex/conftest.py +1 -1
  66. imap_processing/tests/idex/test_idex_l0.py +1 -1
  67. imap_processing/tests/idex/test_idex_l1a.py +7 -1
  68. imap_processing/tests/idex/test_idex_l1b.py +126 -0
  69. imap_processing/tests/lo/test_lo_l1a.py +7 -16
  70. imap_processing/tests/lo/test_lo_science.py +67 -3
  71. imap_processing/tests/lo/test_pkts/imap_lo_l0_raw_20240803_v002.pkts +0 -0
  72. imap_processing/tests/lo/validation_data/Instrument_FM1_T104_R129_20240803_ILO_SCI_DE_dec_DN_with_fills.csv +1999 -0
  73. imap_processing/tests/mag/test_mag_l1b.py +39 -5
  74. imap_processing/tests/spice/test_geometry.py +32 -6
  75. imap_processing/tests/spice/test_time.py +135 -6
  76. imap_processing/tests/swapi/test_swapi_decom.py +75 -69
  77. imap_processing/tests/swapi/test_swapi_l1.py +4 -4
  78. imap_processing/tests/swe/test_swe_l2.py +64 -8
  79. imap_processing/tests/test_utils.py +1 -1
  80. imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3314 -3314
  81. imap_processing/tests/ultra/unit/test_de.py +8 -3
  82. imap_processing/tests/ultra/unit/test_spatial_utils.py +125 -0
  83. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +39 -29
  84. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +2 -25
  85. imap_processing/ultra/constants.py +4 -0
  86. imap_processing/ultra/l1b/de.py +8 -14
  87. imap_processing/ultra/l1b/ultra_l1b_extended.py +29 -70
  88. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +1 -36
  89. imap_processing/ultra/utils/spatial_utils.py +221 -0
  90. {imap_processing-0.8.0.dist-info → imap_processing-0.9.0.dist-info}/METADATA +1 -1
  91. {imap_processing-0.8.0.dist-info → imap_processing-0.9.0.dist-info}/RECORD +94 -76
  92. imap_processing/hi/l0/__init__.py +0 -0
  93. imap_processing/hi/l0/decom_hi.py +0 -24
  94. imap_processing/hi/packet_definitions/hi_packet_definition.xml +0 -482
  95. imap_processing/tests/hi/test_decom.py +0 -55
  96. imap_processing/tests/hi/test_l1a_sci_de.py +0 -72
  97. {imap_processing-0.8.0.dist-info → imap_processing-0.9.0.dist-info}/LICENSE +0 -0
  98. {imap_processing-0.8.0.dist-info → imap_processing-0.9.0.dist-info}/WHEEL +0 -0
  99. {imap_processing-0.8.0.dist-info → imap_processing-0.9.0.dist-info}/entry_points.txt +0 -0
@@ -8,7 +8,6 @@ import numpy as np
8
8
  import xarray as xr
9
9
 
10
10
  from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
11
- from imap_processing.cdf.utils import J2000_EPOCH
12
11
  from imap_processing.mag.constants import DataMode, PrimarySensor
13
12
  from imap_processing.mag.l0 import decom_mag
14
13
  from imap_processing.mag.l0.mag_l0_data import MagL0
@@ -17,7 +16,7 @@ from imap_processing.mag.l1a.mag_l1a_data import (
17
16
  MagL1aPacketProperties,
18
17
  TimeTuple,
19
18
  )
20
- from imap_processing.spice.time import met_to_j2000ns
19
+ from imap_processing.spice.time import J2000_EPOCH, met_to_j2000ns
21
20
 
22
21
  logger = logging.getLogger(__name__)
23
22
 
@@ -9,7 +9,6 @@ from math import floor
9
9
  import numpy as np
10
10
  import numpy.typing as npt
11
11
 
12
- from imap_processing.cdf.utils import J2000_EPOCH
13
12
  from imap_processing.mag.constants import (
14
13
  AXIS_COUNT,
15
14
  FIBONACCI_SEQUENCE,
@@ -17,7 +16,7 @@ from imap_processing.mag.constants import (
17
16
  MAX_FINE_TIME,
18
17
  RANGE_BIT_WIDTH,
19
18
  )
20
- from imap_processing.spice.time import met_to_j2000ns
19
+ from imap_processing.spice.time import J2000_EPOCH, met_to_j2000ns
21
20
 
22
21
 
23
22
  @dataclass
@@ -202,6 +202,7 @@ def calibrate_vector(
202
202
  updated_vector = input_vector.copy()
203
203
 
204
204
  updated_vector[:3] = np.matmul(
205
- input_vector[:3], calibration_matrix.values[:, :, int(input_vector[3])]
205
+ calibration_matrix.values[:, :, int(input_vector[3])], input_vector[:3]
206
206
  )
207
+
207
208
  return updated_vector
@@ -64,8 +64,6 @@ class SpiceFrame(IntEnum):
64
64
  IMAP_GLOWS = -43750
65
65
 
66
66
 
67
- # TODO: Update boresight for in-situ instruments
68
- # TODO: Confirm ENA boresight vectors
69
67
  BORESIGHT_LOOKUP = {
70
68
  SpiceFrame.IMAP_LO: np.array([0, -1, 0]),
71
69
  SpiceFrame.IMAP_HI_45: np.array([0, 1, 0]),
@@ -73,12 +71,12 @@ BORESIGHT_LOOKUP = {
73
71
  SpiceFrame.IMAP_ULTRA_45: np.array([0, 0, 1]),
74
72
  SpiceFrame.IMAP_ULTRA_90: np.array([0, 0, 1]),
75
73
  SpiceFrame.IMAP_MAG: np.array([0, 0, 1]),
76
- SpiceFrame.IMAP_SWE: np.array([0, 0, 1]),
77
- SpiceFrame.IMAP_SWAPI: np.array([0, 0, 1]),
74
+ SpiceFrame.IMAP_SWE: np.array([-1, 0, 0]),
75
+ SpiceFrame.IMAP_SWAPI: np.array([0, 1, 0]),
78
76
  SpiceFrame.IMAP_CODICE: np.array([0, 0, 1]),
79
- SpiceFrame.IMAP_HIT: np.array([0, 0, 1]),
80
- SpiceFrame.IMAP_IDEX: np.array([0, 0, 1]),
81
- SpiceFrame.IMAP_GLOWS: np.array([0, 0, 1]),
77
+ SpiceFrame.IMAP_HIT: np.array([0, 1, 0]),
78
+ SpiceFrame.IMAP_IDEX: np.array([0, 1, 0]),
79
+ SpiceFrame.IMAP_GLOWS: np.array([0, 0, -1]),
82
80
  }
83
81
 
84
82
 
@@ -326,8 +324,11 @@ def frame_transform(
326
324
  Ephemeris time(s) corresponding to position(s).
327
325
  position : np.ndarray
328
326
  <x, y, z> vector or array of vectors in reference frame `from_frame`.
329
- A single position vector may be provided for multiple `et` query times
330
- but only a single position vector can be provided for a single `et`.
327
+ There are several possible shapes for the input position and et:
328
+ 1. A single position vector may be provided for multiple `et` query times
329
+ 2. A single `et` may be provided for multiple position vectors,
330
+ 3. The same number of `et` and position vectors may be provided.
331
+ But it is not allowed to have n position vectors and m `et`, where n != m.
331
332
  from_frame : SpiceFrame
332
333
  Reference frame of input vector(s).
333
334
  to_frame : SpiceFrame
@@ -350,11 +351,13 @@ def frame_transform(
350
351
  f"Each input position vector must have 3 elements."
351
352
  )
352
353
  if not len(position) == np.asarray(et).size:
353
- raise ValueError(
354
- "Mismatch in number of position vectors and Ephemeris times provided."
355
- f"Position has {len(position)} elements and et has "
356
- f"{np.asarray(et).size} elements."
357
- )
354
+ if np.asarray(et).size != 1:
355
+ raise ValueError(
356
+ "Mismatch in number of position vectors and "
357
+ "Ephemeris times provided."
358
+ f"Position has {len(position)} elements and et has "
359
+ f"{np.asarray(et).size} elements."
360
+ )
358
361
 
359
362
  # rotate will have shape = (3, 3) or (n, 3, 3)
360
363
  # position will have shape = (3,) or (n, 3)
@@ -494,6 +497,7 @@ def basis_vectors(
494
497
 
495
498
  def cartesian_to_spherical(
496
499
  v: NDArray,
500
+ degrees: bool = True,
497
501
  ) -> NDArray:
498
502
  """
499
503
  Convert cartesian coordinates to spherical coordinates.
@@ -504,6 +508,9 @@ def cartesian_to_spherical(
504
508
  A NumPy array with shape (n, 3) where each
505
509
  row represents a vector
506
510
  with x, y, z-components.
511
+ degrees : bool
512
+ If True, the azimuth and elevation angles are returned in degrees.
513
+ Defaults to True.
507
514
 
508
515
  Returns
509
516
  -------
@@ -512,8 +519,16 @@ def cartesian_to_spherical(
512
519
  the spherical coordinates (r, azimuth, elevation):
513
520
 
514
521
  - r : Distance of the point from the origin.
515
- - azimuth : angle in the xy-plane in radians [0, 2*pi].
516
- - elevation : angle from the z-axis in radians [-pi/2, pi/2].
522
+ - azimuth : angle in the xy-plane
523
+ In degrees if degrees parameter is True (by default):
524
+ output range=[0, 360],
525
+ otherwise in radians if degrees parameter is False:
526
+ output range=[0, 2*pi].
527
+ - elevation : angle from the z-axis
528
+ In degrees if degrees parameter is True (by default):
529
+ output range=[0, 180],
530
+ otherwise in radians if degrees parameter is False:
531
+ output range=[-pi/2, pi/2].
517
532
  """
518
533
  # Magnitude of the velocity vector
519
534
  magnitude_v = np.linalg.norm(v, axis=-1, keepdims=True)
@@ -528,9 +543,12 @@ def cartesian_to_spherical(
528
543
 
529
544
  # Ensure azimuth is from 0 to 2PI
530
545
  az = az % (2 * np.pi)
531
- spherical_coords = np.stack(
532
- (np.squeeze(magnitude_v), np.degrees(az), np.degrees(el)), axis=-1
533
- )
546
+
547
+ if degrees:
548
+ az = np.degrees(az)
549
+ el = np.degrees(el)
550
+
551
+ spherical_coords = np.stack((np.squeeze(magnitude_v), az, el), axis=-1)
534
552
 
535
553
  return spherical_coords
536
554
 
@@ -1,7 +1,7 @@
1
1
  """Time conversion functions that rely on SPICE."""
2
2
 
3
3
  import typing
4
- from collections.abc import Collection
4
+ from collections.abc import Collection, Iterable
5
5
  from typing import Union
6
6
 
7
7
  import numpy as np
@@ -13,6 +13,32 @@ from imap_processing.spice.kernels import ensure_spice
13
13
 
14
14
  TICK_DURATION = 2e-5 # 20 microseconds as defined in imap_sclk_0000.tsc
15
15
 
16
+ # Hard code the J2000 epoch. This allows for CDF epoch to be converted without
17
+ # use of SPICE though it should be noted that this results in a 5-second error
18
+ # due to the occurrence of 5 leap-seconds since the J2000 epoch.
19
+ # TODO: Implement a function for converting CDF epoch to UTC correctly.
20
+ # see github ticket #1208
21
+ # The UTC string was generated by:
22
+ # >>> spiceypy.et2utc(0, "ISOC", 9)
23
+ J2000_EPOCH = np.datetime64("2000-01-01T11:58:55.816072737", "ns")
24
+
25
+
26
+ def met_to_sclkticks(met: npt.ArrayLike) -> npt.NDArray[float]:
27
+ """
28
+ Convert Mission Elapsed Time (MET) to floating point spacecraft clock ticks.
29
+
30
+ Parameters
31
+ ----------
32
+ met : float, numpy.ndarray
33
+ Number of seconds since epoch according to the spacecraft clock.
34
+
35
+ Returns
36
+ -------
37
+ numpy.ndarray[float]
38
+ The mission elapsed time converted to nanoseconds since the J2000 epoch.
39
+ """
40
+ return np.asarray(met, dtype=float) / TICK_DURATION
41
+
16
42
 
17
43
  def met_to_j2000ns(
18
44
  met: npt.ArrayLike,
@@ -40,7 +66,7 @@ def met_to_j2000ns(
40
66
  "tick" which is defined to be 20 microseconds, according to the sclk kernel,
41
67
  it is preferable to use the higher accuracy method.
42
68
  """
43
- sclk_ticks = np.asarray(met, dtype=float) / TICK_DURATION
69
+ sclk_ticks = met_to_sclkticks(met)
44
70
  return np.asarray(_sct2e_wrapper(sclk_ticks) * 1e9, dtype=np.int64)
45
71
 
46
72
 
@@ -64,6 +90,53 @@ def j2000ns_to_j2000s(j2000ns: npt.ArrayLike) -> npt.NDArray[float]:
64
90
  return np.asarray(j2000ns, dtype=np.float64) / 1e9
65
91
 
66
92
 
93
+ @typing.no_type_check
94
+ @ensure_spice(time_kernels_only=True)
95
+ def met_to_utc(met: npt.ArrayLike, precision: int = 9) -> npt.NDArray[str]:
96
+ """
97
+ Convert mission elapsed time (MET) to UTC.
98
+
99
+ Parameters
100
+ ----------
101
+ met : float, numpy.ndarray
102
+ Number of seconds since epoch according to the spacecraft clock.
103
+ precision : int
104
+ The number of digits of precision to which fractional seconds
105
+ are to be computed.
106
+
107
+ Returns
108
+ -------
109
+ numpy.ndarray[str]
110
+ The mission elapsed time converted to UTC string. The UTC string(s)
111
+ returned will be of the form '1987-04-12T16:31:12.814' with the
112
+ fractional seconds precision as specified by the precision keyword.
113
+ """
114
+ sclk_ticks = met_to_sclkticks(met)
115
+ et = _sct2e_wrapper(sclk_ticks)
116
+ return spice.et2utc(et, "ISOC", prec=precision)
117
+
118
+
119
+ def met_to_datetime64(
120
+ met: npt.ArrayLike,
121
+ ) -> Union[np.datetime64, npt.NDArray[np.datetime64]]:
122
+ """
123
+ Convert mission elapsed time (MET) to datetime.datetime.
124
+
125
+ Parameters
126
+ ----------
127
+ met : float, numpy.ndarray
128
+ Number of seconds since epoch according to the spacecraft clock.
129
+
130
+ Returns
131
+ -------
132
+ numpy.ndarray[str]
133
+ The mission elapsed time converted to UTC string.
134
+ """
135
+ if isinstance(met, typing.Iterable):
136
+ return np.asarray([np.datetime64(utc) for utc in met_to_utc(met)])
137
+ return np.datetime64(met_to_utc(met))
138
+
139
+
67
140
  @typing.no_type_check
68
141
  @ensure_spice
69
142
  def _sct2e_wrapper(
@@ -90,3 +163,72 @@ def _sct2e_wrapper(
90
163
  return np.array([spice.sct2e(IMAP_SC_ID, s) for s in sclk_ticks])
91
164
  else:
92
165
  return spice.sct2e(IMAP_SC_ID, sclk_ticks)
166
+
167
+
168
+ @typing.no_type_check
169
+ @ensure_spice
170
+ def str_to_et(
171
+ time_str: Union[str, Iterable[str]],
172
+ ) -> Union[float, np.ndarray]:
173
+ """
174
+ Convert string to ephemeris time.
175
+
176
+ Decorated wrapper for spiceypy.str2et that vectorizes the function in addition
177
+ to wrapping with the @ensure_spice automatic kernel furnishing functionality.
178
+ https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.str2et
179
+
180
+ Parameters
181
+ ----------
182
+ time_str : str or Iterable[str]
183
+ Input string(s) to be converted to ephemeris time.
184
+
185
+ Returns
186
+ -------
187
+ ephemeris_time: np.ndarray
188
+ Ephemeris time, seconds past J2000.
189
+ """
190
+ if isinstance(time_str, str):
191
+ return spice.str2et(time_str)
192
+ else:
193
+ return np.array([spice.str2et(t) for t in time_str])
194
+
195
+
196
+ @typing.no_type_check
197
+ @ensure_spice
198
+ def et_to_utc(
199
+ et: Union[float, Iterable[float]],
200
+ format_str: str = "ISOC",
201
+ precision: int = 3,
202
+ utclen: int = 24,
203
+ ) -> Union[str, np.ndarray]:
204
+ """
205
+ Convert ephemeris time to UTC.
206
+
207
+ Decorated wrapper for spiceypy.et2utc that vectorizes the function in addition
208
+ to wrapping with the @ensure_spice automatic kernel furnishing functionality.
209
+ https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.et2utc
210
+
211
+ Parameters
212
+ ----------
213
+ et : float or Iterable[float]
214
+ Input ephemeris time(s) to be converted to UTC.
215
+ format_str : str
216
+ Format of the output time string. Default is "ISOC". All options:
217
+ "C" Calendar format, UTC.
218
+ "D" Day-of-Year format, UTC.
219
+ "J" Julian Date format, UTC.
220
+ "ISOC" ISO Calendar format, UTC.
221
+ "ISOD" ISO Day-of-Year format, UTC.
222
+ precision : int
223
+ Digits of precision in fractional seconds or days. Default is 3.
224
+ utclen : int
225
+ The length of the output string. Default is 24 (to accommodate the
226
+ "YYYY-MM-DDT00:00:00.000" format + 1). From the NAIF docs: if the output string
227
+ is expected to have `x` characters, utclen` must be x + 1.
228
+
229
+ Returns
230
+ -------
231
+ utc_time : str or np.ndarray
232
+ UTC time(s).
233
+ """
234
+ return spice.et2utc(et, format_str, precision, utclen)
@@ -39,7 +39,7 @@ def filter_good_data(full_sweep_sci: xr.Dataset) -> npt.NDArray:
39
39
  """
40
40
  # PLAN_ID for current sweep should all be one value and
41
41
  # SWEEP_TABLE should all be one value.
42
- plan_id = full_sweep_sci["plan_id_science"].data.reshape(-1, 12)
42
+ plan_id = full_sweep_sci["plan_id"].data.reshape(-1, 12)
43
43
  sweep_table = full_sweep_sci["sweep_table"].data.reshape(-1, 12)
44
44
 
45
45
  mode = full_sweep_sci["mode"].data.reshape(-1, 12)
@@ -72,7 +72,7 @@ def filter_good_data(full_sweep_sci: xr.Dataset) -> npt.NDArray:
72
72
  )
73
73
  logger.debug(
74
74
  "Plan ID should be same: "
75
- f"{full_sweep_sci['plan_id_science'].data[bad_cycle_indices]}"
75
+ f"{full_sweep_sci['plan_id'].data[bad_cycle_indices]}"
76
76
  )
77
77
  logger.debug(
78
78
  f"Mode Id should be 3(HVSCI): {full_sweep_sci['mode'].data[bad_cycle_indices]}"
@@ -615,7 +615,7 @@ def process_swapi_science(
615
615
  attrs=cdf_manager.get_variable_attributes("sweep_table"),
616
616
  )
617
617
  dataset["plan_id"] = xr.DataArray(
618
- good_sweep_sci["plan_id_science"].data.reshape(total_full_sweeps, 12)[:, 0],
618
+ good_sweep_sci["plan_id"].data.reshape(total_full_sweeps, 12)[:, 0],
619
619
  name="plan_id",
620
620
  dims=["epoch"],
621
621
  attrs=cdf_manager.get_variable_attributes("plan_id"),