-
Notifications
You must be signed in to change notification settings - Fork 16
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
Adding CoDICE Event data + Species counts packet definitions for L0 #106
Adding CoDICE Event data + Species counts packet definitions for L0 #106
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has a lot of duplicated code that I'd like to see consolidated into one method. However, that code itself looks great, and this will definitely be a handy reference for other instruments!
@maxinelasp look at the class I made in |
imap_processing/packet_definitions/codice/lo_sw_species_counts.xml
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks a lot better, nice job! I'll approve when you have updated the other generation files to use this shared class.
|
||
# Load data from Excel file | ||
xls = pd.ExcelFile(self.path_to_excel_file) | ||
pkt = xls.parse(self.packet_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like you're generating pkt
here using self.path_to_excel_file
and self.packet_name
, but you take in pkt
as a variable to your init
function (line 9). I'd suggest removing self.path_to_excel_file
and self.packet_name
from the class, and just using self.pkt
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or, since pkt
is optional, you could make the path and packet name optional as well, and in __init__
assign self.pkt
to the provided packet dataframe if it exists, and otherwise, generate/parse it from the excel file and packet name.
if pkt:
self.pkt = pkt
else:
if self.path_to_excel_file and self.packet_name:
xls = pd.ExcelFile(self.path_to_excel_file)
self.pkt = xls.parse(self.packet_name)
else:
raise TypeError("Error creating TelemetryGenerator: either a packet dataframe OR a packet name and excel file path must be provided!")
|
||
# Create the TelemetryMetaData element | ||
telemetry_metadata = Et.SubElement( | ||
root, "{http://www.omg.org/space}TelemetryMetaData" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we assigned http://www.omg.org/space
to a variable because if this link changes, we can easily replace it in one place.
encoding.attrib["sizeInBits"] = str(size) | ||
encoding.attrib["encoding"] = "unsigned" | ||
|
||
if data_type == "BYTE": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, it seems like user need to input science_byte sizeInBits if packet has science data of datatype BYTE. Is that right? can we raise error if user forgot to input science_byte?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! We could add an error.
codice_science_container = Et.SubElement( | ||
container_set, "xtce:SequenceContainer" | ||
) | ||
codice_science_container.attrib["name"] = "CoDICESciencePacket" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we take in packet_name as an input and then assign it to this name, then we can use this to create sequence container for any data packet.
parameter.attrib["name"] = row["mnemonic"] | ||
parameter_type_ref = "" | ||
|
||
if row["mnemonic"] == "Data": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to make this useable for other instrument, how can we generalized this. This could be called differently in different packet. Eg. Science data could be called SCIENCE_DATA
or DE_TOF
and so on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just used this code to generate a GLOWS file - still need to make sure it all works, but this was the only place it got hung up! Once I fixed this line (the GLOWS mnemonic is different - BIN0, BIN01, etc ) it all ran successfully, which is great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I juist had to do this for my updated packets with"Data" and 'Event_Data',
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@maxinelasp @tech3371 I tried to figure this out, but I think I would need guidance on how to elevate it work on the mnemonic. Would it be as simple as assigning it?
parameter_set = self.create_ccsds_packet_parameters( | ||
parameter_set, CCSDSParameters().parameters | ||
) | ||
telemetry_metadata = self.create_container_set( | ||
telemetry_metadata, CCSDSParameters().parameters, self.apid | ||
) | ||
codice_science_container = self.create_container_set( | ||
telemetry_metadata, CCSDSParameters().parameters, self.apid | ||
) | ||
codice_science_container = self.add_codice_science_parameters( | ||
codice_science_container, self.pkt | ||
) | ||
parameter_set = self.create_parameters_from_dataframe(parameter_set, self.pkt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To summarize what's happening in these lines,
- Creating Parameter definition for CCSDS parameters, first 10 rows from excel sheet.
- Create CCSDS container set with CCSDS parameters as EntryList. Then create empty containerset for a packet and use CCSDS containerset as base container.
- Populate above empty containerset with EntryList using data from row 10 and onwards from excel sheet.
- Create remaining parameter for row 10 and onwards from excel sheet.
If this is the logic, then it is non-instrument specific. I feel like we can generalized it to be non-instrument specific if we take out CoDICE specific names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did take out codice specific I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! I had a few suggestions, but they're minor, so you can take them or leave them. Like I mentioned, I ran this on the GLOWS packet with very minimal issues - which is great! You've certainly saved me a lot of time, thanks!
array_parameter_type.attrib["signed"] = "false" | ||
|
||
encoding = Et.SubElement( | ||
array_parameter_type, "xtce:IntegerDataEncoding" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be BinaryDataEncoding
? @tech3371 had this in a slack thread: https://lasp.slack.com/archives/C05CRQL2LJF/p1693503000638779?thread_ts=1693501674.878519&cid=C05CRQL2LJF
xtce:BinaryParameterType name="sciData">
<xtce:UnitSet/>
<xtce:BinaryDataEncoding bitOrder="mostSignificantBitFirst">
<xtce:SizeInBits>
<xtce:FixedValue>10080</xtce:FixedValue>
</xtce:SizeInBits>
</xtce:BinaryDataEncoding>
</xtce:BinaryParameterType>
i.e. you don't want one massive integer out, you want a binary field of 0s and 1s
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this work on all instruments? This a generalized way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am saying that BYTE is not an Integer parameter type, and it is just a field we know nothing about, so we want to leave it as a binary stream and do the processing on it later. So I think this is more general and is what instruments are expecting.
I think it would just be updating a few of the above variable settings you have from "Integer" to "Binary", not using those fixed values.
Yay! I want to make it perfect, but I hear Greg saying "we will always update code"... |
- data_type_event_data: The data type for the "Event_Data" mnemonic | ||
""" | ||
# Extract unique values from the 'lengthInBits' column | ||
unique_lengths = self.pkt["lengthInBits"].unique() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unique_lengths = self.pkt["lengthInBits"].unique() | |
unique_lengths = self.pkt["lengthInBits"].unique().astype(int) |
I noticed some issues with it producing types like uint8.0
, stemming from the fact that this value is stored as a float instead of an int. So anywhere that this "length in bits" column is, it should be an int.
if row["mnemonic"] in ["Data", "Event_Data"]: | ||
parameter_type_ref = "BYTE" | ||
else: | ||
parameter_type_ref = f"uint{row['lengthInBits']}" # Use UINT for others |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parameter_type_ref = f"uint{row['lengthInBits']}" # Use UINT for others | |
parameter_type_ref = f"uint{int(row['lengthInBits'])}" # Use UINT for others |
Same as above. If it would be possible to get this value from the unique_lengths
variable above, it's better to only parse through the dataframe once exactly because of these type issues. But, it doesn't matter for this review - just wanted to note that for the future.
…MAP-Science-Operations-Center#106) "made `telemetry_generator.py` more user friendly, updated with BinaryParameterType, shorted codice/L0/ files"
Overview
I made
.py
files for 5 codice science packets, and output topacket_definitions
. I added a new directory/packet_definitions/codice
to store codice specific packet definitions.Goal
Break down the repetitive nature of the
.py
files.Feedback required
Please help me with insight on how to break down the python code.
Issue #75 "Utilizing classes, config files, or argument parsing to abstract out parameters from the code"
-argparse
-configure (json)
-classes
New Files
new file: L0/hi_pha.py
new file: L0/lo_pha.py
new file: L0/nsw_species_counts.py
new file: L0/omni_species_counts.py
new file: L0/sw_species_counts.py
new file: ../packet_definitions/codice/hi_pha.xml
new file: ../packet_definitions/codice/lo_nsw_species_counts.xml
new file: ../packet_definitions/codice/lo_pha.xml
new file: ../packet_definitions/codice/lo_sw_species_counts.xml
new file: ../packet_definitions/codice/omni_species_counts.xml
Updated Files
example_xtce.xml