Skip to content

Commit

Permalink
Fix incorrect colour.colorimetry.sd_gaussian_fwhm definition output.
Browse files Browse the repository at this point in the history
References #1171.
  • Loading branch information
KelSolaar committed Jul 23, 2023
1 parent 1966033 commit 708ded0
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 71 deletions.
121 changes: 54 additions & 67 deletions colour/colorimetry/generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,8 @@ def sd_gaussian_normal(
>>> sd = sd_gaussian_normal(555, 25)
>>> sd.shape
SpectralShape(360.0, 780.0, 1.0)
>>> sd[555] # doctest: +ELLIPSIS
1...
>>> sd[555] # doctest: +SKIP
1.0
>>> sd[530] # doctest: +ELLIPSIS
0.6065306...
"""
Expand Down Expand Up @@ -465,16 +465,17 @@ def sd_gaussian_fwhm(
>>> sd = sd_gaussian_fwhm(555, 25)
>>> sd.shape
SpectralShape(360.0, 780.0, 1.0)
>>> sd[555] # doctest: +ELLIPSIS
1...
>>> sd[530] # doctest: +ELLIPSIS
0.3678794...
>>> sd[555] # doctest: +SKIP
1.0
>>> sd[530]
0.0625
"""

settings = {"name": f"{peak_wavelength}nm - {fwhm} FWHM - Gaussian"}
settings.update(kwargs)

values = np.exp(-(((shape.wavelengths - peak_wavelength) / fwhm) ** 2))
mu, sigma = peak_wavelength, fwhm / (2 * np.sqrt(2 * np.log(2)))
values = np.exp(-((shape.wavelengths - mu) ** 2) / (2 * sigma**2))

return SpectralDistribution(values, shape.wavelengths, **settings)

Expand Down Expand Up @@ -505,7 +506,7 @@ def sd_gaussian(
peak at.
sigma_fwhm
Standard deviation :math:`sigma` of the gaussian spectral distribution
or Full width at half maximum, i.e. width of the gaussian spectral
or full width at half maximum, i.e. width of the gaussian spectral
distribution measured between those points on the *y* axis which are
half the maximum amplitude.
shape
Expand Down Expand Up @@ -535,17 +536,17 @@ def sd_gaussian(
>>> sd = sd_gaussian(555, 25)
>>> sd.shape
SpectralShape(360.0, 780.0, 1.0)
>>> sd[555] # doctest: +ELLIPSIS
1...
>>> sd[555] # doctest: +SKIP
1.0
>>> sd[530] # doctest: +ELLIPSIS
0.6065306...
>>> sd = sd_gaussian(555, 25, method="FWHM")
>>> sd.shape
SpectralShape(360.0, 780.0, 1.0)
>>> sd[555] # doctest: +ELLIPSIS
1...
>>> sd[530] # doctest: +ELLIPSIS
0.3678794...
>>> sd[555] # doctest: +SKIP
1.0
>>> sd[530]
0.0625
"""

method = validate_method(method, tuple(SD_GAUSSIAN_METHODS))
Expand All @@ -557,31 +558,29 @@ def sd_gaussian(

def sd_single_led_Ohno2005(
peak_wavelength: float,
fwhm: float,
half_spectral_width: float,
shape: SpectralShape = SPECTRAL_SHAPE_DEFAULT,
**kwargs: Any,
) -> SpectralDistribution:
"""
Return a single *LED* spectral distribution of given spectral shape at
given peak wavelength and full width at half maximum according to
*Ohno (2005)* method.
given peak wavelength and half spectral width :math:`\\Delta\\lambda_{0.5}`
according to *Ohno (2005)* method.
Parameters
----------
peak_wavelength
Wavelength the single *LED* spectral distribution will peak at.
fwhm
Full width at half maximum, i.e. width of the underlying gaussian
spectral distribution measured between those points on the *y* axis
which are half the maximum amplitude.
half_spectral_width
Half spectral width :math:`\\Delta\\lambda_{0.5}`.
shape
Spectral shape used to create the spectral distribution.
Other Parameters
----------------
kwargs
{:func:`colour.colorimetry.sd_gaussian_fwhm`},
See the documentation of the previously listed definition.
{:class:`colour.SpectralDistribution`},
See the documentation of the previously listed class.
Returns
-------
Expand All @@ -606,14 +605,18 @@ def sd_single_led_Ohno2005(
1...
"""

settings = {"name": f"{peak_wavelength}nm - {fwhm} FWHM LED - Ohno (2005)"}
settings = {
"name": f"{peak_wavelength}nm - {half_spectral_width} "
f"Half Spectral Width LED - Ohno (2005)"
}
settings.update(kwargs)

sd = sd_gaussian_fwhm(peak_wavelength, fwhm, shape, **kwargs)

sd.values = (sd.values + 2 * sd.values**5) / 3
values = np.exp(
-(((shape.wavelengths - peak_wavelength) / half_spectral_width) ** 2)
)
values = (values + 2 * values**5) / 3

return sd
return SpectralDistribution(values, shape.wavelengths, **settings)


SD_SINGLE_LED_METHODS: CanonicalMapping = CanonicalMapping(
Expand All @@ -628,24 +631,18 @@ def sd_single_led_Ohno2005(

def sd_single_led(
peak_wavelength: float,
fwhm: float,
shape: SpectralShape = SPECTRAL_SHAPE_DEFAULT,
method: Literal["Ohno 2005"] | str = "Ohno 2005",
**kwargs: Any,
) -> SpectralDistribution:
"""
Return a single *LED* spectral distribution of given spectral shape at
given peak wavelength and full width at half maximum according to given
method.
given peak wavelength according to given method.
Parameters
----------
peak_wavelength
Wavelength the single *LED* spectral distribution will peak at.
fwhm
Full width at half maximum, i.e. width of the underlying gaussian
spectral distribution measured between those points on the *y*
axis which are half the maximum amplitude.
shape
Spectral shape used to create the spectral distribution.
method
Expand Down Expand Up @@ -673,31 +670,30 @@ def sd_single_led(
Examples
--------
>>> sd = sd_single_led(555, 25)
>>> sd = sd_single_led(555, half_spectral_width=25)
>>> sd.shape
SpectralShape(360.0, 780.0, 1.0)
>>> sd[555] # doctest: +ELLIPSIS
1...
"""

method = validate_method(method, tuple(SD_SINGLE_LED_METHODS))
kwargs["shape"] = shape

return SD_SINGLE_LED_METHODS[method](
peak_wavelength, fwhm, shape, **kwargs
)
return SD_SINGLE_LED_METHODS[method](peak_wavelength, **kwargs)


def sd_multi_leds_Ohno2005(
peak_wavelengths: ArrayLike,
fwhm: ArrayLike,
half_spectral_widths: ArrayLike,
peak_power_ratios: ArrayLike | None = None,
shape: SpectralShape = SPECTRAL_SHAPE_DEFAULT,
**kwargs: Any,
) -> SpectralDistribution:
"""
Return a multi *LED* spectral distribution of given spectral shape at
given peak wavelengths and full widths at half maximum according to
*Ohno (2005)* method.
given peak wavelengths, half spectral widths :math:`\\Delta\\lambda_{0.5}`
and peak power ratios according to *Ohno (2005)* method.
The multi *LED* spectral distribution is generated using many single *LED*
spectral distributions generated with :func:`colour.sd_single_led_Ohno2005`
Expand All @@ -708,10 +704,8 @@ def sd_multi_leds_Ohno2005(
peak_wavelengths
Wavelengths the multi *LED* spectral distribution will peak at, i.e.
the peaks for each generated single *LED* spectral distributions.
fwhm
Full widths at half maximum, i.e. widths of the underlying gaussian
spectral distributions measured between those points on the *y* axis
which are half the maximum amplitude.
half_spectral_widths
Half spectral widths :math:`\\Delta\\lambda_{0.5}`.
peak_power_ratios
Peak power ratios for each generated single *LED* spectral
distributions.
Expand Down Expand Up @@ -752,7 +746,9 @@ def sd_multi_leds_Ohno2005(
"""

peak_wavelengths = as_float_array(peak_wavelengths)
fwhm = np.resize(fwhm, peak_wavelengths.shape)
half_spectral_widths = np.resize(
half_spectral_widths, peak_wavelengths.shape
)
if peak_power_ratios is None:
peak_power_ratios = ones(peak_wavelengths.shape)
else:
Expand All @@ -762,11 +758,13 @@ def sd_multi_leds_Ohno2005(

sd = sd_zeros(shape)

for peak_wavelength, fwhm_s, peak_power_ratio in zip(
peak_wavelengths, fwhm, peak_power_ratios
for peak_wavelength, half_spectral_width, peak_power_ratio in zip(
peak_wavelengths, half_spectral_widths, peak_power_ratios
):
sd += (
sd_single_led_Ohno2005(peak_wavelength, fwhm_s, **kwargs)
sd_single_led_Ohno2005(
peak_wavelength, half_spectral_width, **kwargs
)
* peak_power_ratio
)

Expand All @@ -777,7 +775,7 @@ def _format_array(a: NDArrayFloat) -> str:

sd.name = (
f"{_format_array(peak_wavelengths)}nm - "
f"{_format_array(fwhm)} FWHM - "
f"{_format_array(half_spectral_widths)} FWHM - "
f"{_format_array(peak_power_ratios)} Peak Power Ratios - "
f"LED - Ohno (2005)"
)
Expand All @@ -797,29 +795,19 @@ def _format_array(a: NDArrayFloat) -> str:

def sd_multi_leds(
peak_wavelengths: ArrayLike,
fwhm: ArrayLike,
peak_power_ratios: ArrayLike | None = None,
shape: SpectralShape = SPECTRAL_SHAPE_DEFAULT,
method: Literal["Ohno 2005"] | str = "Ohno 2005",
**kwargs: Any,
) -> SpectralDistribution:
"""
Return a multi *LED* spectral distribution of given spectral shape at
given peak wavelengths and full widths at half maximum according to given
method.
given peak wavelengths.
Parameters
----------
peak_wavelengths
Wavelengths the multi *LED* spectral distribution will peak at, i.e.
the peaks for each generated single *LED* spectral distributions.
fwhm
Full widths at half maximum, i.e. widths of the underlying gaussian
spectral distributions measured between those points on the *y* axis
which are half the maximum amplitude.
peak_power_ratios
Peak power ratios for each generated single *LED* spectral
distributions.
shape
Spectral shape used to create the spectral distribution.
method
Expand Down Expand Up @@ -849,8 +837,8 @@ def sd_multi_leds(
--------
>>> sd = sd_multi_leds(
... np.array([457, 530, 615]),
... np.array([20, 30, 20]),
... np.array([0.731, 1.000, 1.660]),
... half_spectral_widths=np.array([20, 30, 20]),
... peak_power_ratios=np.array([0.731, 1.000, 1.660]),
... )
>>> sd.shape
SpectralShape(360.0, 780.0, 1.0)
Expand All @@ -859,7 +847,6 @@ def sd_multi_leds(
"""

method = validate_method(method, tuple(SD_MULTI_LEDS_METHODS))
kwargs["shape"] = shape

return SD_MULTI_LEDS_METHODS[method](
peak_wavelengths, fwhm, peak_power_ratios, shape, **kwargs
)
return SD_MULTI_LEDS_METHODS[method](peak_wavelengths, **kwargs)
9 changes: 5 additions & 4 deletions colour/colorimetry/tests/test_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,17 +187,18 @@ class TestSdGaussianFwhm(unittest.TestCase):

def test_sd_gaussian_fwhm(self):
"""
Test :func:`colour.colorimetry.generation.sd_gaussian_fwhm`
definition.
Test :func:`colour.colorimetry.generation.sd_gaussian_fwhm` definition.
"""

sd = sd_gaussian_fwhm(555, 25)

self.assertAlmostEqual(sd[530], 0.367879441171443, places=7)
self.assertAlmostEqual(sd[530], 0.0625, places=7)

self.assertAlmostEqual(sd[555], 1, places=7)

self.assertAlmostEqual(sd[580], 0.367879441171443, places=7)
self.assertAlmostEqual(sd[580], 0.062499999999999, places=7)

self.assertAlmostEqual(sd[555 - 25 / 2], 0.5, places=7)


class TestSdSingleLedOhno2005(unittest.TestCase):
Expand Down

0 comments on commit 708ded0

Please sign in to comment.