-
Notifications
You must be signed in to change notification settings - Fork 27
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
Refactor clock drift #84
Conversation
I noticed that there were not tests yet regarding the clock drift adjustment. |
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.
Thanks for starting this. I would have liked to see tests for the changed functionality or bugfixing before the refactoring took place, it would ensure that the refactoring is just a refactoring, ie that all the tests are still passing.
No need to delay tests any further now though, go ahead.
pygac/pod_reader.py
Outdated
# TODO: Are we sure all satellites have this scan width in degrees ? | ||
# TODO: Does this also work for LAC? |
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.
Good questions, they should be answered before we merge this.
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.
Are we sure all satellites have this scan width in degrees ?
According to Table J-1 (Satellite Scanning Instrument Parameters for TIROS-N through NOAA-14) in the KLM guide, the max scan angle for AVHRR/2 is given by 55.37 deg. I don't know where the 55.385
deg in the code come from, but the 55.37 deg is also the default in pyorbita..geoloc_instrument_definitions.avhrr_gac
.
Does this also work for LAC?
No, according to Table 8.3.1.3.1-1. (LAC/HRPT Data Characteristics.) the scan rate for LAC/HRPT is 360 scans per minute => 1/6 seconds/line instead of the 1/2 seconds/line which is currently assumed in PODReader._adjust_clock_drift
. This can be fixed by making the scan rate a LAC/GAC reader attribute. This should be passed as frequency argument to pyorbita..geoloc_instrument_definitions.avhrr_gac
.
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.
Just noticed that the GAC/LAC readers already have the attribute reader.scan_freq
... I will definitely use it!
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.
According to Table J-1 (Satellite Scanning Instrument Parameters for TIROS-N through NOAA-14) in the KLM guide, the max scan angle for AVHRR/2 is given by 55.37 deg. I don't know where the 55.385 deg in the code come from, but the 55.37 deg is also the default in pyorbita..geoloc_instrument_definitions.avhrr_gac.
I will have to check, but I think this was calculated somehow. It's somewhere in pyorbital maybe.
return (((year - 1970).astype('datetime64[Y]') | ||
+ (jday - 1).astype('timedelta64[D]')).astype('datetime64[ms]') | ||
return (year.astype(str).astype('datetime64[Y]') |
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.
Could you explain the logic here?
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 usually try to avoid hard coded numbers as much as possible. In this case, I did not like that PyGAC hard codes the numpy.datetime64
epoch (1970). I know that there is a very low chance that numpy will ever change the epoch, but still I think PyGAC should not make any assumptions on it.
The shortest way I found to become independent of the epoch was the string conversion, because something like epoch = int(str(np.datetime64(0, 'Y')))
looks ugly to me and numpy also does not have any attribute to access its epoch directly (or at least I could not easily find it).
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.
Makes sense, thanks for explaining!
Good point for the future, I am not yet much into TDD, but I clearly see the benefit. How can we proceed on it? |
@carloshorn looks go with the test you added! I don't think you need to rewind your work now. As far as TDD goes, it's just as the name says :) Write a test first (that fails) and then proceed with the implementation so that the test passes. When the test passes, refactor so that the code becomes clean. See a demo of how to do this here: https://www.youtube.com/watch?v=58jGpV2Cg50&t=2628s The hardest part is to know what to test. My rule of thumb is that every line should be tested, but we test only public functionality, not implementation details. We can talk more on slack about it if you want (in #random for example). |
I am still trying to understand the given scan angle of 55.385 deg which is passed to pyorbital in the current implementation: Lines 523 to 524 in 5c59f2b
Unfortunately, I could not find any clear hint in Can you think of anything else to try, or maybe some verbal ideas/explanations why the scan angle needs an adjustment? |
@carloshorn Nice work with the PR! About the 55.385 this might be inherited from the PPS-ahamap package. I found a note from 2002. I can ask KG if he remembers :).
|
@ninahakansson, please ask KG. I hope he remembers, otherwise, I would vote for using the default value 55.37 from the KLM Guide, because I would prefer to have a reference/justification/explanation for any assumption/choice/parameter that appears in the code. |
From what I can find, pyorbital is also defaulting to 55.37 for avhrr: https://github.com/pytroll/pyorbital/blob/master/pyorbital/geoloc_instrument_definitions.py#L52-L102 |
Also notice that the scan angle is 55.25 for noaa 16: |
KG had nothing to add and @abhaydd showed me that in one part of the KLM-guide that value is 55.4 and that the value varies between sources, versions of sources and actually between instruments. I have no opinion about updating it or not. As it is a small change PPS will be OK either way. |
Currently, there is just a clock drift adjustment for POD satellites, but it is truly a thing to remember when adding clock drifts for KLM satellites in the future. |
@ninahakansson, thanks for checking. In this case, I would stick on one source, which could be Table J-1 (Satellite Scanning Instrument Parameters for TIROS-N through NOAA-14) in the KLM guide and use it to justify the choice in the code. |
@carloshorn in principle clock drift adjustment shouldn't be needed as the clock is updated daily on the klm series. |
@mraspaud, cool, then we are lucky and do not need to implement an extra case for NOAA-16. |
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.
LGTM, thanks for digging into this.
@sfinkens I think you need to run your tests on this one |
👉 View analysis in DeepCode’s Dashboard | Configure the bot |
@mraspaud, sorry I have not noticed that you were about to approving this. I went through the code a last time for my-self. |
Retry DeepCode |
Awesome, now I'm able to understand what's happening 😄 Thanks for digging into this! I'll run the tests ASAP. |
@sfinkens did you run the tests on this one too? |
I'm on it. There are differences, as expected, but I think not critical. Currently hunting a memory leak occuring while plotting the differences... |
Thanks for the hard work everyone! |
This PR closes #76 and closes #80 and the associated PRs: closes #81 and closes #82.
Enhancements
reader.times
a property, there is no need to synchronize the array withreader.utcs
anymore. This makes sense, because both arrays contain the same information but expressed in different data types.Fixes
It turned out that IndexError in PODReader._adjust_clock_drift #76 was a consequence of an error in computing the maximum line number of shifted line indices.
pygac/pygac/pod_reader.py
Line 452 in 5c59f2b
The
- max_idx
is wrong, see discussion in Fix clock drift rounding error #82.This PR takes care of skipped scan lines which addresses the following TODO:
pygac/pygac/pod_reader.py
Line 418 in 5c59f2b
by taking into account the complete line number range when sub-setting the missed lines, instead of only considering the shifted lines as in the current implementation:
pygac/pygac/pod_reader.py
Lines 446 to 448 in 5c59f2b
The current implementation computes wrong utc values for missed scan lines if the first scan line number is not equal to one, see
pygac/pygac/pod_reader.py
Lines 463 to 464 in 5c59f2b
The correct time transformation is:
The computed longitudes and latitudes for the slerp interpolation should correspond to the utcs before clock adjustment. So the time difference between each line in the interpolation array is equal to the scan rate of 500 ms. Therefore, it should be
clock_drift_adjust=False
in the following call:pygac/pygac/pod_reader.py
Lines 466 to 468 in 5c59f2b
otherwise, the values in
complete_lons
,complete_lats
are not necessarily in the correct order.It corrects Reduce rounding error in POD reader adjust clock drift #80, by making
reader.times
a property and taking into account milliseconds in the final assignmentpygac/pygac/pod_reader.py
Line 487 in 5c59f2b
Furthermore, note that this line is also incorrect, because after
pygac/pygac/pod_reader.py
Line 438 in 5c59f2b
the variable
offsets
has the wrong units (1/scan_rate = 1/(0.5 seconds/line) = 2 lines/seconds)Potential Side Effects:
Reader.compute_lonlat
, seepygac/pygac/reader.py
Line 471 in 5c59f2b
It is not considered as necessary for the public interface of
Reader
, because it is only called for clock drift adjustment, where the calling methodreader._adjust_clock_drift
is private already.