-
Notifications
You must be signed in to change notification settings - Fork 22
GLOWS l1a validation corrections #2584
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
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,15 @@ | ||
| """Data classes to support GLOWS L1A processing.""" | ||
|
|
||
| import logging | ||
| import struct | ||
| from dataclasses import InitVar, dataclass, field | ||
|
|
||
| from imap_processing.glows import __version__ | ||
| from imap_processing.glows.l0.glows_l0_data import DirectEventL0, HistogramL0 | ||
| from imap_processing.glows.utils.constants import DirectEvent, TimeTuple | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| @dataclass | ||
| class StatusData: | ||
|
|
@@ -261,8 +264,7 @@ def __post_init__(self, l0: HistogramL0) -> None: | |
| self.glows_time_offset = TimeTuple(l0.GLXOFFSEC, l0.GLXOFFSUBSEC) | ||
|
|
||
| # In L1a, these are left as unit encoded values. | ||
| # TODO: This is plus one in validation code, why? | ||
| self.number_of_spins_per_block = l0.SPINS + 1 | ||
| self.number_of_spins_per_block = l0.SPINS | ||
| self.number_of_bins_per_histogram = l0.NBINS | ||
| self.number_of_events = l0.EVENTS | ||
| self.filter_temperature_average = l0.TEMPAVG | ||
|
|
@@ -280,6 +282,16 @@ def __post_init__(self, l0: HistogramL0) -> None: | |
| "is_generated_on_ground": False, | ||
| } | ||
|
|
||
| # Remove the extra byte from some packets (if there are an odd number of bins) | ||
| if self.number_of_bins_per_histogram % 2 == 1: | ||
| self.histogram = self.histogram[:-1] | ||
|
|
||
| if self.number_of_bins_per_histogram != len(self.histogram): | ||
| logger.warning( | ||
| f"Number of bins {self.number_of_bins_per_histogram} does not match " | ||
| f"processed number of bins {len(self.histogram)}!" | ||
| ) | ||
|
Comment on lines
+286
to
+293
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so this is trimming
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I only want to trim one byte off the end, because that's the only valid case. Then, I check if the length mismatches - if it does, that means I either have much less data than expected, or more, which are both error cases.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you want to raise or logger.error it instead of a warning then? Does this mean that the flight software is always transmitting an even number of bytes then so you are taking care of that above? That seems somewhat odd to me and I'm not sure why they would send an extra byte down.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the flight software always transmits an even number of bytes so if there is an odd number of bins, we end up with an extra zero at the end. This is something that came up in MAG too so I think this is what is occurring.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can change it to raise an error
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Up to you what you want to do. There are pros and cons. It does fail loudly, but that also means it fails loudly and other people get upset with us for not producing the good data that was there 😂
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I think I would rather this just be evident if I am looking. If the data is as expected, then does it really matter...? I don't really use number of bins in the later code, it's all based off the histogram lengths anyway. |
||
|
|
||
|
|
||
| @dataclass | ||
| class DirectEventL1A: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,6 +41,45 @@ def test_histogram_list(histogram_test_data, decom_test_data): | |
| assert sum(histogram_test_data.histogram) == histl0.EVENTS | ||
|
|
||
|
|
||
| def test_histogram_bin_handling(decom_test_data): | ||
| """Test histogram bin handling for odd bins.""" | ||
| histl0 = decom_test_data[0][0] | ||
|
|
||
| # Test odd number of bins - extra byte should be removed | ||
| mock_histl0_odd = mock.MagicMock(spec=histl0) | ||
| mock_histl0_odd.NBINS = 3599 | ||
| mock_histl0_odd.HISTOGRAM_DATA = list(range(3600)) | ||
| mock_histl0_odd.SWVER = 1 | ||
| mock_histl0_odd.packet_file_name = "test.pkts" | ||
| mock_histl0_odd.ccsds_header = mock.MagicMock() | ||
| mock_histl0_odd.ccsds_header.SRC_SEQ_CTR = 0 | ||
| mock_histl0_odd.STARTID = 0 | ||
| mock_histl0_odd.ENDID = 10 | ||
| mock_histl0_odd.SEC = 1000 | ||
| mock_histl0_odd.SUBSEC = 0 | ||
| mock_histl0_odd.OFFSETSEC = 0 | ||
| mock_histl0_odd.OFFSETSUBSEC = 0 | ||
| mock_histl0_odd.GLXSEC = 1000 | ||
| mock_histl0_odd.GLXSUBSEC = 0 | ||
| mock_histl0_odd.GLXOFFSEC = 0 | ||
| mock_histl0_odd.GLXOFFSUBSEC = 0 | ||
| mock_histl0_odd.SPINS = 10 | ||
| mock_histl0_odd.EVENTS = 1000 | ||
| mock_histl0_odd.TEMPAVG = 100 | ||
| mock_histl0_odd.TEMPVAR = 10 | ||
| mock_histl0_odd.HVAVG = 500 | ||
| mock_histl0_odd.HVVAR = 5 | ||
| mock_histl0_odd.SPAVG = 150 | ||
| mock_histl0_odd.SPVAR = 1 | ||
| mock_histl0_odd.ELAVG = 20 | ||
| mock_histl0_odd.ELVAR = 2 | ||
| mock_histl0_odd.FLAGS = 0 | ||
|
|
||
| hist_odd = HistogramL1A(mock_histl0_odd) | ||
| assert len(hist_odd.histogram) == 3599 | ||
| assert hist_odd.number_of_bins_per_histogram == 3599 | ||
|
|
||
|
|
||
| def test_histogram_obs_day(packet_path): | ||
| l1a = glows_l1a(packet_path) | ||
|
|
||
|
|
@@ -522,10 +561,11 @@ def test_expected_hist_results(l1a_dataset): | |
| } | ||
|
|
||
| # block header and flags are handled differently, so not tested here | ||
| # "number_of_spins_per_block" is a special case and handled specifically | ||
| # (validation data is incorrect) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there plan to fix that mismatch from validation data?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can look into it. I don't think it's worth putting tons of time in because this is a pretty minor mismatch, but I can try and re-run the validation data through the new version of the validation code and see if that produces the new output. |
||
| compare_fields = [ | ||
| "first_spin_id", | ||
| "last_spin_id", | ||
| "number_of_spins_per_block", | ||
| "number_of_bins_per_histogram", | ||
| "histogram", | ||
| "number_of_events", | ||
|
|
@@ -560,6 +600,10 @@ def test_expected_hist_results(l1a_dataset): | |
|
|
||
| for field in compare_fields: | ||
| assert np.array_equal(data[field], datapoint[field].data) | ||
| assert np.array_equal( | ||
| data["number_of_spins_per_block"] - 1, | ||
| datapoint["number_of_spins_per_block"].data, | ||
| ) | ||
|
|
||
|
|
||
| @mock.patch("imap_processing.glows.l1a.glows_l1a.decom_packets") | ||
|
|
||
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.
@greglucas, you just did that for CoDICE. I am wondering if we should refactor incomplete packets filter as general utils function.
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 add a warning for missing sequence counts for a given apid, but that is only when using the
packet_file_to_datasetsfunction which I don't think GLOWS is. But, I think that every instrument will want to handle these differently because some may want to keep it as a warning, others may have different conditions they want to consider on what a valid sequence of packets is.What happens here if you have some direct_events but not all of the sequence, so not all of the data is missing and it is actually partially there. Maybe this is handled in creating the values in the first place.
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, that case is handled later. The missing sequences are in an attribute for tracking. I did hear from Marek about some related changes surrounding duplicate DE packets, so this piece may get updated again soon.