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

Add NDVI-scaled hybrid green correction #2280

Merged
merged 19 commits into from Dec 15, 2022

Conversation

strandgren
Copy link
Collaborator

@strandgren strandgren commented Nov 16, 2022

This PR adds a new approach for correcting the reflectance from green channels that miss the chlorophyll reflectance peak at 0.55 microns, e.g. AHI and FCI.

The approach is based on the hybrid green method from Miller et al. (2016), but using dynamic blend factor that depends on the scene NDVI. The larger the NDVI, the smaller the contribution from the NIR (0.86 micron) channel will be.

  • Tests added
  • Fully documented

@codecov
Copy link

codecov bot commented Nov 16, 2022

Codecov Report

Merging #2280 (befb402) into main (f9c2070) will increase coverage by 0.04%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##             main    #2280      +/-   ##
==========================================
+ Coverage   94.32%   94.36%   +0.04%     
==========================================
  Files         308      311       +3     
  Lines       46168    46703     +535     
==========================================
+ Hits        43546    44073     +527     
- Misses       2622     2630       +8     
Flag Coverage Δ
behaviourtests 4.58% <0.00%> (-0.03%) ⬇️
unittests 95.00% <100.00%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
satpy/tests/compositor_tests/test_ahi.py 100.00% <ø> (ø)
satpy/composites/spectral.py 100.00% <100.00%> (ø)
satpy/tests/compositor_tests/test_spectral.py 100.00% <100.00%> (ø)
satpy/composites/ahi.py 0.00% <0.00%> (-100.00%) ⬇️
satpy/readers/netcdf_utils.py 98.32% <0.00%> (-1.68%) ⬇️
satpy/tests/test_resample.py 88.90% <0.00%> (-0.37%) ⬇️
satpy/readers/yaml_reader.py 97.49% <0.00%> (-0.01%) ⬇️
satpy/tests/test_utils.py 100.00% <0.00%> (ø)
satpy/readers/seviri_base.py 100.00% <0.00%> (ø)
satpy/readers/meris_nc_sen3.py 100.00% <0.00%> (ø)
... and 19 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@coveralls
Copy link

coveralls commented Nov 16, 2022

Coverage Status

Coverage increased (+0.05%) to 94.958% when pulling befb402 on strandgren:feature-ndvi_corrected_hybrid_green into f9c2070 on pytroll:main.

Copy link
Member

@simonrp84 simonrp84 left a comment

Choose a reason for hiding this comment

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

Nice! Glad to see this composite added :)

I have a couple of comments in the docs.

@djhoese
Copy link
Member

djhoese commented Nov 16, 2022

If you have the DOI for the paper this is based on I think you can add:

:doi:`123456`

in the docstring and our custom sphinx DOI plugin will link it to the paper.

@strandgren
Copy link
Collaborator Author

strandgren commented Nov 17, 2022

Below are a few examples using the new green correction. Original high-resolution images can be provided upon request.

Himawari/AHI

Himawari-8/AHI True Color with current hybrid green correction of the green channel Himawari-8/AHI True Color with new NDVI weighted hybrid green correction of the green channel VIIRS True Color from NASA Worldview
AHI_true_color_hybrid_green_93_7 AHI_true_color_ndvi_green_15_5 image

MTG/FCI test dataset

MTG/FCI True Color with current hybrid green correction of the green channel MTG/FCI True Color with new NDVI weighted hybrid green correction of the green channel VIIRS True Color from NASA Worldview
FCI_true_color_hybrid_green_93_7 FCI_true_color_ndvi_green_15_5 image

Sentinel-3/OLCI
OLCI offers an interesting test case for the green correction method since it has two green bands, one that is centered at 0.56 microns that properly capture the chlorophyll signal and is used for true color imager and another one that is centered at 0.51 microns, just like AHI and FCI. Hence we can create OLCI true color RGBs using the 0.51 channel for the green band with the green band corrections applied and then compare against the "proper" green band using the 0.56 channel.

The first columns in the tables below how the OLCI True color using the 0.551 channel as the green band without any corrections to it. This shows that by using this approach we see the same issues as for AHI/FCI true color imager: Brownish vegetation and reddish barren/arid/desert surface types.

Set of granules over Australia and Indonesia

OLCI True color with 0.51 without green correction OLCI True color with 0.51 and current hybrid green correction OLCI True color with 0.51 and new NDVI-weighted hybrid green correction OLCI standard true color using 0.56
OLCI_true_color_hybrid_green_100_0 OLCI_true_color_hybrid_green_93_7 OLCI_true_color_ndvi_green_15_5_asia OLCI_true_color_asia

Set of granules over Sahara and western Europe

OLCI True color with 0.51 without green correction OLCI True color with 0.51 and current hybrid green correction OLCI True color with 0.51 and new NDVI-weighted hybrid green correction OLCI standard true color using 0.56
OLCI_true_color_hybrid_green_100_0 OLCI_true_color_hybrid_green_93_7 OLCI_true_color_ndvi_green_15_5_euro OLCI_true_color_euro

The new NDVI-weighted correction offers a similar boost to the green color of vegetation as the current hybrid green method. However, it performs better in reducing the reddishness of barren surface types, when comparing against reference true color RGB imagery using better located green channels.

One difference that can be seen in the OLCI images around Australia is that the ocean appear more turquoise using the 0.51 channel compared to the reference true color using the 0.56 channel. This effect is rather insensitive to the green correction. This is probably related to the 0.51 channels being more sensitive to phytoplankton and might be nice feature, although it is not likely to make a big difference for GEO imagers like AHI and FCI.

@strandgren
Copy link
Collaborator Author

strandgren commented Nov 17, 2022

It should be noted that the examples shown above are based on a first guess of the tunable parameters of the corrector. I suggest to keep it like this for the moment and then we can update it later when we have performed a more quantitative validation.

Question: Do you think this is mature enough to replace the current hybrid green method in the AHI true color RGBs, or shall we rather keep the current correction for now? Either way I would include both, but make one default e.g. true_color and the other as e.g. true_color_hybrid_green/true_color_ndvi_hybrid_green.

@strandgren
Copy link
Collaborator Author

strandgren commented Nov 17, 2022

With the last commits I have refactored the code used for the green band corrections in order to make them more generalized and aligned with the description of the method in the literature.

I also made the new NDVI weighted hybrid green correction the default one for FCI true color imagery, for now using preliminary limits of the blending factors which will be tuned once we get real data.

@strandgren
Copy link
Collaborator Author

If you have the DOI for the paper this is based on I think you can add:

:doi:`123456`

in the docstring and our custom sphinx DOI plugin will link it to the paper.

Thanks, I added this in one of the later commits.

@strandgren
Copy link
Collaborator Author

Nice! Glad to see this composite added :)

I have a couple of comments in the docs.

@simonrp84 I cannot find any comments. I'm a looking at the wrong place? Please not that I have done some more work on this today, including some refactoring. I also added some test results in the comments above :)

@strandgren strandgren marked this pull request as ready for review November 17, 2022 14:27
@mraspaud mraspaud added enhancement code enhancements, features, improvements component:compositors labels Nov 17, 2022
satpy/composites/spectral.py Outdated Show resolved Hide resolved
modifiers: [sunz_corrected, rayleigh_corrected]
standard_name: toa_bidirectional_reflectance

In this example, pixels with NDVI=0.0 (default `ndvi_min`) will be a weighted average with 85% contribution from the
Copy link
Member

Choose a reason for hiding this comment

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

Is this correct? I thought that for very green objects we wanted more of the 0.8 channel, not less - as we miss the chlorophyll peak in the FCI/AHI 0.5 micron band we need to boost it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Well this is the interesting bit with the green band correction. The location of the AHI/FCI green bands has two effects:

  1. Vegetation appears brownish.
  2. Barren appears reddish.

The green color of vegetation can be boosted with a higher contribution from the NIR channel. Similarly, the reddishness of barren is reduced with an increasing contribution from the NIR channel. However, more contribution from NIR is required to get the proper color of barren, compared to vegetation. Hence, I came up with the solution of increasing the contribution from NIR with decreasing NDVI.

Below are a few examples using the default hybrid green method, with decreasing contribution from the NIR channel. As you can see the color of Australia starts to get too red when the color of vegetation start to look realistic. I also included the result of the NDVIHybridGreen (with just qualitative tuning) and VIIRS RGB from NASA worldview as reference.

15% NIR 10% NIR 7% NIR 4% NIR 0% NIR With this PR VIIRS from NASA Worldview
AHI_true_color_hybrid_green_85_15 AHI_true_color_hybrid_green_90_10 AHI_true_color_hybrid_green_93_7 AHI_true_color_hybrid_green_96_4 AHI_true_color_hybrid_green_100_0 AHI_true_color_ndvi_green_15_5 image

Copy link
Member

Choose a reason for hiding this comment

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

Hence, I came up with the solution of increasing the contribution from NIR with decreasing NDVI.

Your solution, does this mean that this is just for FCI so is "new" or is this being applied to AHI by some other group and documented in some paper?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is only internal developments in preparation for FCI. We are testing with AHI since we have the same scenario with sub-optimal position of the green band there. Hopefully we can publish it at some point though.

satpy/composites/spectral.py Show resolved Hide resolved
Copy link
Member

@djhoese djhoese left a comment

Choose a reason for hiding this comment

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

How much of this is backwards compatible with what existed before? I see classes changing names, composites changing names, etc. I will need to make copies of the originals for my own application if these are merged so I just want to make sure.

@strandgren
Copy link
Collaborator Author

@djhoese If I implemented everything according to plan, everything should be backwards compatible. The renaming of classes and composites is done to make them more generic (they started off as Himawari-specific) and also align the naming with the corresponding literature.

One aspect that would change is the green correction of AHI true color RGBs, since I changed the value to be in-line with the paper on which the correction is based. I can, of course revert this, if preferred. See my comment above on this topic.

@strandgren
Copy link
Collaborator Author

I had underestimated to which extent this PR could potentially cause compatibility problems for other users. After discussion with @mraspaud I have re-introduced the old class (GreenCorrector), but with a deprecation warning. I also re-introduced the composites that used this class, such that they can still be used with the same name, but together with the deprecation warning.

Finally I also changed the default fractions for the hybrid green band correction of the true color RGBs for AHI/AMI, such that they are in line with the current main (rather than on the paper on which they're based).

@pnuu
Copy link
Member

pnuu commented Nov 21, 2022

The documentation build fails with:

/home/docs/checkouts/readthedocs.org/user_builds/satpy/conda/2280/lib/python3.10/site-packages/satpy/composites/spectral.py:docstring of satpy.composites.spectral.NDVIHybridGreen:14: ERROR: Unexpected indentation.
/home/docs/checkouts/readthedocs.org/user_builds/satpy/conda/2280/lib/python3.10/site-packages/satpy/composites/spectral.py:docstring of satpy.composites.spectral.HybridGreen:1: WARNING: Block quote ends without a blank line; unexpected unindent.

@strandgren
Copy link
Collaborator Author

The documentation build fails with:

/home/docs/checkouts/readthedocs.org/user_builds/satpy/conda/2280/lib/python3.10/site-packages/satpy/composites/spectral.py:docstring of satpy.composites.spectral.NDVIHybridGreen:14: ERROR: Unexpected indentation.
/home/docs/checkouts/readthedocs.org/user_builds/satpy/conda/2280/lib/python3.10/site-packages/satpy/composites/spectral.py:docstring of satpy.composites.spectral.HybridGreen:1: WARNING: Block quote ends without a blank line; unexpected unindent.

@pnuu Thanks I missed that. I cannot directly see what is the issue though, at least not for the warning. Can I see what test that is failing in order to test solutions offline?

@pnuu
Copy link
Member

pnuu commented Nov 21, 2022

I think doing make html in the doc/ directory should show the same warning/error.

For example, to simulate an FCI corrected green composite, one could use
a combination of 93% from the green band (vis_05) and 7% from the
near-infrared 0.8 µm band (vis_08)::
hybrid_green = (1 - F) * R(0.51) + F * R(0.86)
Copy link
Member

Choose a reason for hiding this comment

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

Maybe try making this a literal block (indent and put :: on the line above) and see if that fixes the one error.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks, that was the issue. Now it seems to work.

Comment on lines 124 to 134
ndvi_hybrid_green:
compositor: !!python/name:satpy.composites.spectral.NDVIHybridGreen
limits: [0.15, 0.05]
prerequisites:
- name: vis_05
modifiers: [sunz_corrected, rayleigh_corrected]
- name: vis_06
modifiers: [sunz_corrected, rayleigh_corrected]
- name: vis_08
modifiers: [sunz_corrected ]
standard_name: toa_bidirectional_reflectance
Copy link
Member

Choose a reason for hiding this comment

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

I think this whole thin should be indented one level and :: put on the previous line to make it literal.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks, that was the issue. Now it seems to work.

@mraspaud
Copy link
Member

as @ameraner learned last week, the line number in the errors refers to the line number from the start of the docstring (ie not from the beginning of the file)

Copy link
Member

@pnuu pnuu left a comment

Choose a reason for hiding this comment

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

Few typos and inconsistent syntax, otherwise LGTM.

satpy/composites/spectral.py Outdated Show resolved Hide resolved
satpy/etc/composites/ahi.yaml Outdated Show resolved Hide resolved
satpy/etc/composites/ami.yaml Outdated Show resolved Hide resolved
strandgren and others added 3 commits November 23, 2022 18:08
Co-authored-by: Panu Lahtinen <pnuu+git@iki.fi>
Co-authored-by: Panu Lahtinen <pnuu+git@iki.fi>
Co-authored-by: Panu Lahtinen <pnuu+git@iki.fi>
@strandgren
Copy link
Collaborator Author

Thanks for spotting @pnuu , I should consider re-activating the PyCharm spell-check..

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.

Just a couple of comments, otherwise LGTM

satpy/composites/spectral.py Outdated Show resolved Hide resolved
satpy/etc/composites/ahi.yaml Show resolved Hide resolved
satpy/tests/compositor_tests/test_spectral.py Outdated Show resolved Hide resolved
strandgren and others added 3 commits November 28, 2022 08:46
Co-authored-by: Martin Raspaud <martin.raspaud@smhi.se>
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.

LGTM, thanks for adding this great correction to the green channel!

- wavelength: 0.51
modifiers: [sunz_corrected, rayleigh_corrected]
- wavelength: 0.85
modifiers: sunz_corrected]
Copy link
Member

Choose a reason for hiding this comment

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

Something is not being tested. This syntax is not correct.

Copy link
Collaborator Author

@strandgren strandgren Dec 6, 2022

Choose a reason for hiding this comment

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

Indeed this syntax leads to an error, with sunz_corrected] getting split into single characters:

[DEBUG: 2022-12-06 16:01:05 : satpy.node] Skipping optional DataQuery(name='solar_zenith_angle', calibration='reflectance'): Unknown dataset DataQuery(name='solar_zenith_angle', calibration='reflectance')
Traceback (most recent call last):
  File "/tcenas/home/strandgren/git/ext/py/satpy/latest/satpy/satpy/scene.py", line 1362, in _update_dependency_tree
    self._dependency_tree.populate_with_keys(needed_datasets, query)
  File "/tcenas/home/strandgren/git/ext/py/satpy/latest/satpy/satpy/dependency_tree.py", line 262, in populate_with_keys
    raise MissingDependencies(unknown_datasets, "Unknown datasets:")
satpy.node.MissingDependencies: Unknown datasets: {DataQuery(name='green'): {DataQuery(wavelength=0.85, modifiers=('s', 'u', 'n', 'z', '_', 'c', 'o', 'r', 'r', 'e', 'c', 't', 'e', 'd', ']')): {DataQuery(wavelength=0.85, modifiers=('s',))}}}

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/tcenas/home/strandgren/git/ext/py/satpy/latest/satpy/satpy/scene.py", line 1364, in _update_dependency_tree
    raise KeyError(str(err))
KeyError: "Unknown datasets: {DataQuery(name='green'): {DataQuery(wavelength=0.85, modifiers=('s', 'u', 'n', 'z', '_', 'c', 'o', 'r', 'r', 'e', 'c', 't', 'e', 'd', ']')): {DataQuery(wavelength=0.85, modifiers=('s',))}}}"

I have fixed this now, but I'm not sure what kind of (unit) test that would detect this kind of syntax? Did I miss something?

And regarding Polar2Grid you can wait with merging this if you want, no hurry from my side. Although, I have been very careful in making sure that it's fully backwards compatible, but I cannot not guarantee that I have not missed anything. For example the ratios of the green correction are not changing with this PR, the AHI true color images should look like before if the same composite names are used.

Copy link
Member

@djhoese djhoese left a comment

Choose a reason for hiding this comment

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

And regarding Polar2Grid you can wait with merging this if you want, no hurry from my side. Although, I have been very careful in making sure that it's fully backwards compatible, but I cannot not guarantee that I have not missed anything. For example the ratios of the green correction are not changing with this PR, the AHI true color images should look like before if the same composite names are used.

I see that now. Thank you for working so hard to preserve backward compatibility not just in the Python code but the YAML configuration for the composites as well. If there is no hurry on this then I'd like to wait a day or two at least before merging so I can straighten things out in Geo2Grid before the version 1.1 release. I can always force the commit SHA that we use in our builds, but we are also like a day away from release so I'd like to not risk anything if possible. I have a meeting about Geo2Grid tomorrow so I'll know more then.

Copy link
Member

@pnuu pnuu left a comment

Choose a reason for hiding this comment

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

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component:compositors enhancement code enhancements, features, improvements
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

None yet

6 participants