Open strandgren opened 1 year ago
This is very interesting! As this follows a non linear approach to correction I think it would have fixed issues I ran into when trying to get the overall balance between strength, thresh and max zen. I've now moved onto the JMA method of blending the uncorrected image so unfortunately wont be able to provide much technical assistance.
Background
The built-in method (reduce_rayleigh_highzenith)](https://github.com/pytroll/pyspectral/blob/main/pyspectral/rayleigh.py#L287) offers a way to linearly reduce the Rayleigh correction at high sun zenith angles in order to compensate for the fact that RTM models and thus the Rayleigh correction computation breaks down at large angles. This reduction Rayleigh correction can be defined/tuned using three parameters:
thres_zen
: the lower sun zenith angle limit, i.e. where to start reducing the Rayleigh correction.maxzen
: the upper sun zenith angle limit, typically where to the Rayleigh correction is completely removed but can be ambiguous (see below).strength
: the aggressiveness of the of the Rayleigh correction reduction betweenthres_zen
andmaxzen
, i.e. the steepness of the linear Rayleigh reduction function that starts decreasing atthres_zen
.Using
strength=1.0
will result in full Rayleigh correction atthres_zen
and zero Rayleigh correction atmaxzen
(and beyond), with a linear decrease in between. Astrength
below1.0
will reduce the slope of the linear decrease and thus shift the point of zero Rayleigh correction to a larger angle.New feature proposal
To make the transition from full to no Rayleigh correction smoother I suggest to use a smoothstep function for the Rayleigh reduction rather than the current linear function. This could better capture the non-linear behavior at large angles. Below is an example of a smoothstep function where the
strength
is kept and still controls the steepness of the reduction betweenthres_zen
andmaxzen
:Note that
thres_zen
andmaxzen
always define the points of full and zero Rayleigh correction, respectively, independent ofstrength
, as opposed the the current linear scaling function. Furthermore, the the smoothstep function used here simplifies to a linear function ifstrength=1.0
, hence preserving the current functionality and backwards compatibility.Below are two examples of an AHI true color RGB with the current linear reduction function (left, current main) and a slight non-linear reduction function (right, proposed feature):
thresh_zen=70
,maxzen=105
,strength=1.0
thresh_zen=70
,maxzen=105
,strength=1.5
Although the differences may not strike as significant, the non-linear reduction function clearly results in more vivid colors in eastern Australia and Monglia as a result of slower reduction in the Rayleigh correction. This is a single example and there might be more optimized tuning settings for the current linear implementation. However, this is also true for the non-linear example and the the proposed non-linear function including the tunable steepness parameter
strength
in combination with different combinations ofthres_zen
andmaxzen
should offer even more extensive tuning and optimization possibilities of the Rayleigh correction reduction.If this is considered a useful feature, I would be happy to make a PR since I have most of the the code ready.
Open question
The main question is how to integrate this into the current main with minimum changes for other users and full backwards compatibility.
Actually I would be in favor of removing the current functionality of the
strength
parameter which simply changes the steepness of the linear reduction function and increases the sun zenith angle at with the Rayleigh correction is completely removed. For any value ofstrength
less than 1.0 it's not transparent to the user at which sun zenith angle the Rayleigh correction reaches zero. I would rather be in favor of keeping the linear strength constant (=1.0
) and let the user modifymaxzen
accordingly instead, which would give the user full transparency sincemaxzen
would always define the point where the Rayleigh correction is completely removed. The figure below shows how the linear reduction function for constantthres_zen
/maxzen
and variablestrength
can be replicated simply using variablemaxzen
and constantstrength
(=1.0
)):Suggested solution
Given the fact that:
strength
is only valid for the range [0.0, 1.0], andstrength
is only valid for the range [1.0, inf)I suggest the following:
Short-term implementation (following PR):
strength < 1.0
compute the Rayleigh reduction following the current linear implementation.strength >= 1.0
compute the Rayleigh reduction following the non-linear smoothstep function proposed above.strength < 1.0
will loose support and that users shall modifymaxzen
instead to weaken the "strength" of the linear decrease.Long-term implementation (a couple of releases after suggested PR is released):
strength < 1.0
: Remove deprecation warning and throw error that this is an invalid strength.One could also implement the proposed non-linear function independently, but given the fact that any change to current
strength
can be achieved by increasingmaxzen
, I think the above would be the most clean solution. But if preferred, one could also skip the proposed deprecation warning and long-term implementation and simply have different behavior forstrength=[0.0, 1.0)
(current functionality with linear scaling) andstrength=[1.0, inf)
(new proposed non-linear scaling).Before making a PR I would be happy to hear any feedback on this, especially from e.g. @simonrp84 , @mherbertson and @yukaribbba who have implemented and/or shown interest in the current Rayleigh reduction functionality :)