Skip to content

Commit 708ded0

Browse files
committed
Fix incorrect colour.colorimetry.sd_gaussian_fwhm definition output.
References #1171.
1 parent 1966033 commit 708ded0

File tree

2 files changed

+59
-71
lines changed

2 files changed

+59
-71
lines changed

colour/colorimetry/generation.py

Lines changed: 54 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,8 @@ def sd_gaussian_normal(
409409
>>> sd = sd_gaussian_normal(555, 25)
410410
>>> sd.shape
411411
SpectralShape(360.0, 780.0, 1.0)
412-
>>> sd[555] # doctest: +ELLIPSIS
413-
1...
412+
>>> sd[555] # doctest: +SKIP
413+
1.0
414414
>>> sd[530] # doctest: +ELLIPSIS
415415
0.6065306...
416416
"""
@@ -465,16 +465,17 @@ def sd_gaussian_fwhm(
465465
>>> sd = sd_gaussian_fwhm(555, 25)
466466
>>> sd.shape
467467
SpectralShape(360.0, 780.0, 1.0)
468-
>>> sd[555] # doctest: +ELLIPSIS
469-
1...
470-
>>> sd[530] # doctest: +ELLIPSIS
471-
0.3678794...
468+
>>> sd[555] # doctest: +SKIP
469+
1.0
470+
>>> sd[530]
471+
0.0625
472472
"""
473473

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

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

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

@@ -505,7 +506,7 @@ def sd_gaussian(
505506
peak at.
506507
sigma_fwhm
507508
Standard deviation :math:`sigma` of the gaussian spectral distribution
508-
or Full width at half maximum, i.e. width of the gaussian spectral
509+
or full width at half maximum, i.e. width of the gaussian spectral
509510
distribution measured between those points on the *y* axis which are
510511
half the maximum amplitude.
511512
shape
@@ -535,17 +536,17 @@ def sd_gaussian(
535536
>>> sd = sd_gaussian(555, 25)
536537
>>> sd.shape
537538
SpectralShape(360.0, 780.0, 1.0)
538-
>>> sd[555] # doctest: +ELLIPSIS
539-
1...
539+
>>> sd[555] # doctest: +SKIP
540+
1.0
540541
>>> sd[530] # doctest: +ELLIPSIS
541542
0.6065306...
542543
>>> sd = sd_gaussian(555, 25, method="FWHM")
543544
>>> sd.shape
544545
SpectralShape(360.0, 780.0, 1.0)
545-
>>> sd[555] # doctest: +ELLIPSIS
546-
1...
547-
>>> sd[530] # doctest: +ELLIPSIS
548-
0.3678794...
546+
>>> sd[555] # doctest: +SKIP
547+
1.0
548+
>>> sd[530]
549+
0.0625
549550
"""
550551

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

558559
def sd_single_led_Ohno2005(
559560
peak_wavelength: float,
560-
fwhm: float,
561+
half_spectral_width: float,
561562
shape: SpectralShape = SPECTRAL_SHAPE_DEFAULT,
562563
**kwargs: Any,
563564
) -> SpectralDistribution:
564565
"""
565566
Return a single *LED* spectral distribution of given spectral shape at
566-
given peak wavelength and full width at half maximum according to
567-
*Ohno (2005)* method.
567+
given peak wavelength and half spectral width :math:`\\Delta\\lambda_{0.5}`
568+
according to *Ohno (2005)* method.
568569
569570
Parameters
570571
----------
571572
peak_wavelength
572573
Wavelength the single *LED* spectral distribution will peak at.
573-
fwhm
574-
Full width at half maximum, i.e. width of the underlying gaussian
575-
spectral distribution measured between those points on the *y* axis
576-
which are half the maximum amplitude.
574+
half_spectral_width
575+
Half spectral width :math:`\\Delta\\lambda_{0.5}`.
577576
shape
578577
Spectral shape used to create the spectral distribution.
579578
580579
Other Parameters
581580
----------------
582581
kwargs
583-
{:func:`colour.colorimetry.sd_gaussian_fwhm`},
584-
See the documentation of the previously listed definition.
582+
{:class:`colour.SpectralDistribution`},
583+
See the documentation of the previously listed class.
585584
586585
Returns
587586
-------
@@ -606,14 +605,18 @@ def sd_single_led_Ohno2005(
606605
1...
607606
"""
608607

609-
settings = {"name": f"{peak_wavelength}nm - {fwhm} FWHM LED - Ohno (2005)"}
608+
settings = {
609+
"name": f"{peak_wavelength}nm - {half_spectral_width} "
610+
f"Half Spectral Width LED - Ohno (2005)"
611+
}
610612
settings.update(kwargs)
611613

612-
sd = sd_gaussian_fwhm(peak_wavelength, fwhm, shape, **kwargs)
613-
614-
sd.values = (sd.values + 2 * sd.values**5) / 3
614+
values = np.exp(
615+
-(((shape.wavelengths - peak_wavelength) / half_spectral_width) ** 2)
616+
)
617+
values = (values + 2 * values**5) / 3
615618

616-
return sd
619+
return SpectralDistribution(values, shape.wavelengths, **settings)
617620

618621

619622
SD_SINGLE_LED_METHODS: CanonicalMapping = CanonicalMapping(
@@ -628,24 +631,18 @@ def sd_single_led_Ohno2005(
628631

629632
def sd_single_led(
630633
peak_wavelength: float,
631-
fwhm: float,
632634
shape: SpectralShape = SPECTRAL_SHAPE_DEFAULT,
633635
method: Literal["Ohno 2005"] | str = "Ohno 2005",
634636
**kwargs: Any,
635637
) -> SpectralDistribution:
636638
"""
637639
Return a single *LED* spectral distribution of given spectral shape at
638-
given peak wavelength and full width at half maximum according to given
639-
method.
640+
given peak wavelength according to given method.
640641
641642
Parameters
642643
----------
643644
peak_wavelength
644645
Wavelength the single *LED* spectral distribution will peak at.
645-
fwhm
646-
Full width at half maximum, i.e. width of the underlying gaussian
647-
spectral distribution measured between those points on the *y*
648-
axis which are half the maximum amplitude.
649646
shape
650647
Spectral shape used to create the spectral distribution.
651648
method
@@ -673,31 +670,30 @@ def sd_single_led(
673670
674671
Examples
675672
--------
676-
>>> sd = sd_single_led(555, 25)
673+
>>> sd = sd_single_led(555, half_spectral_width=25)
677674
>>> sd.shape
678675
SpectralShape(360.0, 780.0, 1.0)
679676
>>> sd[555] # doctest: +ELLIPSIS
680677
1...
681678
"""
682679

683680
method = validate_method(method, tuple(SD_SINGLE_LED_METHODS))
681+
kwargs["shape"] = shape
684682

685-
return SD_SINGLE_LED_METHODS[method](
686-
peak_wavelength, fwhm, shape, **kwargs
687-
)
683+
return SD_SINGLE_LED_METHODS[method](peak_wavelength, **kwargs)
688684

689685

690686
def sd_multi_leds_Ohno2005(
691687
peak_wavelengths: ArrayLike,
692-
fwhm: ArrayLike,
688+
half_spectral_widths: ArrayLike,
693689
peak_power_ratios: ArrayLike | None = None,
694690
shape: SpectralShape = SPECTRAL_SHAPE_DEFAULT,
695691
**kwargs: Any,
696692
) -> SpectralDistribution:
697693
"""
698694
Return a multi *LED* spectral distribution of given spectral shape at
699-
given peak wavelengths and full widths at half maximum according to
700-
*Ohno (2005)* method.
695+
given peak wavelengths, half spectral widths :math:`\\Delta\\lambda_{0.5}`
696+
and peak power ratios according to *Ohno (2005)* method.
701697
702698
The multi *LED* spectral distribution is generated using many single *LED*
703699
spectral distributions generated with :func:`colour.sd_single_led_Ohno2005`
@@ -708,10 +704,8 @@ def sd_multi_leds_Ohno2005(
708704
peak_wavelengths
709705
Wavelengths the multi *LED* spectral distribution will peak at, i.e.
710706
the peaks for each generated single *LED* spectral distributions.
711-
fwhm
712-
Full widths at half maximum, i.e. widths of the underlying gaussian
713-
spectral distributions measured between those points on the *y* axis
714-
which are half the maximum amplitude.
707+
half_spectral_widths
708+
Half spectral widths :math:`\\Delta\\lambda_{0.5}`.
715709
peak_power_ratios
716710
Peak power ratios for each generated single *LED* spectral
717711
distributions.
@@ -752,7 +746,9 @@ def sd_multi_leds_Ohno2005(
752746
"""
753747

754748
peak_wavelengths = as_float_array(peak_wavelengths)
755-
fwhm = np.resize(fwhm, peak_wavelengths.shape)
749+
half_spectral_widths = np.resize(
750+
half_spectral_widths, peak_wavelengths.shape
751+
)
756752
if peak_power_ratios is None:
757753
peak_power_ratios = ones(peak_wavelengths.shape)
758754
else:
@@ -762,11 +758,13 @@ def sd_multi_leds_Ohno2005(
762758

763759
sd = sd_zeros(shape)
764760

765-
for peak_wavelength, fwhm_s, peak_power_ratio in zip(
766-
peak_wavelengths, fwhm, peak_power_ratios
761+
for peak_wavelength, half_spectral_width, peak_power_ratio in zip(
762+
peak_wavelengths, half_spectral_widths, peak_power_ratios
767763
):
768764
sd += (
769-
sd_single_led_Ohno2005(peak_wavelength, fwhm_s, **kwargs)
765+
sd_single_led_Ohno2005(
766+
peak_wavelength, half_spectral_width, **kwargs
767+
)
770768
* peak_power_ratio
771769
)
772770

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

778776
sd.name = (
779777
f"{_format_array(peak_wavelengths)}nm - "
780-
f"{_format_array(fwhm)} FWHM - "
778+
f"{_format_array(half_spectral_widths)} FWHM - "
781779
f"{_format_array(peak_power_ratios)} Peak Power Ratios - "
782780
f"LED - Ohno (2005)"
783781
)
@@ -797,29 +795,19 @@ def _format_array(a: NDArrayFloat) -> str:
797795

798796
def sd_multi_leds(
799797
peak_wavelengths: ArrayLike,
800-
fwhm: ArrayLike,
801-
peak_power_ratios: ArrayLike | None = None,
802798
shape: SpectralShape = SPECTRAL_SHAPE_DEFAULT,
803799
method: Literal["Ohno 2005"] | str = "Ohno 2005",
804800
**kwargs: Any,
805801
) -> SpectralDistribution:
806802
"""
807803
Return a multi *LED* spectral distribution of given spectral shape at
808-
given peak wavelengths and full widths at half maximum according to given
809-
method.
804+
given peak wavelengths.
810805
811806
Parameters
812807
----------
813808
peak_wavelengths
814809
Wavelengths the multi *LED* spectral distribution will peak at, i.e.
815810
the peaks for each generated single *LED* spectral distributions.
816-
fwhm
817-
Full widths at half maximum, i.e. widths of the underlying gaussian
818-
spectral distributions measured between those points on the *y* axis
819-
which are half the maximum amplitude.
820-
peak_power_ratios
821-
Peak power ratios for each generated single *LED* spectral
822-
distributions.
823811
shape
824812
Spectral shape used to create the spectral distribution.
825813
method
@@ -849,8 +837,8 @@ def sd_multi_leds(
849837
--------
850838
>>> sd = sd_multi_leds(
851839
... np.array([457, 530, 615]),
852-
... np.array([20, 30, 20]),
853-
... np.array([0.731, 1.000, 1.660]),
840+
... half_spectral_widths=np.array([20, 30, 20]),
841+
... peak_power_ratios=np.array([0.731, 1.000, 1.660]),
854842
... )
855843
>>> sd.shape
856844
SpectralShape(360.0, 780.0, 1.0)
@@ -859,7 +847,6 @@ def sd_multi_leds(
859847
"""
860848

861849
method = validate_method(method, tuple(SD_MULTI_LEDS_METHODS))
850+
kwargs["shape"] = shape
862851

863-
return SD_MULTI_LEDS_METHODS[method](
864-
peak_wavelengths, fwhm, peak_power_ratios, shape, **kwargs
865-
)
852+
return SD_MULTI_LEDS_METHODS[method](peak_wavelengths, **kwargs)

colour/colorimetry/tests/test_generation.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,17 +187,18 @@ class TestSdGaussianFwhm(unittest.TestCase):
187187

188188
def test_sd_gaussian_fwhm(self):
189189
"""
190-
Test :func:`colour.colorimetry.generation.sd_gaussian_fwhm`
191-
definition.
190+
Test :func:`colour.colorimetry.generation.sd_gaussian_fwhm` definition.
192191
"""
193192

194193
sd = sd_gaussian_fwhm(555, 25)
195194

196-
self.assertAlmostEqual(sd[530], 0.367879441171443, places=7)
195+
self.assertAlmostEqual(sd[530], 0.0625, places=7)
197196

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

200-
self.assertAlmostEqual(sd[580], 0.367879441171443, places=7)
199+
self.assertAlmostEqual(sd[580], 0.062499999999999, places=7)
200+
201+
self.assertAlmostEqual(sd[555 - 25 / 2], 0.5, places=7)
201202

202203

203204
class TestSdSingleLedOhno2005(unittest.TestCase):

0 commit comments

Comments
 (0)