From 0d94a347ee3446e0c772c808e708fa90e661c306 Mon Sep 17 00:00:00 2001 From: Jon Niehof Date: Tue, 17 Feb 2026 13:57:05 -0700 Subject: [PATCH 1/3] JNIE - Populate map variable CATDESC based on descriptor. --- imap_l3_processing/cdf/cdf_utils.py | 14 ++++++++++++ tests/cdf/test_cdf_utils.py | 33 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/imap_l3_processing/cdf/cdf_utils.py b/imap_l3_processing/cdf/cdf_utils.py index 920c991b..24c857cd 100644 --- a/imap_l3_processing/cdf/cdf_utils.py +++ b/imap_l3_processing/cdf/cdf_utils.py @@ -4,6 +4,7 @@ from spacepy import pycdf from spacepy.pycdf import CDF +from imap_processing.ena_maps.utils import naming from imap_l3_processing.cdf.imap_attribute_manager import ImapAttributeManager from imap_l3_processing.swapi.l3a.models import DataProduct @@ -26,6 +27,19 @@ def write_cdf(file_path: str, data: DataProduct, attribute_manager: ImapAttribut data_type = getattr(pycdf.const, variable_attributes["DATA_TYPE"]) data_array = np.asanyarray(data_product.value) + possible_principal_data = ( + "dust_rate", + "ena_intensity", + "ena_spectral_index", + "glows_rate", + "isn_rate", + "isn_rate_bg_subtracted", + ) + if var_name in possible_principal_data: + descriptor = data.input_metadata.descriptor + catdesc = naming.MapDescriptor.from_string(descriptor).to_catdesc() + variable_attributes["CATDESC"] = catdesc + record_varying = variable_attributes["RECORD_VARYING"].lower() == "rv" if record_varying: dims = data_array.shape[1:] diff --git a/tests/cdf/test_cdf_utils.py b/tests/cdf/test_cdf_utils.py index 1b1ed3d2..101070bd 100644 --- a/tests/cdf/test_cdf_utils.py +++ b/tests/cdf/test_cdf_utils.py @@ -294,6 +294,39 @@ def test_read_variable_replaces_fill_values_with_nan(self): np.testing.assert_equal(data, np.array([1, 2, np.nan, 4, 5])) np.testing.assert_equal(int_data, np.array([1, 2, 3, 4, np.nan])) + def test_write_map_cdf(self): + class TestMapDataProduct(DataProduct): + def __init__(self): + self.input_metadata = InputMetadata("hi", "l3", datetime(year=2025, month=1, day=1), + datetime(year=2025, month=5, day=31), "v001", + "h45-ena-h-sf-sp-ram-hae-6deg-6mo") + self.parent_file_names = [] + + def to_data_product_variables(self) -> list[DataProductVariable]: + return [ + DataProductVariable("ena_intensity", np.arange(0, 10)), + ] + path = str(self.temp_directory / "write_cdf.cdf") + data = TestMapDataProduct() + ena_intensity, = data.to_data_product_variables() + attribute_manager = Mock(spec=ImapAttributeManager) + attribute_manager.get_global_attributes.return_value = {"global1": "global_val1", "global2": "global_val2"} + attribute_manager.get_variable_attributes.side_effect = [ + {"CATDESC": "This should be ignored", "DATA_TYPE": "CDF_REAL4", "FILLVAL": -1e31, "RECORD_VARYING": "rV"}, + ] + + write_cdf(path, data, attribute_manager) + + expected_data_product_logical_source = "imap_hi_l3_h45-ena-h-sf-sp-ram-hae-6deg-6mo" + attribute_manager.get_global_attributes.assert_called_once_with(expected_data_product_logical_source) + attribute_manager.get_variable_attributes.assert_has_calls( + [call(var.name) for var in data.to_data_product_variables()] + ) + + with pycdf.CDF(path) as actual_cdf: + self.assertEqual("IMAP Hi45 Inten H, HAE SC Frame, Surv Corr, Ram, 6 deg, 6 Mon", + actual_cdf['ena_intensity'].attrs['CATDESC']) + class TestDataProduct(DataProduct): def __init__(self): From 92ce3d086d2a8b4a54b707c7a39d37e8972ab58e Mon Sep 17 00:00:00 2001 From: Jon Niehof Date: Tue, 17 Feb 2026 14:38:24 -0700 Subject: [PATCH 2/3] JNIE - Updated expcted map CATDESC based on IMWG feedback --- tests/cdf/test_cdf_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cdf/test_cdf_utils.py b/tests/cdf/test_cdf_utils.py index 101070bd..6f62c8e2 100644 --- a/tests/cdf/test_cdf_utils.py +++ b/tests/cdf/test_cdf_utils.py @@ -324,7 +324,7 @@ def to_data_product_variables(self) -> list[DataProductVariable]: ) with pycdf.CDF(path) as actual_cdf: - self.assertEqual("IMAP Hi45 Inten H, HAE SC Frame, Surv Corr, Ram, 6 deg, 6 Mon", + self.assertEqual("IMAP Hi45 H Inten, HAE SC Frame, Surv Corr, Ram, 6 deg, 6 Mon", actual_cdf['ena_intensity'].attrs['CATDESC']) From 9e062456652362b80275bc1a3a094ebfef628c24 Mon Sep 17 00:00:00 2001 From: Jon Niehof Date: Wed, 18 Feb 2026 13:42:50 -0700 Subject: [PATCH 3/3] JNIE - Identify principal variables from new L2 code --- imap_l3_processing/cdf/cdf_utils.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/imap_l3_processing/cdf/cdf_utils.py b/imap_l3_processing/cdf/cdf_utils.py index 24c857cd..edfcf560 100644 --- a/imap_l3_processing/cdf/cdf_utils.py +++ b/imap_l3_processing/cdf/cdf_utils.py @@ -21,24 +21,23 @@ def write_cdf(file_path: str, data: DataProduct, attribute_manager: ImapAttribut for k, v in global_attrs.items(): cdf.attrs[k] = v + map_descriptor = None + if data.input_metadata.instrument in ("lo", "hi", "ultra", "glows",): + try: + map_descriptor = naming.MapDescriptor.from_string(data.input_metadata.descriptor) + except ValueError: + # Assume this is not actually a map + pass + for data_product in data.to_data_product_variables(): var_name = data_product.name variable_attributes = attribute_manager.get_variable_attributes(var_name) data_type = getattr(pycdf.const, variable_attributes["DATA_TYPE"]) data_array = np.asanyarray(data_product.value) - possible_principal_data = ( - "dust_rate", - "ena_intensity", - "ena_spectral_index", - "glows_rate", - "isn_rate", - "isn_rate_bg_subtracted", - ) - if var_name in possible_principal_data: - descriptor = data.input_metadata.descriptor - catdesc = naming.MapDescriptor.from_string(descriptor).to_catdesc() - variable_attributes["CATDESC"] = catdesc + if (map_descriptor is not None + and var_name == map_descriptor.principal_data_var): + variable_attributes["CATDESC"] = map_descriptor.to_catdesc() record_varying = variable_attributes["RECORD_VARYING"].lower() == "rv" if record_varying: