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

Approximate angles without TLE #65

Merged
merged 17 commits into from
Jun 18, 2021

Conversation

ninahakansson
Copy link
Collaborator

When a TLE close enough in time is missing use lat, lon of
mid-column for apprixmation of satellite position and Tiros-N height
from OSCAR as satellite altitude approximation.

When a TLE close enough in time is missing use lat, lon of
mid-column for apprixmation of satellite position and Tiros-N height
from OSCAR as satellite altitude approximation.
Copy link
Member

@mraspaud mraspaud left a comment

Choose a reason for hiding this comment

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

In some cases some of the parameters or angles are available. Should we try using these also when possible as a fallback when TLE is missing?

Copy link
Member

@mraspaud mraspaud left a comment

Choose a reason for hiding this comment

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

Interesting, thanks for submitting this! A couple of comments.

pygac/reader.py Outdated
Comment on lines 754 to 761
from pyorbital.orbital import get_observer_look as get_observer_look_no_tle
sat_alt = 850.0 # km TIROS-N OSCAR
sat_azi, sat_elev = get_observer_look_no_tle(
self.lons[:, 204][:, np.newaxis],
self.lats[:, 204][:, np.newaxis], # approximate satellite position
sat_alt, # approximate satellite altitude
self.times[:, np.newaxis],
self.lons, self.lats, 0)
Copy link
Member

Choose a reason for hiding this comment

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

Could you make this into a separate function?

pygac/reader.py Outdated
Comment on lines 754 to 761
from pyorbital.orbital import get_observer_look as get_observer_look_no_tle
sat_alt = 850.0 # km TIROS-N OSCAR
sat_azi, sat_elev = get_observer_look_no_tle(
self.lons[:, 204][:, np.newaxis],
self.lats[:, 204][:, np.newaxis], # approximate satellite position
sat_alt, # approximate satellite altitude
self.times[:, np.newaxis],
self.lons, self.lats, 0)
Copy link
Member

Choose a reason for hiding this comment

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

Should we take into account the static attitude shifts from some satellites for this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I do not know what the static attitude shifts is. Something included in the data? And I guess the sat_alt should be different for different satellites too.

Copy link
Member

Choose a reason for hiding this comment

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

sometimes it is in the data (for klm), otherwise we have these:

pygac/pygac/reader.py

Lines 51 to 75 in 3162edd

rpy_coeffs = {
'noaa7': {'roll': 0.000,
'pitch': 0.000,
'yaw': 0.000,
},
'noaa9': {'roll': 0.000,
'pitch': 0.0025,
'yaw': 0.000,
},
'noaa10': {'roll': 0.000,
'pitch': 0.000,
'yaw': 0.000,
},
'noaa11': {'roll': -0.0019,
'pitch': -0.0037,
'yaw': 0.000,
},
'noaa12': {'roll': 0.000,
'pitch': 0.000,
'yaw': 0.000,
},
'noaa14': {'roll': 0.000,
'pitch': 0.000,
'yaw': 0.000,
}}

@ghost
Copy link

ghost commented Sep 9, 2020

Congratulations 🎉. DeepCode analyzed your code in 4.614 seconds and we found no issues. Enjoy a moment of no bugs ☀️.

👉 View analysis in DeepCode’s Dashboard | Configure the bot

👉 The DeepCode service and API will be deprecated in August, 2021. Here is the information how to migrate. Thank you for using DeepCode 🙏 ❤️ !

If you are using our plugins, you might be interested in their successors: Snyk's JetBrains plugin and Snyk's VS Code plugin.

@ninahakansson ninahakansson marked this pull request as ready for review September 21, 2020 12:30
@carloshorn
Copy link
Collaborator

Hi @ninahakansson,
we used this PR to process the entire TIROS-N data and compare it with the one using TLEs.
Unfortunately, it still requires some work, because we could not use the output to generate AMVs due to missing angles.
It appears like the algorithm that computes the sensor angles produces NaNs in the output.

image

See the central NaN stripe in the above image taken from the produced file AVHRR-GAC_FDR_1C_TSN_19790201T020219Z_19790201T035622Z_R_O_20201008T100626Z_0100.nc.

@carloshorn
Copy link
Collaborator

We also looked into potential other satellites that could benefit from this method, and it turned out that NOAA7 also shows large TLE gaps.

In order to avoid a static constant altitude for each satellite, I would propose to interpolate the satellite altitude from surrounding TLEs, because we can expect that the changes in altitude are smooth, except there was a manoeuvre. @mraspaud, is pyorbital capable to do this?

As @mraspaud proposed, we may also have a look into the angles inside the file and compare them to the fix presented in this PR.

@ninahakansson
Copy link
Collaborator Author

@carloshorn I checked and I get the same error. For some pixels in column 204 there are nodata instead of 0. I guess we could just put it to zero.

@ninahakansson
Copy link
Collaborator Author

ninahakansson commented Jan 14, 2021

I pushed a fix for the NaN for satzenith angle. Looking at the code I suspect the problem is really in pyorbital.

As for using the correction for noaa7 the height (according to OSCAR) is for NOAA-7 850km that is quite close to the 860km for TIROS-N. I think as a first approximation the fixed value of 860km is Ok. Interpolation using existing TLEs could be added later in an other PR. But I think it is good if we keep a default value as this means pygac can run also when TLEs are completely missing.

@mraspaud
Copy link
Member

@carloshorn Pyorbital can't do interpolation of the TLEs, only propagation (extrapolation).

@carloshorn
Copy link
Collaborator

I see the advantage of having a TLE independent fall back mechanism.
For the FDR generation, I would prefer an algorithm that makes use of the entire TLE record, treating each TLE as an observation to determine the actual flight path.
@mraspaud, do you know if there are any libraries that we could use? Or do you know any algorithms in this direction that we may include into PyTroll? I could ask some people working on space debris at ESOC. Maybe they have an idea about the most accurate way to bridge TLE gaps.
Quick paper search gave me https://arxiv.org/pdf/1002.2277.pdf

@mraspaud
Copy link
Member

@carloshorn I don't know of any library for doing TLE interpolation, but I haven't looked in a while. The fact that I'm no flight dynamics expert doesn't help, but I guess you have these people in house, right?
The paper you show seems promising, and that method would be a great addition to pyorbital :) 👍

@ninahakansson
Copy link
Collaborator Author

@carloshorn I think it is a good idea to include more accurate height estimates. But I will not have time to include this any time soon.

pygac/reader.py Outdated
self.times[:, np.newaxis],
self.lons, self.lats, 0)
# Sometimes the get_observer_look_not_tle returns nodata instead of 90.
sat_elev[:, mid_column] = 90
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since pyorbital is part of the PyTroll libraries, I would prefer to fix the issue there instead of fixing the library output in pygac. The issue is very likely a problem with the defined domain of trigonometric functions and their inverse, my candidates are arctan and arcsin.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Absolutely! But with the fix here it is ok to use also an old version of pyorbital. I think that is nice. I have made an issue to pyorbital pytroll/pyorbital#72.

Copy link
Member

Choose a reason for hiding this comment

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

I was thinking whether that correction could be applied only if the pyorbital version <= current version. This would remind us to remove that fix in the future. On the other hand we don't know whether the issue will be solved in the next pyorbital release. So what about referencing the github issue in the comment?

@carloshorn
Copy link
Collaborator

An additional note on using this fix together with pygac-fdr.
It turned out, that the IndexError in Reader.get_tle_lines will also hit the metadata collector.
In my quick and dirty test, I avoided this by returning empty strings instead of raising the index error, but raising the exception would be cleaner.
This is just a reminder for opening a ticket on pygac-fdr in case this fix produces useful data and gets merged into master.

Copy link
Member

@sfinkens sfinkens left a comment

Choose a reason for hiding this comment

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

Nice work! Just one minor comment and question.

pygac/reader.py Outdated
self.times[:, np.newaxis],
self.lons, self.lats, 0)
# Sometimes the get_observer_look_not_tle returns nodata instead of 90.
sat_elev[:, mid_column] = 90
Copy link
Member

Choose a reason for hiding this comment

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

I was thinking whether that correction could be applied only if the pyorbital version <= current version. This would remind us to remove that fix in the future. On the other hand we don't know whether the issue will be solved in the next pyorbital release. So what about referencing the github issue in the comment?

Comment on lines +340 to +344
expected_sat_azi_0 = np.array([283.09872924, 283.12775589, 283.13951497, 283.14786413, 283.19638805])
expected_sat_azi_201 = np.array([272.85051989, 273.79847634, 272.04794616, 273.01363377, 274.00055397])
expected_sat_azi_408 = np.array([39.77021472, 39.71516966, 39.68104134, 39.60503726, 39.5403431])
expected_sat_elev_0 = np.array([20.94889204, 20.96041284, 20.96368521, 20.96826309, 20.95849212])
expected_sat_elev_204 = np.array([89.24533884, 89.22663677, 89.25079817, 89.24938043, 89.23004118])
Copy link
Member

Choose a reason for hiding this comment

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

Were these expected values computed with TLE and then for the tests they are approximated without TLE?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, that is how I made theml.

Copy link
Member

@mraspaud mraspaud left a comment

Choose a reason for hiding this comment

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

Thanks for improving this, is there a test to update or add for this?

# Sometimes (pyorbital <= 1.6.1) the get_observer_look_not_tle returns nodata instead of 90.
# Problem solved with https://github.com/pytroll/pyorbital/pull/77
if LooseVersion(pyorbital.__version__) <= LooseVersion('1.6.1'):
sat_elev[:, mid_column] = 90
Copy link
Member

Choose a reason for hiding this comment

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

Could you issue a warning here saying eg that for best results, pyorbital > 1.6.1 is needed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Results are not better with pyorbital > 1.6.1. With the fix they are the same (= 90). Without the fix they sometimes get rounded to 89.999999 instead of 90 but I don't think that is better. I added a test to check sat_elev at nadir are 90 degrees.

pygac/reader.py Outdated
@@ -739,6 +740,7 @@ def get_sat_angles_without_tle(self):
# Sometimes (pyorbital <= 1.6.1) the get_observer_look_not_tle returns nodata instead of 90.
# Problem solved with https://github.com/pytroll/pyorbital/pull/77
if LooseVersion(pyorbital.__version__) <= LooseVersion('1.6.1'):
pass
Copy link
Member

Choose a reason for hiding this comment

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

Why do you need a pass here?

Copy link
Member

@mraspaud mraspaud left a comment

Choose a reason for hiding this comment

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

Thanks for fixing this, LGTM

@mraspaud
Copy link
Member

I made a mess here, I'll fix it after lunch

@codecov
Copy link

codecov bot commented Jun 18, 2021

Codecov Report

Merging #65 (c53b737) into main (b4a9731) will increase coverage by 0.36%.
The diff coverage is 95.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #65      +/-   ##
==========================================
+ Coverage   66.30%   66.66%   +0.36%     
==========================================
  Files          34       34              
  Lines        2858     2895      +37     
==========================================
+ Hits         1895     1930      +35     
- Misses        963      965       +2     
Impacted Files Coverage Δ
pygac/reader.py 63.79% <88.23%> (+0.68%) ⬆️
pygac/tests/test_reader.py 99.32% <100.00%> (+0.05%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b4a9731...c53b737. Read the comment docs.

@mraspaud mraspaud merged commit 5423880 into pytroll:main Jun 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants