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 22, 2023
1 parent 1966033 commit a2e89cf
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 63 deletions.
105 changes: 46 additions & 59 deletions colour/colorimetry/generation.py
Expand Up @@ -467,14 +467,15 @@ def sd_gaussian_fwhm(
SpectralShape(360.0, 780.0, 1.0)
>>> sd[555] # doctest: +ELLIPSIS
1...
>>> sd[530] # doctest: +ELLIPSIS
0.3678794...
>>> 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 @@ -544,8 +545,8 @@ def sd_gaussian(
SpectralShape(360.0, 780.0, 1.0)
>>> sd[555] # doctest: +ELLIPSIS
1...
>>> sd[530] # doctest: +ELLIPSIS
0.3678794...
>>> 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
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 a2e89cf

Please sign in to comment.