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

HIT housekeeping data class #342

Merged
merged 14 commits into from
Feb 19, 2024
4 changes: 3 additions & 1 deletion docs/source/code-documentation/hit.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ The L0 code to decommutate the CCSDS packet data can be found below.
:template: autosummary.rst
:recursive:

l0.hit_l1a_decom
l0.data_classes
l0.utils
l0.hit_l1a_decom.py
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the extra .py might be causing the doc build failure.

Suggested change
l0.hit_l1a_decom.py
l0.hit_l1a_decom

219 changes: 219 additions & 0 deletions imap_processing/hit/l0/data_classes/housekeeping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
"""L1A HIT Housekeeping data class."""
from dataclasses import dataclass
import bitstring
import numpy as np
from imap_processing.ccsds.ccsds_data import CcsdsData
from imap_processing.hit.l0.utils.hit_base import HITBase

@dataclass
class Housekeeping(HITBase):
"""L1A HIT Housekeeping data.

The HIT Housekeeping data class handles the decommutation
and parsing of L0 to L1A data.

Attributes
----------
SHCOARSE : int
Spacecraft time.
MODE : int
Mode (0=boot, 1=maint, 2=stdby, 3=science)
FSW_VERSION_A : int
FSW version number (A.B.C bits)
FSW_VERSION_B : int
FSW version number (A.B.C bits)
FSW_VERSION_C : int
FSW version number (A.B.C bits)
NUM_GOOD_CMDS : int
Number of good commands
LAST_GOOD_CMD : int
Last good command
LAST_GOOD_SEQ_NUM : int
Last good sequence number
NUM_BAD_CMDS : int
Number of bad commands
LAST_BAD_CMD : int
Last bad command
LAST_BAD_SEQ_NUM : int
Last bad sequence number
FEE_RUNNING : int
FEE running (1) or reset (0)
MRAM_DISABLED : int
MRAM disabled (1) or enabled (0)
ENABLE_50KHZ : int
50kHz enabled (1) or disabled (0)
ENABLE_HVPS : int
HVPS enabled (1) or disabled (0)
TABLE_STATUS : int
Table status OK (1) or error (0)
HEATER_CONTROL : int
Heater control (0=none, 1=pri, 2=sec)
ADC_MODE : int
ADC mode (0=quiet, 1=normal, 2=adcstim, 3=adcThreshold?)
DYN_THRESH_LVL : int
Dynamic threshold level (0-3)
NUM_EVNT_LAST_HK : int
Number of events since last HK update
NUM_ERRORS : int
Number of errors
LAST_ERROR_NUM : int
Last error number
CODE_CHECKSUM : int
Code checksum
SPIN_PERIOD_SHORT : int
Spin period at t=0
SPIN_PERIOD_LONG : int
Spin period at t=0
LEAK_I_RAW : str
Raw binary for Leakage current [V]
LEAK_I : np.ndarray
Leakage currents [V] formatted as (64, 1) array
PHASIC_STAT : int
PHASIC status
ACTIVE_HEATER : int
Active heater
HEATER_ON : int
Heater on/off
TEST_PULSER_ON : int
Test pulser on/off
DAC0_ENABLE : int
DAC_0 enable
DAC1_ENABLE : int
DAC_1 enable
PREAMP_L234A : int
Preamp L234A
PREAMP_L1A : int
Preamp L1A
PREAMP_L1B : int
Preamp L1B
PREAMP_L234B : int
Preamp L234B
TEMP0 : int
FEE LDO Regulator
TEMP1 : int
Primary Heater
TEMP2 : int
FEE FPGA
TEMP3 : int
Secondary Heater
ANALOG_TEMP : int
Chassis temp
HVPS_TEMP : int
Board temp
IDPU_TEMP : int
LDO Temp
LVPS_TEMP : int
Board temp
EBOX_3D4VD : int
3.4VD Ebox (digital)
EBOX_5D1VD : int
5.1VD Ebox (digital)
EBOX_P12VA : int
+12VA Ebox (analog)
EBOX_M12VA : int
-12VA Ebox (analog)
EBOX_P5D7VA : int
+5.7VA Ebox (analog)
EBOX_M5D7VA : int
-5.7VA Ebox (analog)
REF_P5V : int
+5Vref
L1AB_BIAS : int
L1A/B Bias
L2AB_BIAS : int
L2A/B Bias
L34A_BIAS : int
L3/4A Bias
L34B_BIAS : int
L3/4B Bias
EBOX_P2D0VD : int
+2.0VD Ebox (digital)

Methods
-------
__init__(packet, software_vesion, packet_file_name):
Uses the CCSDS packet, version of the software, and
the name of the packet file to parse and store information about
the Houskeeping packet data.
_parse_leak():
Parse each current leakage field and put into an array.

"""
SHCOARSE: int
MODE: int
FSW_VERSION_A: int
FSW_VERSION_B: int
FSW_VERSION_C: int
NUM_GOOD_CMDS: int
LAST_GOOD_CMD: int
LAST_GOOD_SEQ_NUM: int
NUM_BAD_CMDS: int
LAST_BAD_CMD: int
LAST_BAD_SEQ_NUM: int
FEE_RUNNING: int
MRAM_DISABLED: int
ENABLE_50KHZ: int
ENABLE_HVPS: int
TABLE_STATUS: int
HEATER_CONTROL: int
ADC_MODE: int
DYN_THRESH_LVL: int
NUM_EVNT_LAST_HK: int
NUM_ERRORS: int
LAST_ERROR_NUM: int
CODE_CHECKSUM: int
SPIN_PERIOD_SHORT: int
SPIN_PERIOD_LONG: int
LEAK_I_RAW: str
LEAK_I: np.ndarray
PHASIC_STAT: int
ACTIVE_HEATER: int
HEATER_ON: int
TEST_PULSER_ON: int
DAC0_ENABLE: int
DAC1_ENABLE: int
PREAMP_L234A: int
PREAMP_L1A: int
PREAMP_L1B: int
PREAMP_L234B: int
TEMP0: int
TEMP1: int
TEMP2: int
TEMP3: int
ANALOG_TEMP: int
HVPS_TEMP: int
IDPU_TEMP: int
LVPS_TEMP: int
EBOX_3D4VD: int
EBOX_5D1VD: int
EBOX_P12VA: int
EBOX_M12VA: int
EBOX_P5D7VA: int
EBOX_M5D7VA: int
REF_P5V: int
L1AB_BIAS: int
L2AB_BIAS: int
L34A_BIAS: int
L34B_BIAS: int
EBOX_P2D0VD: int

def __init__(self, packet, software_version: str, packet_file_name: str):
"""Intialization method for Housekeeping Data class."""
super().__init__(software_version, packet_file_name, CcsdsData(packet.header))
self.parse_data(packet)
self._parse_leak()

def _parse_leak(self):
"""Parse each current leakage field and put into an array."""
leak_list = list()
leak_bits = bitstring.Bits(bin=self.LEAK_I_RAW)
# Each Leak field is 10 bits long
leak_bit_length = 10
# There are 64 leak fields
num_leak_fields = 64
# The leak fields appear in the packet in ascending order, so to append
# the leak fields in the correct order, the binary will be parsed
# from right to left.
for leak_idx in range(leak_bit_length * num_leak_fields, 0, -leak_bit_length):
leak_list.append(leak_bits[leak_idx - leak_bit_length:leak_idx].uint)
self.LEAK_I = np.array(leak_list)
Copy link
Collaborator

@greglucas greglucas Feb 15, 2024

Choose a reason for hiding this comment

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

You can initialize the shape of the array right away and then fill in the values and avoid bitstring as well I think.

Suggested change
leak_list = list()
leak_bits = bitstring.Bits(bin=self.LEAK_I_RAW)
# Each Leak field is 10 bits long
leak_bit_length = 10
# There are 64 leak fields
num_leak_fields = 64
# The leak fields appear in the packet in ascending order, so to append
# the leak fields in the correct order, the binary will be parsed
# from right to left.
for leak_idx in range(leak_bit_length * num_leak_fields, 0, -leak_bit_length):
leak_list.append(leak_bits[leak_idx - leak_bit_length:leak_idx].uint)
self.LEAK_I = np.array(leak_list)
# Each Leak field is 10 bits long
leak_bit_length = 10
# There are 64 leak fields
num_leak_fields = 64
self.LEAK_I = np.empty(num_leak_fields, dtype=np.uint16)
# The leak fields appear in the packet in ascending order, so to append
# the leak fields in the correct order, the binary will be parsed
# from right to left.
for i, leak_idx in enumerate(range(leak_bit_length * num_leak_fields, 0, -leak_bit_length)):
self.LEAK_I[i] = int(self.LEAK_I_RAW[leak_idx - leak_bit_length:leak_idx], 2)
# or something like this to iterate through and then just fill backwards:
# self.LEAK_I[-i] = int(self.LEAK_I_RAW[i * leak_bit_length:(i + 1) * leak_bit_length], 2)

Also, are the bits supposed to be read in reverse as well (little-endian vs big-endian matter). Or are they just stored in reverse?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They're just stored in reverse. There's 64 leak fields in the packet and they're ordered as leak_64, leak_63, .... so I just need to reverse the field order when I make the array

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are we trying to move away from the bitstring library entirely?

Copy link
Collaborator

Choose a reason for hiding this comment

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

IMO we should. Let bitstring be a detail for space_packet_parser, but not bring it into imap_processing if we can avoid it. I found it to be really slow. If we need to do complicated bit manipulations then I don't see much of an issue, but everything I've seen so far is not too bad to handle ourselves. Note that bitstring has already made this a string for you, so you're sort of going back to bitstring then rather than using the original bits.

53 changes: 53 additions & 0 deletions imap_processing/hit/l0/utils/hit_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""General HIT L0 data class used for parsing data and setting attributes."""
from dataclasses import dataclass, fields

from imap_processing.ccsds.ccsds_data import CcsdsData


@dataclass
class HITBase:
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice, I like this

"""Data structure for common values across HIT.

Attributes
----------
ground_sw_version : str
Ground software version
packet_file_name : str
File name of the source packet
ccsds_header : CcsdsData
CCSDS header data

Methods
-------
parse_data(packet):
Parse the packet and assign to class variable using the xtce defined named.
"""

ground_sw_version: str
packet_file_name: str
ccsds_header: CcsdsData

def parse_data(self, packet):
"""Parse Lo L0 packet data.

Parameters
----------
packet : dict
A single Lo L0 packet from space packet parser.

"""
attributes = [field.name for field in fields(self)]

# For each item in packet, assign it to the matching attribute in the class.
for key, item in packet.data.items():
value = (
item.derived_value if item.derived_value is not None else item.raw_value
)
if "SPARE" in key:
continue
Comment on lines +46 to +47
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder if there is a way to get XTCE / space packet parser to ignore a field like this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question. I'll check the docs

if key not in attributes and "SPARE" not in key:
Copy link
Collaborator

Choose a reason for hiding this comment

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

You already checked for it above I think

Suggested change
if key not in attributes and "SPARE" not in key:
if key not in attributes:

Copy link
Contributor Author

Choose a reason for hiding this comment

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

forgot to remove that part. thanks!

raise KeyError(
f"Did not find matching attribute in {self.__class__} data class"
f"for {key}"
)
setattr(self, key, value)
19 changes: 8 additions & 11 deletions imap_processing/hit/packet_definitions/P_HIT_AUT.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='utf-8'?>
<xtce:SpaceSystem xmlns:xtce="http://www.omg.org/space/xtce" name="P_HIT_AUT">
<xtce:Header date="2023-11" version="1.0" author="IMAP SDC" />
<xtce:Header date="2024-02" version="1.0" author="IMAP SDC" />
<xtce:TelemetryMetaData>
<xtce:ParameterTypeSet>
<xtce:IntegerParameterType name="UINT1" signed="false">
Expand All @@ -12,9 +12,6 @@
<xtce:IntegerParameterType name="UINT3" signed="false">
<xtce:IntegerDataEncoding sizeInBits="3" encoding="unsigned" />
</xtce:IntegerParameterType>
<xtce:IntegerParameterType name="UINT6" signed="false">
<xtce:IntegerDataEncoding sizeInBits="6" encoding="unsigned" />
</xtce:IntegerParameterType>
<xtce:IntegerParameterType name="UINT11" signed="false">
<xtce:IntegerDataEncoding sizeInBits="11" encoding="unsigned" />
</xtce:IntegerParameterType>
Expand Down Expand Up @@ -50,11 +47,11 @@
<xtce:Parameter name="PKT_LEN" parameterTypeRef="UINT16">
<xtce:LongDescription>CCSDS Packet Length (number of bytes after Packet length minus 1)</xtce:LongDescription>
</xtce:Parameter>
<xtce:Parameter name="SHCOARSE" parameterTypeRef="UINT32">
<xtce:ShortDescription>CCSDS Packet Sec Header</xtce:ShortDescription>
<xtce:Parameter name="SC_TICK" parameterTypeRef="UINT32">
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought SHCOARSE or MET was required - is it missing here because it's a housekeeping packet?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No you're correct. HIT is calling it SC_TICK in their Telem definition and I guess I forgot to change it back to SHCOARSE when I got an updated definition sheet and re-generated the XTCE. I'm going to remove all the HIT XTCE that isn't housekeeping.

<xtce:ShortDescription>Spacecraft tick</xtce:ShortDescription>
<xtce:LongDescription>Spacecraft tick</xtce:LongDescription>
</xtce:Parameter>
<xtce:Parameter name="SPARE1" parameterTypeRef="UINT6" />
<xtce:Parameter name="AUT_SPARE1" parameterTypeRef="FILL6" />
<xtce:Parameter name="POWER_CYCLE" parameterTypeRef="UINT1">
<xtce:ShortDescription>Power cycle request (1=power cycle)</xtce:ShortDescription>
</xtce:Parameter>
Expand All @@ -67,7 +64,7 @@
<xtce:Parameter name="HEATER_NUM" parameterTypeRef="UINT1">
<xtce:ShortDescription>Heater number (0=primary, 1=secondary)</xtce:ShortDescription>
</xtce:Parameter>
<xtce:Parameter name="SPARE2" parameterTypeRef="UINT6" />
<xtce:Parameter name="AUT_SPARE2" parameterTypeRef="FILL6" />
</xtce:ParameterSet>
<xtce:ContainerSet>
<xtce:SequenceContainer name="CCSDSPacket">
Expand All @@ -88,13 +85,13 @@
</xtce:RestrictionCriteria>
</xtce:BaseContainer>
<xtce:EntryList>
<xtce:ParameterRefEntry parameterRef="SHCOARSE" />
<xtce:ParameterRefEntry parameterRef="SPARE1" />
<xtce:ParameterRefEntry parameterRef="SC_TICK" />
<xtce:ParameterRefEntry parameterRef="AUT_SPARE1" />
<xtce:ParameterRefEntry parameterRef="POWER_CYCLE" />
<xtce:ParameterRefEntry parameterRef="POWER_DOWN" />
<xtce:ParameterRefEntry parameterRef="HEATER_STAT" />
<xtce:ParameterRefEntry parameterRef="HEATER_NUM" />
<xtce:ParameterRefEntry parameterRef="SPARE2" />
<xtce:ParameterRefEntry parameterRef="AUT_SPARE2" />
</xtce:EntryList>
</xtce:SequenceContainer>
</xtce:ContainerSet>
Expand Down
Loading
Loading