Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial CoDICE L1A Processing Algorithm #288

Merged
merged 17 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
ee9d48f
Renamed and moved files around to be more consistent and avoid duplic…
bourque Nov 28, 2023
fa50e8e
Updates to reflect changes in module/function names and reorg; update…
bourque Nov 28, 2023
a9388f6
Initial commit of codice l1a processing code
bourque Nov 28, 2023
2b2ecf4
Updated codice API reference docs to include new L1a processing and r…
bourque Nov 28, 2023
a9868db
Renamed and moved files around to be more consistent and avoid duplic…
bourque Nov 28, 2023
58aa174
Updates to reflect changes in module/function names and reorg; update…
bourque Nov 28, 2023
8212e48
Initial commit of codice l1a processing code
bourque Nov 28, 2023
049e293
Updated codice API reference docs to include new L1a processing and r…
bourque Nov 28, 2023
e9a65b2
Merge branch 'initial-codice-l1a' of github.com:bourque/imap_processi…
bourque Nov 29, 2023
ca8f872
Added parameter for CDF directory as to avoid hardcoding a path to wr…
bourque Nov 29, 2023
fd0b337
Added typing and updated some docstrings
bourque Nov 29, 2023
43c24fe
Some more reorganization and renaming of files
bourque Nov 29, 2023
9e210e1
Updates for code review suggestions; fixed some typos, now using pyte…
bourque Nov 29, 2023
03d6581
Updated CoDICE API reference docs to reflect new organization of files
bourque Nov 29, 2023
c9e8c5e
Added new configuration items to ignore some specific warnings
bourque Nov 30, 2023
7d0e974
Added -W --keep-going -n flags to Makefile so that developers do not …
bourque Nov 30, 2023
71649b0
Implemented code review suggestions; removed placeholder for EU conve…
bourque Nov 30, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions docs/source/reference/codice.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,24 @@ CoDICE (Compact Dual Ion Composition Experiment)
This is the CoDICE Instrument module, which contains the code for processing
data from the CoDICE instrument.

The L0 code to decommutate the CCSDS packet data can be found below:
The processing code to decommutate the CCSDS packets (L0) and create L1a data
products can be found below:

.. autosummary::
:toctree: generated/
:template: autosummary.rst
:recursive:

l0.decom_codice
codice_l0
codice_l1a

The code below is used to decompress an 8 bit science value to a 24- or 32-bit
uncompressed value:
The modules below contain various utility classes and functions to support L0
and L1a processing:

.. autosummary::
:toctree: generated/
:template: autosummary.rst
:recursive:

l0.decompress_codice
utils.codice_utils
utils.decompress
5 changes: 4 additions & 1 deletion imap_processing/cdf/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ def write_cdf(
file_start_date = None
if "idex" in data.attrs["Logical_source"]:
file_start_date = data["Epoch"][0].data
elif "swe" in data.attrs["Logical_source"]:
elif (
"swe" in data.attrs["Logical_source"]
or "codice" in data.attrs["Logical_source"]
):
start_time = data["Epoch"].data[0]
file_start_date = calc_start_time(start_time)
if file_start_date is None:
Expand Down
1 change: 1 addition & 0 deletions imap_processing/codice/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "01"
116 changes: 116 additions & 0 deletions imap_processing/codice/codice_cdf_attrs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
"""CDF attrs for CoDICE.

This website provides information about what variables are required and what
their value should be:

https://spdf.gsfc.nasa.gov/istp_guide/istp_guide.html

For further details, see the documentation provided at
https://imap-processing.readthedocs.io/en/latest/development/CDFs/cdf_requirements.html
"""


from imap_processing.cdf.defaults import GlobalConstants
from imap_processing.cdf.global_attrs import (
AttrBase,
GlobalDataLevelAttrs,
GlobalInstrumentAttrs,
ScienceAttrs,
StringAttrs,
)
from imap_processing.codice import __version__

descriptor = "CoDICE>Compact Dual Ion Composition Experiment"
codice_description_text = (
"The Compact Dual Ion Composition Experiment (CoDICE) will measure the "
"distributions and composition of interstellar pickup ions(PUIs), "
"particles that make it through the heliosheath into the heliosphere. "
"CoDICE also collects and characterizes solar wind ions including the "
"mass and composition of highly energized particles (called suprathermal) "
"from the Sun.CoDICE combines an electrostatic analyzer(ESA) with a "
"Time-Of-Flight versus Energy (TOF / E) subsystem to simultaneously "
"measure the velocity, arrival direction, ionic charge state, and mass of "
"specific species of ions in the LISM.CoDICE also has a path for higher "
"energy particles to skip the ESA but still get measured by the common "
"TOF / E systm.These measurements are critical in determining the Local "
"Interstellar Medium (LISM) composition and flow properties, the origin of "
"the enigmatic suprathermal tails on the solar wind distributions and "
"advance understanding of the acceleration of particles in the heliosphere."
)

codice_base = GlobalInstrumentAttrs(
version=__version__, descriptor=descriptor, text=codice_description_text
)

codice_l1a_global_attrs = GlobalDataLevelAttrs(
data_type="L1A->Level-1A",
logical_source="imap_codice_l1a",
logical_source_desc="IMAP Mission CoDICE Instrument Level-1A Data",
instrument_base=codice_base,
)

codice_l1b_global_attrs = GlobalDataLevelAttrs(
data_type="L1B->Level-1B",
logical_source="imap_cpdice_l1b",
logical_source_desc="IMAP Mission CoDICE Instrument Level-1B Data",
instrument_base=codice_base,
)

int_base = AttrBase(
validmin=0,
validmax=GlobalConstants.INT_MAXVAL,
format="I12",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, do we care that the maxval is a 64-bit signed integer, but we have only 12 digits of representation in the format?

INT_MAXVAL = np.iinfo(np.int64).max

var_type="support_data",
display_type="no_plot",
)

float_base = AttrBase(
validmin=0,
validmax=GlobalConstants.INT_MAXVAL,
format="I12",
var_type="support_data",
display_type="no_plot",
)

string_base = StringAttrs(
depend_0="Epoch",
)

codice_metadata_attrs = ScienceAttrs(
validmin=0,
validmax=GlobalConstants.INT_MAXVAL,
display_type="no_plot",
depend_0="Epoch",
format="I12",
units="dN",
var_type="support_data",
variable_purpose="PRIMARY",
)

# TODO: ask CoDICE team about valid min and max values of these data
l1a_science_attrs = ScienceAttrs(
validmin=0,
validmax=GlobalConstants.INT_MAXVAL,
display_type="spectrogram",
depend_0="Epoch",
depend_1="Energy",
depend_2="Counts",
format="I12",
units="dN",
var_type="data",
variable_purpose="PRIMARY",
)

l1b_science_attrs = ScienceAttrs(
validmin=0,
validmax=GlobalConstants.INT_MAXVAL,
display_type="spectrogram",
depend_0="Epoch",
depend_1="Energy",
depend_2="Angle",
depend_3="Rates",
format="I12",
units="dN",
var_type="data",
variable_purpose="PRIMARY",
)
35 changes: 35 additions & 0 deletions imap_processing/codice/codice_l0.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""Perform CoDICE L0 processing.

This module contains a function to decommutate CoDICE CCSDS packets using
XTCE packet definitions.

For more information on this process and the latest versions of the packet
definitions, see https://lasp.colorado.edu/galaxy/display/IMAP/CoDICE.

Use
---

from imap_processing.codice.codice_l0 import decom_packets
packet_file = '/path/to/raw_ccsds_20230822_122700Z_idle.bin'
xtce_document = '/path/to/P_COD_NHK.xml'
packet_list = decom_packets(packet_file, xtce_document)
"""

from imap_processing import decom, imap_module_directory


def decom_packets(packet_file: str):
"""Decom CoDICE data packets using CoDICE packet definition.

Parameters
----------
packet_file : str
Path to data packet path with filename.

Returns
-------
list : list
all the unpacked data.
"""
xtce_document = f"{imap_module_directory}/codice/packet_definitions/P_COD_NHK.xml"
return decom.decom_packets(packet_file, xtce_document)
51 changes: 51 additions & 0 deletions imap_processing/codice/codice_l1a.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""Perform CoDICE l1a processing.

This module contains functions to process decommutated CoDICE packets and create
L1a data products.

Use
---

from imap_processing.codice.codice_l0 import decom_packets
from imap_processing.codice.codice_l1a import codice_l1a
packets = decom_packets(packet_file, xtce_document)
cdf_filename = codice_l1a(packets)
"""

from imap_processing.cdf.utils import write_cdf
from imap_processing.codice.utils.codice_utils import CODICEAPID, create_dataset
from imap_processing.utils import group_by_apid, sort_by_time


def codice_l1a(packets):
"""Process CoDICE l0 data to create l1a data products.

Parameters
----------
packets : list
Decom data list that contains all APIDs

Returns
-------
cdf_filename : str
The path to the CDF file that was created
"""
# Group data by APID and sort by time
grouped_data = group_by_apid(packets)

for apid in grouped_data.keys():
if apid == CODICEAPID.COD_NHK:
sorted_packets = sort_by_time(grouped_data[apid], "SHCOARSE")
data = create_dataset(packets=sorted_packets)
else:
pass

# Write data to CDF
cdf_filename = write_cdf(
data,
mode="",
description="hk",
directory="/Users/mabo8927/Desktop/repositories/imap_processing/imap_processing/codice/tests/data/",
)

return cdf_filename
Empty file.
18 changes: 0 additions & 18 deletions imap_processing/codice/l0/decom_codice.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@
import pytest

from imap_processing import imap_module_directory
from imap_processing.codice.l0 import decom_codice
from imap_processing.codice import codice_l0


@pytest.fixture(scope="session")
def decom_test_data():
"""Read test data from file"""

packet_file = Path(
f"{imap_module_directory}/codice/tests/data/"
f"raw_ccsds_20230822_122700Z_idle.bin"
)
Path(f"{imap_module_directory}/codice/packet_definitions/P_COD_NHK.xml")
data_packet_list = decom_codice.decom_packets(packet_file)
data_packet_list = codice_l0.decom_packets(packet_file)
data_packet_list = [
packet
for packet in data_packet_list
Expand Down Expand Up @@ -81,16 +82,19 @@ def test_housekeeping_data(decom_test_data, validation_data):

def test_total_packets_in_data_file(decom_test_data):
"""Test if total packets in data file is correct"""

total_packets = 99
assert len(decom_test_data) == total_packets


def test_ways_to_get_data(decom_test_data):
"""Test if data can be retrieved using different ways"""

# First way to get data
data_value_using_key = decom_test_data[0].data

# Second way to get data
data_value_using_list = decom_test_data[0][1]

# Check if data is same
assert data_value_using_key == data_value_using_list
33 changes: 33 additions & 0 deletions imap_processing/codice/tests/test_codice_l1a.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""Tests the L1a processing for decommutated CoDICE data"""

from pathlib import Path

import pytest

from imap_processing import imap_module_directory
from imap_processing.codice.codice_l0 import decom_packets
from imap_processing.codice.codice_l1a import codice_l1a


@pytest.fixture(scope="session")
def l0_test_data():
"""Decom some packets to be used for testing"""
packet_file = Path(
f"{imap_module_directory}/codice/tests/data/"
f"raw_ccsds_20230822_122700Z_idle.bin"
)
packets = decom_packets(packet_file)

return packets


def test_codice_l1a(l0_test_data):
"""Tests the ``codice_l1a`` function and ensured that a proper CDF file
was created"""

cdf_filename = codice_l1a(l0_test_data)

assert Path(cdf_filename).name == "imap_codice_l1a_hk_20100101_v01.cdf"

# Remove the test data
Path(cdf_filename).unlink()
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

import pytest

from imap_processing.codice.l0.decompress_codice import decompress
from imap_processing.codice.utils.codice_utils import CoDICECompression
from imap_processing.codice.utils.decompress import decompress

# Test the algorithms using input value of 234 (picked randomly)
LZMA_EXAMPLE = lzma.compress((234).to_bytes(1, byteorder="big"))
Expand Down
Loading