Refactor code for Sun zenith angle corrections and change to effective_solar_pathlength_corrected instead of sunz_corrected for built-in RGB recipes#3397
Conversation
…ation and logging.
… ffunctionality to cap/reduce the correction.
…s already been applied.
I think in general I'm not against this PR "in spirit". The one thing I had trouble with when trying to switch to effective path length as described in your point above is that for some readers the However, I think this means that for VIIRS composites we'd have to redefine the |
|
You could always reverse the |
|
🤔 I'd prefer not to. |
|
@djhoese I understand the concern, but if I understand the comment correctly I don't think the proposed changes would be a problem and no significant change to the current behavior. Now the default
Does that make sense and sound ok for you you, or did I miss something else? I'll try to implement my suggested changes today such that it's more clear what I propose, and then we can see i the review process if this is acceptable or if I should revert something. |
|
What you say makes sense but I can't tell if you're saying we would still need to do what I mentioned. That is, VIIRS composites would need to use "sunz_corrected" for RGBs but either have to:
|
- Fix bug to make sure that custom sza values are used when actually intended and pass as optional_dataset instead of as a projectable. - Use different sza values in order to be able to properly test the available options concerning correction_limit and max_sza. - Add tests for more combinations of correction_limit and max_sza
…eSolarPathLengthCorrector
…sed as expected. Fix expected values to pass updated values of sunz_sza.
Indeed, I think that's needed unless the dependency tree is modified. In the end I went for Option 2 above, which I think is the best solution for now. |
|
This PR is now ready for review 🙂 Two important points/questions at this point:
|
|
Here are some FCI and SEVIRI images (using built-in recipes) in support of the changes in this PR, temporarily also available in a PDF here: https://sftp.eumetsat.int/public/file/abx2zrqqyuc6koinualwra/satpy_pr3397.pdf.
|
…loud_type_sunz_reduced and cloud_phase_sunz_reduced recipes given clear benefit of more data being retained without it, without obvious artefacts, as well as alternative tuning by CHMI to reduce saturation.
ameraner
left a comment
There was a problem hiding this comment.
Nice work, thanks! The only thing I find a bit of a pity is that the default true_color now gets back the reddish clouds at the terminator. But I can see the point of being consistent with all the other recipes and wanting to keep as much daytime as possible, and there's now also true_color_sunz_reduced as an alternative option that is close to the old appearance.
Just a suggestion inline.
Co-authored-by: Andrea Meraner <49722768+ameraner@users.noreply.github.com>
…odifiers" This reverts commit f2053c0.
…rrected for sun zenith angle modifier
…o not change any user behaviour and change back later for v1.0
…orresponding warnings. this is now handled centrally in SunZenithCorrector, which will only have a change of default behaviour in v1.0
As per our discussion in the monthly meeting I have now modified this PR to do the following:
|
|
Could we add an option to If this is done, would you also need to update some of the FCI "uncorrecting" logic? I think it was FCI or maybe AHI? |
Working with the satpy.config is new territory for me, but I will have a look. So the benefit is that you can change the behavior of all of satpy without having to change any code or roll-back to another version? In general I don't see a huge advantage, since we want to get away from the current default correction, but I guess it helps users during migration. Or what is the main argument for this?
For FCI (and all other instruments/recipes) there wouldn't be any issue since we no longer use the |
|
RE uncorrecting: I have some memory of you coming up with some correction "reduction" when you were working on geo_color in Satpy to make the sunz correction not so aggressive. Or something like that. RE satpy.config: The idea would be to implement a "feature flag" essentially. This is kind of what I talked about in the meeting. The idea is that someone using satpy pre-1.0 could use Satpy as-is and get the same output as before, but when they are ready they can set It would come down to adding something to if some_limit == "__default__":
if satpy.config.get("sunz_legacy_defaults", True):
some_limit = 88
else:
# no correctionWith maybe a warning added to the |
|
Alright, I will look into that, thanks for elaborating 🙂 Regarding the "uncorrection", we worked on it for FCI indeed and we call it But again, the changes to the the default reduction of the |







This PR aims to clarify the code used for the Sun zenith angle corrections in satpy, including improving documentation and log messages to make it more transparent to the user. Furthermore, the default behavior of the
SunZenithCorrector/sunz_correctedmodifier is changed to remove the default reduction at high angles in order to compute the true reflectance. Finally, the built-in recipes are modified to improve imagery and comply with the recommendation from the WMO RGB workshop in Norrkoeping in April 2025.Background
In satpy we have two corrections for the Solar zenith angle/Solar path length available, the standard
SunZenithCorrectorwhich applies the1/cos(sunz)correction and theEffectiveSolarPathLengthCorrectorwhich applies the parameterization proposed by Li and Shibata (2006).There is also a default reduction of the correction starting at a given Sun zenith angle (88 degrees). This is intended for (RGB) imagery to avoid overcorrection at very large angles. However, this is not desirable for quantitative or scientific use of the data, where the standard
1/cos(sunz)should be used as is in order to compute the true reflectance. This functionality for capping/reduction has also been implemented in theEffectiveSolarPathLengthCorrector(duplicate code), but as shown in #3096 this reduction doesn't have any added value for the Li and Shibata parameterization, which works best as is, since it already accounts for the overcorrection at higher angles. For this reason, it was also agreed at the WMO RGB workshop in Spring 2025, that the Li and Shibata parameterization should be the recommended method for normalizing the data for the Solar zenith angle (without any capping or reduction).Furthermore, some datasets come with the
1/cos(sunz)already applied, in which case thesunz_correctedmodifier is attached to the dataset. However, this is not accurate since the default satpysunz_correctedmodifier is not only the simple1/cos(sunz), but also includes the reduction of the correction at higher Solar zenith angels. Therefore it would also be good if the defaultsunz_correctedwould rather be the simple1/cos(sunz)corrected, which would then be in-line with these datasets and also allow users in general to compute the true reflectance - this becomes even more relevant with #3292 where we clearly separate between "reflectance" data normalized by the Solar zenith angel and not.Changes in this PR
In response to the points above this PR includes the following changes:
Python code:
EffectiveSolarPathLengthCorrectormodifier. The paramters for this are still kept as valid input to avoid run-time errors if provided, but have no effect. A warning is issues if provided.EffectiveSolarPathLengthCorrectorto the same place as the other Solar zenith angle correction methods (./satpy/satpy/modifiers/angles.py)SunZenithCorrectorand underlying methods to make the functionality more clear.Change the default behavior ofKept as is for now, to be changed for satpy v1.0.SunZenithCorrectorto compute the true reflectance without any reduction of the the correction.SunZenithCorrectorandEffectiveSolarPathLengthCorrector, also highlighting the differences between the two and clarify that the former can be used to compute the true reflectance, whereas the latter is tailored for imagery.map_blocksyaml-recipes
effective_solar_pathlength_correctedmodifier instead ofsunz_correctedfor the solar zenith angle correction. As demonstrated in Standardize the correction for atmospheric path length for solar channels #3096 this leads to better imagery and was also suggested as recommendation at WMO RGB workshop in spring 2025.effective_solar_pathlength_correctedmodifier instead ofsunz_correctedfor the solar zenith angle correction of the red band used for reduced correction over clouds. This is done sincesunz_correctedis changing to become the simple 1/cos(sunz) correction which would not work well for imagery purposes since the reflectance of the red band would become 0 for angles larger than 90 degrees and thus break the Rayleigh correction. The Rayleigh correction reduction over clouds would also not work well close to 90 degrees, since also clear-sky becomes very bright at high sun zenith angles with the1/cos(sunz)correction.sunz_reducedmodifier for FCItrue_color,cloud_phaseandcloud_typeRGBs to be in-line with other sensors and recommendation from RGB workshop. Additionaltrue_color_sunz_reducedcomposite is added to still support the generation of this RGB with a smoother transition into deep-space.Special cases
Some readers provide the reflectance data with the
1/cos(sunz)correction already applied, in which case thesunz_correctedmodifier is already attached to the dataset. This is the case for the following readers:For
meris_nc_sen3,olci_l2andclavrxthere are no pre-configured RGB recipes, so the changes in this PR are not relevant for these data. Formsi_safe_l2athe data have the dedicated modifieresa_sunz_correctedattached to them, which is also used for the corresponding RGB recipes. Hence, the changes in the PR are not relevant for these data either.The only relevant one is VIIRS (SDR). Since the VIIRS SDR data come with the Solar zenith angle correction already applied, the dataset gets the
sunz_correctedmodifier attached. However, VIIRS L1B data come without the1/cos(sunz)correction and therefore nosunz_correctedmodifier is attached to the dataset.For this reason, we can use theEffectiveSolarPathLengthCorrectormodifier for the recipes, but we have to name itsunz_corrected, in order for satpy to understand that this is equivalent to the sunz correction already in the SDR data in the sense that no further correction should be applied.A better and more generic solution would be to modify the dependency tree to know that if the user requests a dataset with theeffective_solar_pathlength_correctedmodifier, but only finds a DataID with the modifiersunz_corrected, it would be regarded as equivalent and a substitute for theeffective_solar_pathlength_correctedmodifier. However, such a solution is outside the scope of this PR.After the monthly meeting on June 2, it was agreed to use the regular
effective_solar_pathlength_correctedmodifier also for VIIRS data. Currently this won't work with VIIRS SDR data, since satpy will fail to find the "base" version of the requested without modifiers. It was agreed that this should be solved by adding the unnormalized_reflectance calibration level to theviirs_sdrreader once #3292 is merged, see details in #3411. We then just need to make sure that the VIIRS composites specify the expected calibration level in the composite and/or modifier recipes.Changes for users and backwards incompatibility
sunz_correctedmodifier at 88 degrees. See Standardize the correction for atmospheric path length for solar channels #3096 and comments in the PR for examples.sunz_reducedmodifier leads to significantly more data being retained/visible close to the terminator. see examples below.effective_solar_pathlength_correctedmodifier has been removed as it's not needed, given that the Li and Shibata parameterization already deals with the over-correction at high solar zenith angels. If the reduction parameters are still provided they will be accepted but ignored and a warning is raised.effective_solar_pathlength_correctedmodifier will not be possible with VIIRS SDR data until Addunnormalized_reflectanceto VIIRS SDR (viirs_sdr) reader #3411 has been fixed.The default reduction of thesunz_correctedhas been disabled (but still with support to apply it if needed). Hence, thesunz_correctedmodifier will compute the true reflectance if applied with it's new default configuration. This will impact local composites which use the upstreamsunz_correctedmodifiers defined in satpy (except for VIIRS which is treated differently given the differences between the L1B and SDR data). The result will be very bright imagery close to 90 degrees and no data beyond 90 degrees. A warning has been added when using these modifiers to inform users on this change and how to fix it.Similarly, if users have defined there own localsunz_correctedmodifier with default configuration (i.e. nocorrection_limitormax_sza), the imagery will change close to the terminator (again becoming very bright close to 90 degrees and black beyond).Following the monthly meeting on June 2, this PR has been changed such that there are no changes to the default values in
SunZenithCorrectoror corresponding pre-configuredsunz_correctedmodifiers in satpy at this point. Instead we will change this in v1.0 (#3412) and a warning is therefore now raised about this upcoming change if the default values ofSunZenithCorrectorare used.AI was used to support this PR, mainly for refactoring tests and writing doc-strings