imap-processing 1.0.28__tar.gz → 1.0.29__tar.gz

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.
Files changed (294) hide show
  1. {imap_processing-1.0.28 → imap_processing-1.0.29}/PKG-INFO +1 -1
  2. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/_version.py +2 -2
  3. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ancillary/ancillary_dataset_combiner.py +4 -8
  4. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +48 -0
  5. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cli.py +31 -4
  6. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l2.py +10 -0
  7. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ena_maps/ena_maps.py +12 -2
  8. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/l2/glows_l2_data.py +28 -5
  9. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hi/hi_l1c.py +223 -24
  10. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hi/utils.py +194 -53
  11. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/generate_coverage.py +1 -68
  12. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/constants.py +32 -2
  13. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1b/extendedspin.py +58 -4
  14. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1b/goodtimes.py +9 -0
  15. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1b/quality_flag_filters.py +3 -0
  16. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1b/ultra_l1b.py +23 -4
  17. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1b/ultra_l1b_culling.py +143 -3
  18. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/helio_pset.py +30 -19
  19. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/l1c_lookup_utils.py +109 -26
  20. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/spacecraft_pset.py +31 -17
  21. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/ultra_l1c.py +5 -0
  22. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +1 -1
  23. {imap_processing-1.0.28 → imap_processing-1.0.29}/pyproject.toml +1 -1
  24. {imap_processing-1.0.28 → imap_processing-1.0.29}/LICENSE +0 -0
  25. {imap_processing-1.0.28 → imap_processing-1.0.29}/README.md +0 -0
  26. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/__init__.py +0 -0
  27. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ancillary/__init__.py +0 -0
  28. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ccsds/__init__.py +0 -0
  29. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ccsds/ccsds_data.py +0 -0
  30. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ccsds/excel_to_xtce.py +0 -0
  31. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/__init__.py +0 -0
  32. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +0 -0
  33. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +0 -0
  34. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_codice_l2-hi-direct-events_variable_attrs.yaml +0 -0
  35. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_codice_l2-hi-omni_variable_attrs.yaml +0 -0
  36. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_codice_l2-hi-sectored_variable_attrs.yaml +0 -0
  37. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_codice_l2-lo-angular_variable_attrs.yaml +0 -0
  38. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_codice_l2-lo-direct-events_variable_attrs.yaml +0 -0
  39. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_codice_l2-lo-species_variable_attrs.yaml +0 -0
  40. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_constant_attrs.yaml +0 -0
  41. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_default_global_cdf_attrs.yaml +0 -0
  42. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_enamaps_l2-common_variable_attrs.yaml +0 -0
  43. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_enamaps_l2-healpix_variable_attrs.yaml +0 -0
  44. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_enamaps_l2-rectangular_variable_attrs.yaml +0 -0
  45. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +0 -0
  46. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_glows_l1a_variable_attrs.yaml +0 -0
  47. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +0 -0
  48. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_glows_l2_variable_attrs.yaml +0 -0
  49. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +0 -0
  50. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_hi_variable_attrs.yaml +0 -0
  51. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +0 -0
  52. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +0 -0
  53. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +0 -0
  54. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml +0 -0
  55. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_ialirt_global_cdf_attrs.yaml +0 -0
  56. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_ialirt_l1_variable_attrs.yaml +0 -0
  57. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +0 -0
  58. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +0 -0
  59. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +0 -0
  60. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_idex_l2a_variable_attrs.yaml +0 -0
  61. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_idex_l2b_variable_attrs.yaml +0 -0
  62. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml +0 -0
  63. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +0 -0
  64. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +0 -0
  65. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_lo_l1b_variable_attrs.yaml +0 -0
  66. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_lo_l1c_variable_attrs.yaml +0 -0
  67. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +0 -0
  68. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_mag_l1a_variable_attrs.yaml +0 -0
  69. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_mag_l1b_variable_attrs.yaml +0 -0
  70. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +0 -0
  71. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_mag_l2_variable_attrs.yaml +0 -0
  72. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_spacecraft_global_cdf_attrs.yaml +0 -0
  73. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_spacecraft_variable_attrs.yaml +0 -0
  74. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml +0 -0
  75. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +0 -0
  76. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +0 -0
  77. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +0 -0
  78. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +0 -0
  79. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +0 -0
  80. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +0 -0
  81. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +0 -0
  82. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +0 -0
  83. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/config/imap_variable_schema.yaml +0 -0
  84. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/imap_cdf_manager.py +0 -0
  85. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/cdf/utils.py +0 -0
  86. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/__init__.py +0 -0
  87. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1a.py +0 -0
  88. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1a_de.py +0 -0
  89. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1a_hi_counters_aggregated.py +0 -0
  90. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1a_hi_counters_singles.py +0 -0
  91. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1a_hi_omni.py +0 -0
  92. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1a_hi_priority.py +0 -0
  93. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1a_hi_sectored.py +0 -0
  94. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1a_ialirt_hi.py +0 -0
  95. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1a_lo_angular.py +0 -0
  96. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1a_lo_counters_aggregated.py +0 -0
  97. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1a_lo_counters_singles.py +0 -0
  98. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1a_lo_priority.py +0 -0
  99. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1a_lo_species.py +0 -0
  100. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/codice_l1b.py +0 -0
  101. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/constants.py +0 -0
  102. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/data/esa_sweep_values.csv +0 -0
  103. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/data/lo_stepping_values.csv +0 -0
  104. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/decompress.py +0 -0
  105. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/packet_definitions/P_COD_NHK.xml +0 -0
  106. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/packet_definitions/imap_codice_packet-definition_20250101_v001.xml +0 -0
  107. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/packet_definitions/imap_codice_packet-definition_20260129_v001.xml +0 -0
  108. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/codice/utils.py +0 -0
  109. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ena_maps/__init__.py +0 -0
  110. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ena_maps/utils/__init__.py +0 -0
  111. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ena_maps/utils/coordinates.py +0 -0
  112. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ena_maps/utils/corrections.py +0 -0
  113. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ena_maps/utils/map_utils.py +0 -0
  114. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ena_maps/utils/naming.py +0 -0
  115. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ena_maps/utils/spatial_utils.py +0 -0
  116. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/__init__.py +0 -0
  117. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/ancillary/imap_glows_exclusions-by-instr-team_20250923_v002.dat +0 -0
  118. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/ancillary/imap_glows_map-of-excluded-regions_20250923_v002.dat +0 -0
  119. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/ancillary/imap_glows_map-of-uv-sources_20250923_v002.dat +0 -0
  120. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/ancillary/imap_glows_pipeline-settings_20250923_v002.json +0 -0
  121. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/ancillary/imap_glows_pipeline_settings_v001.json +0 -0
  122. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/ancillary/imap_glows_suspected-transients_20250923_v002.dat +0 -0
  123. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/ancillary/l1b_conversion_table_v001.json +0 -0
  124. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/l0/__init__.py +0 -0
  125. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/l0/decom_glows.py +0 -0
  126. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/l0/glows_l0_data.py +0 -0
  127. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/l1a/glows_l1a.py +0 -0
  128. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/l1a/glows_l1a_data.py +0 -0
  129. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/l1b/glows_l1b.py +0 -0
  130. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/l1b/glows_l1b_data.py +0 -0
  131. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/l2/glows_l2.py +0 -0
  132. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/packet_definitions/GLX_COMBINED.xml +0 -0
  133. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/packet_definitions/P_GLX_TMSCDE.xml +0 -0
  134. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/packet_definitions/P_GLX_TMSCHIST.xml +0 -0
  135. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/utils/__init__.py +0 -0
  136. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/glows/utils/constants.py +0 -0
  137. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hi/__init__.py +0 -0
  138. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hi/hi_goodtimes.py +0 -0
  139. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hi/hi_l1a.py +0 -0
  140. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hi/hi_l1b.py +0 -0
  141. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hi/hi_l2.py +0 -0
  142. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hi/packet_definitions/TLM_HI_COMBINED_SCI.xml +0 -0
  143. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hi/packet_definitions/__init__.py +0 -0
  144. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hit/__init__.py +0 -0
  145. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hit/hit_utils.py +0 -0
  146. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hit/l0/__init__.py +0 -0
  147. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hit/l0/constants.py +0 -0
  148. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hit/l0/decom_hit.py +0 -0
  149. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hit/l1a/__init__.py +0 -0
  150. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hit/l1a/hit_l1a.py +0 -0
  151. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hit/l1b/constants.py +0 -0
  152. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hit/l1b/hit_l1b.py +0 -0
  153. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hit/l2/constants.py +0 -0
  154. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hit/l2/hit_l2.py +0 -0
  155. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/hit/packet_definitions/hit_packet_definitions.xml +0 -0
  156. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/__init__.py +0 -0
  157. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/calculate_ingest.py +0 -0
  158. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/constants.py +0 -0
  159. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/l0/__init__.py +0 -0
  160. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/l0/ialirt_spice.py +0 -0
  161. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/l0/mag_l0_ialirt_data.py +0 -0
  162. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/l0/parse_mag.py +0 -0
  163. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/l0/process_codice.py +0 -0
  164. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/l0/process_hit.py +0 -0
  165. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/l0/process_status.py +0 -0
  166. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/l0/process_swapi.py +0 -0
  167. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/l0/process_swe.py +0 -0
  168. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/packet_definitions/__init__.py +0 -0
  169. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/packet_definitions/ialirt.xml +0 -0
  170. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +0 -0
  171. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +0 -0
  172. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/packet_definitions/ialirt_hit.xml +0 -0
  173. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/packet_definitions/ialirt_mag.xml +0 -0
  174. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +0 -0
  175. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/packet_definitions/ialirt_swe.xml +0 -0
  176. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/process_ephemeris.py +0 -0
  177. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/utils/constants.py +0 -0
  178. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/utils/create_xarray.py +0 -0
  179. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/utils/grouping.py +0 -0
  180. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ialirt/utils/time.py +0 -0
  181. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/__init__.py +0 -0
  182. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/atomic_masses.csv +0 -0
  183. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/decode.py +0 -0
  184. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/evt_msg_decode_utils.py +0 -0
  185. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/idex_constants.py +0 -0
  186. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/idex_evt_msg_parsing_dictionaries.json +0 -0
  187. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/idex_l0.py +0 -0
  188. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/idex_l1a.py +0 -0
  189. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/idex_l1b.py +0 -0
  190. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/idex_l2a.py +0 -0
  191. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/idex_l2b.py +0 -0
  192. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/idex_utils.py +0 -0
  193. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +0 -0
  194. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +0 -0
  195. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/idex/packet_definitions/idex_science_packet_definition.xml +0 -0
  196. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/__init__.py +0 -0
  197. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv +0 -0
  198. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv +0 -0
  199. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l0/__init__.py +0 -0
  200. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l0/decompression_tables/decompression_tables.py +0 -0
  201. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l0/decompression_tables/log10_12_to_16_bit_uncompress.csv +0 -0
  202. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l0/decompression_tables/log10_8_to_12_bit_uncompress.csv +0 -0
  203. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l0/decompression_tables/log10_8_to_16_bit_uncompress.csv +0 -0
  204. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l0/lo_apid.py +0 -0
  205. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l0/lo_science.py +0 -0
  206. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l0/lo_star_sensor.py +0 -0
  207. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l0/utils/binary_string.py +0 -0
  208. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l0/utils/bit_decompression.py +0 -0
  209. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l1a/__init__.py +0 -0
  210. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l1a/lo_l1a.py +0 -0
  211. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l1b/lo_l1b.py +0 -0
  212. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l1b/tof_conversions.py +0 -0
  213. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l1c/lo_l1c.py +0 -0
  214. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/l2/lo_l2.py +0 -0
  215. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/lo_ancillary.py +0 -0
  216. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/lo/packet_definitions/lo_xtce.xml +0 -0
  217. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/__init__.py +0 -0
  218. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/constants.py +0 -0
  219. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/imap_mag_sdc_configuration_v001.py +0 -0
  220. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l0/decom_mag.py +0 -0
  221. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l0/mag_l0_data.py +0 -0
  222. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l1a/mag_l1a.py +0 -0
  223. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l1a/mag_l1a_data.py +0 -0
  224. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l1b/imap_mag_l1b-calibration_20240229_v002.cdf +0 -0
  225. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l1b/mag_l1b.py +0 -0
  226. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l1c/interpolation_methods.py +0 -0
  227. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l1c/mag_l1c.py +0 -0
  228. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l1d/__init__.py +0 -0
  229. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l1d/mag_l1d.py +0 -0
  230. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l1d/mag_l1d_data.py +0 -0
  231. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l2/__init__.py +0 -0
  232. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l2/mag_l2.py +0 -0
  233. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/l2/mag_l2_data.py +0 -0
  234. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/mag/packet_definitions/MAG_SCI_COMBINED.xml +0 -0
  235. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/quality_flags.py +0 -0
  236. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/spacecraft/packet_definitions/scid_x252.xml +0 -0
  237. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/spacecraft/quaternions.py +0 -0
  238. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/spice/__init__.py +0 -0
  239. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/spice/config.py +0 -0
  240. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/spice/geometry.py +0 -0
  241. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/spice/pointing_frame.py +0 -0
  242. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/spice/repoint.py +0 -0
  243. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/spice/spin.py +0 -0
  244. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/spice/time.py +0 -0
  245. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swapi/__init__.py +0 -0
  246. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swapi/constants.py +0 -0
  247. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swapi/l1/__init__.py +0 -0
  248. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swapi/l1/swapi_l1.py +0 -0
  249. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swapi/l2/__init__.py +0 -0
  250. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swapi/l2/swapi_l2.py +0 -0
  251. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swapi/packet_definitions/__init__.py +0 -0
  252. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swapi/packet_definitions/swapi_packet_definition.xml +0 -0
  253. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swapi/swapi_utils.py +0 -0
  254. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swe/__init__.py +0 -0
  255. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swe/l1a/__init__.py +0 -0
  256. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swe/l1a/swe_l1a.py +0 -0
  257. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swe/l1a/swe_science.py +0 -0
  258. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swe/l1b/swe_l1b.py +0 -0
  259. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swe/l2/swe_l2.py +0 -0
  260. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swe/packet_definitions/__init__.py +0 -0
  261. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swe/packet_definitions/swe_packet_definition.xml +0 -0
  262. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swe/utils/__init__.py +0 -0
  263. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swe/utils/swe_constants.py +0 -0
  264. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/swe/utils/swe_utils.py +0 -0
  265. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/__init__.py +0 -0
  266. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l0/__init__.py +0 -0
  267. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l0/decom_tools.py +0 -0
  268. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l0/decom_ultra.py +0 -0
  269. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l0/ultra_utils.py +0 -0
  270. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1a/__init__.py +0 -0
  271. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1a/ultra_l1a.py +0 -0
  272. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1b/badtimes.py +0 -0
  273. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1b/de.py +0 -0
  274. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1b/lookup_utils.py +0 -0
  275. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1b/ultra_l1b_annotated.py +0 -0
  276. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1b/ultra_l1b_extended.py +0 -0
  277. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/make_helio_index_maps.py +0 -0
  278. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/sim_spice_kernels/imap_001.tf +0 -0
  279. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/sim_spice_kernels/imap_science_100.tf +0 -0
  280. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/sim_spice_kernels/imap_science_120.tf +0 -0
  281. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/sim_spice_kernels/imap_sclk_0000.tsc +0 -0
  282. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/sim_spice_kernels/imap_spk_demo.bsp +0 -0
  283. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/sim_spice_kernels/naif0012.tls +0 -0
  284. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/sim_spice_kernels/sim_1yr_imap_attitude.bc +0 -0
  285. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/sim_spice_kernels/sim_1yr_imap_pointing_frame.bc +0 -0
  286. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l1c/ultra_l1c_culling.py +0 -0
  287. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l2/__init__.py +0 -0
  288. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/l2/ultra_l2.py +0 -0
  289. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/packet_definitions/README.md +0 -0
  290. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +0 -0
  291. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/packet_definitions/__init__.py +0 -0
  292. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/utils/__init__.py +0 -0
  293. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/ultra/utils/ultra_l1_utils.py +0 -0
  294. {imap_processing-1.0.28 → imap_processing-1.0.29}/imap_processing/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: imap-processing
3
- Version: 1.0.28
3
+ Version: 1.0.29
4
4
  Summary: IMAP Science Operations Center Processing
5
5
  License: MIT
6
6
  Keywords: IMAP,SDC,SOC,Science Operations
@@ -1,3 +1,3 @@
1
1
  # These version placeholders will be replaced later during substitution.
2
- __version__ = "1.0.28"
3
- __version_tuple__ = (1, 0, 28)
2
+ __version__ = "1.0.29"
3
+ __version_tuple__ = (1, 0, 29)
@@ -431,17 +431,13 @@ class GlowsAncillaryCombiner(AncillaryCombiner):
431
431
  lines = [line.strip() for line in f if not line.startswith("#")]
432
432
  identifiers = [line.split(" ", 1)[0] for line in lines]
433
433
  values = [float(line.split(" ", 1)[1]) for line in lines]
434
- ds = xr.Dataset(
434
+ return xr.Dataset(
435
435
  {
436
- "cps_per_r": (["start_time_utc"], values), # floats
437
- },
438
- coords={
439
- "start_time_utc": np.array(identifiers, dtype="datetime64[s]")
440
- }, # (e.g. '2025-07-01T00:00:00')
436
+ "start_time_utc": (["time_block"], identifiers),
437
+ "cps_per_r": (["time_block"], values),
438
+ }
441
439
  )
442
440
 
443
- return ds.sortby("start_time_utc")
444
-
445
441
  elif filename.endswith(".json"):
446
442
  # Handle pipeline settings JSON file using the generic read_json method
447
443
  return self.convert_json_to_dataset(filepath)
@@ -212,6 +212,54 @@ imap_ultra_l1b_90sensor-de:
212
212
  Logical_source: imap_ultra_l1b_90sensor-de
213
213
  Logical_source_description: IMAP-Ultra Instrument Level-1B Direct Event Data.
214
214
 
215
+ imap_ultra_l1b_45sensor-priority-1-de:
216
+ <<: *instrument_base
217
+ Data_type: L1B_PRIORITY_1_DE>Level-1B Priority 1 Direct Event
218
+ Logical_source: imap_ultra_l1b_45sensor-priority-1-de
219
+ Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 1 Direct Event Data.
220
+
221
+ imap_ultra_l1b_90sensor-priority-1-de:
222
+ <<: *instrument_base
223
+ Data_type: L1B_PRIORITY_1_DE>Level-1B Priority 1 Direct Event
224
+ Logical_source: imap_ultra_l1b_90sensor-priority-1-de
225
+ Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 1 Direct Event Data.
226
+
227
+ imap_ultra_l1b_45sensor-priority-2-de:
228
+ <<: *instrument_base
229
+ Data_type: L1B_PRIORITY_2_DE>Level-1B Priority 2 Direct Event
230
+ Logical_source: imap_ultra_l1b_45sensor-priority-2-de
231
+ Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 2 Direct Event Data.
232
+
233
+ imap_ultra_l1b_90sensor-priority-2-de:
234
+ <<: *instrument_base
235
+ Data_type: L1B_PRIORITY_2_DE>Level-1B Priority 2 Direct Event
236
+ Logical_source: imap_ultra_l1b_90sensor-priority-2-de
237
+ Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 2 Direct Event Data.
238
+
239
+ imap_ultra_l1b_45sensor-priority-3-de:
240
+ <<: *instrument_base
241
+ Data_type: L1B_PRIORITY_3_DE>Level-1B Priority 3 Direct Event
242
+ Logical_source: imap_ultra_l1b_45sensor-priority-3-de
243
+ Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 3 Direct Event Data.
244
+
245
+ imap_ultra_l1b_90sensor-priority-3-de:
246
+ <<: *instrument_base
247
+ Data_type: L1B_PRIORITY_3_DE>Level-1B Priority 3 Direct Event
248
+ Logical_source: imap_ultra_l1b_90sensor-priority-3-de
249
+ Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 3 Direct Event Data.
250
+
251
+ imap_ultra_l1b_45sensor-priority-4-de:
252
+ <<: *instrument_base
253
+ Data_type: L1B_PRIORITY_4_DE>Level-1B Priority 4 Direct Event
254
+ Logical_source: imap_ultra_l1b_45sensor-priority-4-de
255
+ Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 4 Direct Event Data.
256
+
257
+ imap_ultra_l1b_90sensor-priority-4-de:
258
+ <<: *instrument_base
259
+ Data_type: L1B_PRIORITY_4_DE>Level-1B Priority 4 Direct Event
260
+ Logical_source: imap_ultra_l1b_90sensor-priority-4-de
261
+ Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 4 Direct Event Data.
262
+
215
263
  imap_ultra_l1b_45sensor-extendedspin:
216
264
  <<: *instrument_base
217
265
  Data_type: L1B_45Sensor-ExtendedSpin>Level-1B Extended Spin for Ultra45
@@ -879,11 +879,36 @@ class Hi(ProcessInstrument):
879
879
  f"Expected exactly one DE science dependency. "
880
880
  f"Got {l1b_de_paths}"
881
881
  )
882
- anc_paths = dependencies.get_file_paths(data_type="ancillary")
883
- if len(anc_paths) != 1:
882
+
883
+ # Get ancillary dependencies
884
+ anc_dependencies = dependencies.get_processing_inputs(
885
+ data_type="ancillary"
886
+ )
887
+ if len(anc_dependencies) != 2:
888
+ raise ValueError(
889
+ f"Expected two ancillary dependencies (cal-prod and "
890
+ f"backgrounds). Got "
891
+ f"{[anc_dep.descriptor for anc_dep in anc_dependencies]}"
892
+ )
893
+
894
+ # Create mapping from descriptor to path
895
+ anc_path_dict = {
896
+ dep.descriptor.split("-", 1)[1]: dep.imap_file_paths[
897
+ 0
898
+ ].construct_path()
899
+ for dep in anc_dependencies
900
+ }
901
+
902
+ # Verify we have both required ancillary files
903
+ if (
904
+ "cal-prod" not in anc_path_dict
905
+ or "backgrounds" not in anc_path_dict
906
+ ):
884
907
  raise ValueError(
885
- f"Expected exactly one ancillary dependency. Got {anc_paths}"
908
+ f"Missing required ancillary files. Expected 'cal-prod' and "
909
+ f"'backgrounds', got {list(anc_path_dict.keys())}"
886
910
  )
911
+
887
912
  # Load goodtimes dependency
888
913
  goodtimes_paths = dependencies.get_file_paths(
889
914
  source="hi", data_type="l1b", descriptor="goodtimes"
@@ -893,10 +918,12 @@ class Hi(ProcessInstrument):
893
918
  f"Expected exactly one goodtimes dependency. "
894
919
  f"Got {goodtimes_paths}"
895
920
  )
921
+
896
922
  datasets = hi_l1c.hi_l1c(
897
923
  load_cdf(l1b_de_paths[0]),
898
- anc_paths[0],
924
+ anc_path_dict["cal-prod"],
899
925
  load_cdf(goodtimes_paths[0]),
926
+ anc_path_dict["backgrounds"],
900
927
  )
901
928
  elif self.data_level == "l2":
902
929
  science_paths = dependencies.get_file_paths(source="hi", data_type="l1c")
@@ -1166,6 +1166,16 @@ def process_hi_sectored(dependencies: ProcessingInputCollection) -> xr.Dataset:
1166
1166
  base_angles = np.asarray(L2_HI_SECTORED_ANGLE, dtype=float).reshape(n_spin, 1)
1167
1167
 
1168
1168
  spin_angle = (base_angles + elevation_offsets) % 360.0
1169
+ # We need to transpose spin_angle to put spin_angle data into correct
1170
+ # dimensions. Eg.
1171
+ # spin_angle[0,0] - 285
1172
+ # spin_angle[1,0] - 315
1173
+ # ....
1174
+ # This is expected behavior per CoDICE because the spin angle should increments
1175
+ # at 30 degree spin angle per elevation angle. Due to that, in the example, the
1176
+ # column remained same but spin angle incremented by 30 degrees for each
1177
+ # elevation angle.
1178
+ spin_angle = spin_angle.T
1169
1179
  # Add spin angle variable using the new elevation_angle dimension
1170
1180
  l2_dataset["spin_angle"] = (("spin_sector", "elevation_angle"), spin_angle)
1171
1181
  l2_dataset["spin_angle"].attrs = cdf_attrs.get_variable_attributes(
@@ -627,6 +627,14 @@ class UltraPointingSet(HealpixPointingSet):
627
627
  nside of the input pset counts variable (e.g. 128) to the nside of the pset.
628
628
  """
629
629
  pset_data = self.data
630
+ # TODO remove this check once we reprocess all psets
631
+ # going forward, all psets should have counts_pixel_index as a coordinate.
632
+ if "counts_pixel_index" not in pset_data.dims:
633
+ logger.info(
634
+ "No counts_pixel_index found in the dataset. Skipping counts "
635
+ "downsampling."
636
+ )
637
+ return
630
638
  counts_n_pix = pset_data.sizes["counts_pixel_index"]
631
639
  pset_n_pix = hp.nside2npix(self.nside)
632
640
  if counts_n_pix != pset_n_pix:
@@ -647,9 +655,11 @@ class UltraPointingSet(HealpixPointingSet):
647
655
  # Get counts in nested ordering. In nested ordering, the
648
656
  # pixels that need to be binned together to go from the counts nside to
649
657
  # the pset nside are contiguous in the array.
658
+ # Use nest2ring to get the indices to convert from ring to nest ordering if
659
+ # necessary.
650
660
  if not self.nested:
651
661
  counts_n = counts[
652
- :, hp.ring2nest(counts_nside, np.arange(counts_n_pix))
662
+ :, hp.nest2ring(counts_nside, np.arange(counts_n_pix))
653
663
  ]
654
664
  else:
655
665
  counts_n = counts
@@ -667,7 +677,7 @@ class UltraPointingSet(HealpixPointingSet):
667
677
  # convert back to ring ordering if necessary and store in the
668
678
  # downsampled counts array
669
679
  binned_counts_n = binned_counts_n[
670
- :, hp.nest2ring(self.nside, np.arange(pset_n_pix))
680
+ :, hp.ring2nest(self.nside, np.arange(pset_n_pix))
671
681
  ]
672
682
 
673
683
  self.data["counts"] = xr.DataArray(
@@ -574,16 +574,39 @@ class HistogramL2:
574
574
  epoch_values : np.ndarray
575
575
  Array of epoch values from the L1B dataset, in TT J2000 nanoseconds.
576
576
  calibration_dataset : xr.Dataset
577
- Dataset containing calibration data.
577
+ Dataset containing calibration data with the following structure:
578
+ Coords: epoch (datetime64[s])
579
+ Dims: epoch, cps_per_r_dim_0, start_time_utc_dim_0
580
+ Data vars: "cps_per_r" and "start_time_utc" are 2D (epoch, *_dim_0)
581
+
582
+ Note: epoch and start_time_utc do not necessarily match in size or
583
+ values
584
+ - epoch contains timestamps in the calibration data up to a defined
585
+ day buffer and start_time_utc are the timestamps for all the
586
+ calibration data entries.
587
+ - epoch is used for selecting the time block, and start_time_utc is
588
+ used for selecting the calibration value within that block.
578
589
 
579
590
  Returns
580
591
  -------
581
592
  float
582
593
  The calibration factor needed to compute flux in Rayleigh units.
583
594
  """
584
- # Use the midpoint epoch for the day
595
+ # Use the midpoint epoch for the observation day
585
596
  mid_idx = len(epoch_values) // 2
586
597
  mid_epoch_utc = et_to_datetime64(ttj2000ns_to_et(epoch_values[mid_idx].item()))
587
- return calibration_dataset.sel(start_time_utc=mid_epoch_utc, method="pad")[
588
- "cps_per_r"
589
- ].data.item()
598
+
599
+ # Select calibration data before or equal to mid_epoch_utc using "pad" to find
600
+ # the nearest preceding entry in the calibration dataset's epoch
601
+ # coordinate which is in UTC datetime64 format.
602
+ cal_at_epoch = calibration_dataset.sel(epoch=mid_epoch_utc, method="pad")
603
+
604
+ # start_time_utc is a data variable with its own index dimension.
605
+ # Use searchsorted to find the last entry whose start_time_utc <= mid_epoch_utc.
606
+ start_times = np.array(
607
+ cal_at_epoch["start_time_utc"].values, dtype="datetime64[ns]"
608
+ )
609
+ nearest_idx = np.searchsorted(start_times, mid_epoch_utc, side="right") - 1
610
+
611
+ # Select the calibration value at the nearest index.
612
+ return float(cal_at_epoch["cps_per_r"].isel(cps_per_r_dim_0=nearest_idx))
@@ -13,10 +13,12 @@ from numpy import typing as npt
13
13
  from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
14
14
  from imap_processing.cdf.utils import parse_filename_like
15
15
  from imap_processing.hi.utils import (
16
+ BackgroundConfig,
16
17
  CalibrationProductConfig,
17
18
  HiConstants,
18
19
  create_dataset_variables,
19
20
  full_dataarray,
21
+ iter_background_events_by_config,
20
22
  iter_qualified_events_by_config,
21
23
  parse_sensor_number,
22
24
  )
@@ -44,6 +46,7 @@ def hi_l1c(
44
46
  de_dataset: xr.Dataset,
45
47
  calibration_prod_config_path: Path,
46
48
  goodtimes_ds: xr.Dataset,
49
+ background_config_path: Path,
47
50
  ) -> list[xr.Dataset]:
48
51
  """
49
52
  High level IMAP-Hi l1c processing function.
@@ -56,6 +59,8 @@ def hi_l1c(
56
59
  Calibration product configuration file.
57
60
  goodtimes_ds : xarray.Dataset
58
61
  Goodtimes dataset with cull_flags.
62
+ background_config_path : pathlib.Path
63
+ Background configuration file.
59
64
 
60
65
  Returns
61
66
  -------
@@ -65,7 +70,7 @@ def hi_l1c(
65
70
  logger.info("Running Hi l1c processing")
66
71
 
67
72
  l1c_dataset = generate_pset_dataset(
68
- de_dataset, calibration_prod_config_path, goodtimes_ds
73
+ de_dataset, calibration_prod_config_path, goodtimes_ds, background_config_path
69
74
  )
70
75
 
71
76
  return [l1c_dataset]
@@ -75,6 +80,7 @@ def generate_pset_dataset(
75
80
  de_dataset: xr.Dataset,
76
81
  calibration_prod_config_path: Path,
77
82
  goodtimes_ds: xr.Dataset,
83
+ background_config_path: Path,
78
84
  ) -> xr.Dataset:
79
85
  """
80
86
  Generate IMAP-Hi l1c pset xarray dataset from l1b product.
@@ -87,6 +93,8 @@ def generate_pset_dataset(
87
93
  Calibration product configuration file.
88
94
  goodtimes_ds : xarray.Dataset
89
95
  Goodtimes dataset with cull_flags.
96
+ background_config_path : pathlib.Path
97
+ Background configuration file.
90
98
 
91
99
  Returns
92
100
  -------
@@ -100,6 +108,8 @@ def generate_pset_dataset(
100
108
  logical_source_parts = parse_filename_like(de_dataset.attrs["Logical_source"])
101
109
  # read calibration product configuration file
102
110
  config_df = CalibrationProductConfig.from_csv(calibration_prod_config_path)
111
+ # read background configuration file
112
+ background_df = BackgroundConfig.from_csv(background_config_path)
103
113
 
104
114
  pset_dataset = empty_pset_dataset(
105
115
  de_dataset.ccsds_met.data.mean(),
@@ -119,8 +129,17 @@ def generate_pset_dataset(
119
129
  )
120
130
  # Calculate and add the exposure time to the pset_dataset
121
131
  pset_dataset.update(pset_exposure(pset_dataset.coords, de_dataset, goodtimes_ds))
122
- # Get the backgrounds
123
- pset_dataset.update(pset_backgrounds(pset_dataset.coords))
132
+
133
+ # Compute backgrounds (background counts computed internally)
134
+ pset_dataset.update(
135
+ pset_backgrounds(
136
+ pset_dataset.coords,
137
+ background_df,
138
+ de_dataset,
139
+ goodtimes_ds,
140
+ pset_dataset["exposure_times"],
141
+ )
142
+ )
124
143
 
125
144
  return pset_dataset
126
145
 
@@ -347,10 +366,9 @@ def pset_counts(
347
366
  Returns
348
367
  -------
349
368
  dict[str, xarray.DataArray]
350
- Dictionary containing new exposure_times DataArray to be added to the PSET
351
- dataset.
369
+ Dictionary containing counts DataArray.
352
370
  """
353
- # Generate exposure time variable filled with zeros
371
+ # Generate counts variable filled with zeros
354
372
  counts_var = create_dataset_variables(
355
373
  ["counts"],
356
374
  coords=pset_coords,
@@ -373,12 +391,6 @@ def pset_counts(
373
391
  good_mask = de_ds["trigger_id"].data != de_ds["trigger_id"].attrs["FILLVAL"]
374
392
  if not np.any(good_mask):
375
393
  return counts_var
376
- elif not np.all(good_mask):
377
- raise ValueError(
378
- "An event with trigger_id=FILLVAL should only occur for a pointing "
379
- "with no events that gets a single fill event. Events with mixed "
380
- "valid and FILLVAL trigger_ids found."
381
- )
382
394
 
383
395
  # Remove DEs not in Goodtimes/angles
384
396
  # For direct events, use nominal_bin (spacecraft spin bin 0-89) to look up goodtimes
@@ -417,43 +429,230 @@ def pset_counts(
417
429
  spin_bin_indices,
418
430
  1,
419
431
  )
432
+
420
433
  return counts_var
421
434
 
422
435
 
423
- def pset_backgrounds(pset_coords: dict[str, xr.DataArray]) -> dict[str, xr.DataArray]:
436
+ def _compute_background_counts(
437
+ pset_coords: dict[str, xr.DataArray],
438
+ background_config_df: pd.DataFrame,
439
+ l1b_de_dataset: xr.Dataset,
440
+ goodtimes_ds: xr.Dataset,
441
+ ) -> xr.DataArray:
424
442
  """
425
- Calculate pointing set backgrounds and background uncertainties.
443
+ Compute background counts by filtering and binning direct events.
444
+
445
+ Background counts are computed across all esa_energy_steps and spin_angle_bins
446
+ since backgrounds are isotropic and do not depend on ESA energy step or spin angle.
426
447
 
427
448
  Parameters
428
449
  ----------
429
450
  pset_coords : dict[str, xarray.DataArray]
430
451
  The PSET coordinates from the xarray.Dataset.
452
+ background_config_df : pandas.DataFrame
453
+ Background configuration DataFrame with MultiIndex
454
+ (calibration_prod, background_index).
455
+ l1b_de_dataset : xarray.Dataset
456
+ The L1B dataset for the pointing being processed.
457
+ goodtimes_ds : xarray.Dataset
458
+ Goodtimes dataset with cull_flags.
459
+
460
+ Returns
461
+ -------
462
+ xarray.DataArray
463
+ Background counts with dims (epoch, calibration_prod, background_index).
464
+ """
465
+ # Create background_counts as xarray DataArray with proper coordinates
466
+ # Note: esa_energy_step and spin_angle_bin are NOT included since backgrounds
467
+ # are isotropic and computed across all ESA steps and spin angles
468
+ background_indices = (
469
+ background_config_df.index.get_level_values("background_index")
470
+ .unique()
471
+ .sort_values()
472
+ .values
473
+ )
474
+
475
+ bg_coords = {
476
+ "epoch": pset_coords["epoch"],
477
+ "calibration_prod": pset_coords["calibration_prod"],
478
+ "background_index": background_indices,
479
+ }
480
+
481
+ background_counts = xr.DataArray(
482
+ np.zeros(
483
+ (
484
+ len(bg_coords["epoch"]),
485
+ len(bg_coords["calibration_prod"]),
486
+ len(bg_coords["background_index"]),
487
+ ),
488
+ ),
489
+ dims=[
490
+ "epoch",
491
+ "calibration_prod",
492
+ "background_index",
493
+ ],
494
+ coords=bg_coords,
495
+ )
496
+
497
+ # Process direct events
498
+ de_ds = l1b_de_dataset.drop_dims("epoch")
499
+
500
+ good_mask = de_ds["trigger_id"].data != de_ds["trigger_id"].attrs["FILLVAL"]
501
+ if not np.any(good_mask):
502
+ return background_counts
503
+
504
+ # Remove DEs not in Goodtimes/angles
505
+ goodtimes_mask = good_time_and_phase_mask(
506
+ de_ds.event_met.values,
507
+ de_ds.nominal_bin.values,
508
+ goodtimes_ds,
509
+ )
510
+ de_ds = de_ds.isel(event_met=goodtimes_mask)
511
+
512
+ n_events = len(de_ds["event_met"])
513
+ if n_events == 0:
514
+ return background_counts
515
+
516
+ for cal_prod in pset_coords["calibration_prod"].values:
517
+ # Check that cal_prod exists in background_config_df
518
+ if cal_prod not in background_config_df.index.get_level_values(
519
+ "calibration_prod"
520
+ ):
521
+ raise ValueError(
522
+ f"Calibration product {cal_prod} not found in background "
523
+ f"configuration. Available calibration products: "
524
+ f"{sorted(background_config_df.index.get_level_values('calibration_prod').unique().tolist())}"
525
+ )
526
+
527
+ # Take a cross-section of the background configuration DataFrame
528
+ # to get rows relevant to the current calibration product
529
+ cal_prod_rows = background_config_df.xs(cal_prod, level="calibration_prod")
530
+
531
+ # Use iter_background_events_by_config to get filtered events
532
+ for config_row, filtered_de_ds in iter_background_events_by_config(
533
+ de_ds, cal_prod_rows
534
+ ):
535
+ background_idx = config_row.Index
536
+
537
+ if len(filtered_de_ds["event_met"]) == 0:
538
+ continue
539
+
540
+ # Count all filtered events
541
+ # (no binning by spin angle since backgrounds are isotropic)
542
+ count = len(filtered_de_ds["event_met"])
543
+
544
+ background_counts.loc[
545
+ dict(
546
+ epoch=pset_coords["epoch"].values[0],
547
+ calibration_prod=cal_prod,
548
+ background_index=background_idx,
549
+ )
550
+ ] += count
551
+
552
+ return background_counts
553
+
554
+
555
+ def pset_backgrounds(
556
+ pset_coords: dict[str, xr.DataArray],
557
+ background_config_df: pd.DataFrame,
558
+ l1b_de_dataset: xr.Dataset,
559
+ goodtimes_ds: xr.Dataset,
560
+ exposure_times: xr.DataArray,
561
+ ) -> dict[str, xr.DataArray]:
562
+ """
563
+ Calculate pointing set backgrounds from direct events.
564
+
565
+ Computes background counts internally by filtering and binning events
566
+ according to the background configuration, then calculates background
567
+ rates and uncertainties.
568
+
569
+ Parameters
570
+ ----------
571
+ pset_coords : dict[str, xarray.DataArray]
572
+ The PSET coordinates from the xarray.Dataset.
573
+ background_config_df : pandas.DataFrame
574
+ Background configuration DataFrame with MultiIndex
575
+ (calibration_prod, background_index).
576
+ l1b_de_dataset : xarray.Dataset
577
+ The L1B dataset for the pointing being processed.
578
+ goodtimes_ds : xarray.Dataset
579
+ Goodtimes dataset with cull_flags.
580
+ exposure_times : xarray.DataArray
581
+ Exposure times with dims (epoch, esa_energy_step, spin_angle_bin).
431
582
 
432
583
  Returns
433
584
  -------
434
585
  dict[str, xarray.DataArray]
435
- Dictionary containing background_rates and background_rates_unc DataArrays
436
- to be added to the PSET dataset.
586
+ Dictionary containing background_rates and background_rates_uncertainty
587
+ DataArrays to be added to the PSET dataset.
437
588
  """
438
- # TODO: This is just a placeholder setting backgrounds to zero. The background
439
- # algorithm will be determined in flight.
440
589
  attr_mgr = ImapCdfAttributes()
441
590
  attr_mgr.add_instrument_global_attrs("hi")
442
591
  attr_mgr.add_instrument_variable_attrs(instrument="hi", level=None)
443
592
 
444
- return {
593
+ # Create output arrays
594
+ output_vars = {
445
595
  var_name: full_dataarray(
446
596
  var_name,
447
597
  attr_mgr.get_variable_attributes(f"hi_pset_{var_name}", check_schema=False),
448
598
  pset_coords,
449
- fill_value=fill_val,
450
599
  )
451
- for var_name, fill_val in [
452
- ("background_rates", 0),
453
- ("background_rates_uncertainty", 1),
454
- ]
600
+ for var_name in ["background_rates", "background_rates_uncertainty"]
455
601
  }
456
602
 
603
+ # Get total exposure time
604
+ total_exposure_time = float(exposure_times.sum())
605
+
606
+ if total_exposure_time <= 0:
607
+ output_vars["background_rates"].values[:] = 0
608
+ output_vars["background_rates_uncertainty"].values[:] = 0
609
+ return output_vars
610
+
611
+ # Compute background counts: shape (epoch, calibration_prod, background_index)
612
+ background_counts = _compute_background_counts(
613
+ pset_coords, background_config_df, l1b_de_dataset, goodtimes_ds
614
+ )
615
+
616
+ # Compute count rates: shape (epoch, calibration_prod, background_index)
617
+ count_rates = background_counts / total_exposure_time
618
+
619
+ # Convert background config DataFrame to xarray Dataset
620
+ config_ds = background_config_df.to_xarray()
621
+ if not config_ds["calibration_prod"].equals(pset_coords["calibration_prod"]):
622
+ raise ValueError(
623
+ f"Calibration products in pset_coords and background_config_df "
624
+ f"do not match. pset_coords: {pset_coords['calibration_prod'].values}, "
625
+ f"background_config_df: {config_ds['calibration_prod'].values}"
626
+ )
627
+ scaling_factors_da = config_ds["scaling_factor"]
628
+ uncertainties_da = config_ds["uncertainty"]
629
+
630
+ # Compute scaled rates
631
+ scaled_rates = count_rates * scaling_factors_da
632
+
633
+ # Compute uncertainties (Poisson + scaling factor, combined in quadrature)
634
+ poisson_unc = (
635
+ np.sqrt(background_counts) / total_exposure_time
636
+ ) * scaling_factors_da
637
+ scaling_unc = count_rates * uncertainties_da
638
+ combined_unc = np.sqrt(poisson_unc**2 + scaling_unc**2)
639
+
640
+ # Sum over background_index dimension to get final rates
641
+ total_rates = scaled_rates.sum(dim="background_index", skipna=True)
642
+ total_unc = np.sqrt((combined_unc**2).sum(dim="background_index", skipna=True))
643
+
644
+ # Broadcast to (epoch, esa_energy_step, calibration_prod, spin_angle_bin)
645
+ # Backgrounds are isotropic and independent of ESA step, so we
646
+ # broadcast across esa_energy_step and spin_angle_bin dimensions.
647
+ output_vars["background_rates"].values[:] = total_rates.values[
648
+ :, np.newaxis, :, np.newaxis
649
+ ]
650
+ output_vars["background_rates_uncertainty"].values[:] = total_unc.values[
651
+ :, np.newaxis, :, np.newaxis
652
+ ]
653
+
654
+ return output_vars
655
+
457
656
 
458
657
  def pset_exposure(
459
658
  pset_coords: dict[str, xr.DataArray],