Skip to content

Commit

Permalink
Refactor code for applying non-linearity and computing blend fractions.
Browse files Browse the repository at this point in the history
  • Loading branch information
strandgren committed Sep 18, 2023
1 parent ed1c4a1 commit 049a2a3
Showing 1 changed file with 28 additions and 6 deletions.
34 changes: 28 additions & 6 deletions satpy/composites/spectral.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,17 +169,39 @@ def __call__(self, projectables, optional_datasets=None, **attrs):
ndvi.data = da.where(ndvi > self.ndvi_min, ndvi, self.ndvi_min)
ndvi.data = da.where(ndvi < self.ndvi_max, ndvi, self.ndvi_max)

# Apply non-linearity to the ndvi for a non-linear conversion from ndvi to fraction. This can be used for a
# slower or faster transision to higher/lower fractions at the ndvi extremes. If strength equals 1.0, this
# operation has no effect on the ndvi.
# Introduce non-linearity to ndvi for non-linear scaling to NIR blend fraction
if self.strength != 1.0: # self._apply_strength() has no effect if strength = 1.0 -> no non-linear behaviour
ndvi = self._apply_strength(ndvi)

# Compute pixel-level NIR blend fractions from ndvi
fraction = self._compute_blend_fraction(ndvi)

# Prepare input as required by parent class (SpectralBlender)
self.fractions = (1 - fraction, fraction)

return super().__call__([projectables[0], projectables[2]], **attrs)

def _apply_strength(self, ndvi):
"""Introduce non-linearity by applying strength factor.
The method introduces non-linearity to the ndvi for a non-linear scaling from ndvi to blend fraction in
`_compute_blend_fraction`. This can be used for a slower or faster transision to higher/lower fractions
at the ndvi extremes. If strength equals 1.0, this operation has no effect on the ndvi.
"""
ndvi = ndvi ** self.strength / (ndvi ** self.strength + (1 - ndvi) ** self.strength)

# Compute blending fraction from ndvi
return ndvi

def _compute_blend_fraction(self, ndvi):
"""Compute pixel-level fraction of NIR signal to blend with native green signal.
This method linearly scales the input ndvi values to pixel-level blend fractions within the range
`[limits[0], limits[1]]` following this implementation <https://stats.stackexchange.com/a/281164>.
"""
fraction = (ndvi - self.ndvi_min) / (self.ndvi_max - self.ndvi_min) * (self.limits[1] - self.limits[0]) \
+ self.limits[0]
self.fractions = (1 - fraction, fraction)

return super().__call__([projectables[0], projectables[2]], **attrs)
return fraction


class GreenCorrector(SpectralBlender):
Expand Down

0 comments on commit 049a2a3

Please sign in to comment.