From 1dbda615460cefeee3f14d4459a16cd122708a60 Mon Sep 17 00:00:00 2001 From: Thomas Mansencal Date: Thu, 29 Jun 2023 20:47:46 +0200 Subject: [PATCH] Ensure that spectral distribution not starting or ending on a tenth wavelength and having an interval of 10 or 20 can be integrated using practise "ASTM E308-15". --- colour/colorimetry/spectrum.py | 5 +++ .../tests/test_tristimulus_values.py | 21 ++++++++++++ colour/colorimetry/tristimulus_values.py | 32 ++++++++++++++++--- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/colour/colorimetry/spectrum.py b/colour/colorimetry/spectrum.py index b87699672a..f22803caa4 100644 --- a/colour/colorimetry/spectrum.py +++ b/colour/colorimetry/spectrum.py @@ -1590,6 +1590,11 @@ def trim(self, shape: SpectralShape) -> Self: self.wavelengths = wavelengths self.values = values + if self.shape.boundaries != shape.boundaries: + runtime_warning( + f'"{shape}" shape could not be honoured, using "{self.shape}"!' + ) + return self def normalise(self, factor: Real = 1) -> Self: diff --git a/colour/colorimetry/tests/test_tristimulus_values.py b/colour/colorimetry/tests/test_tristimulus_values.py index ee034b9eca..44285c038d 100644 --- a/colour/colorimetry/tests/test_tristimulus_values.py +++ b/colour/colorimetry/tests/test_tristimulus_values.py @@ -1205,6 +1205,17 @@ def test_sd_to_XYZ_ASTME308_mi_10nm(self): decimal=7, ) + np.testing.assert_array_almost_equal( + sd_to_XYZ_ASTME308( + reshape_sd(self._sd, SpectralShape(401, 701, 10)), + self._cmfs, + self._A, + k=1, + ), + np.array([15.6713226093, 11.7392254489, 2.2117708792]), + decimal=7, + ) + def test_sd_to_XYZ_ASTME308_mi_20nm(self): """ Test :func:`colour.colorimetry.tristimulus_values.sd_to_XYZ_ASTME308` @@ -1310,6 +1321,16 @@ def test_sd_to_XYZ_ASTME308_mi_20nm(self): decimal=7, ) + np.testing.assert_array_almost_equal( + sd_to_XYZ_ASTME308( + reshape_sd(self._sd, SpectralShape(401, 701, 20)), + self._cmfs, + self._A, + ), + np.array([14.5220164311, 10.8790959535, 2.0490905325]), + decimal=7, + ) + def test_raise_exception_sd_to_XYZ_ASTME308(self): """ Test :func:`colour.colorimetry.tristimulus_values.sd_to_XYZ_ASTME308` diff --git a/colour/colorimetry/tristimulus_values.py b/colour/colorimetry/tristimulus_values.py index f4f018cf93..349325453b 100644 --- a/colour/colorimetry/tristimulus_values.py +++ b/colour/colorimetry/tristimulus_values.py @@ -859,7 +859,7 @@ def sd_to_XYZ_tristimulus_weighting_factors_ASTME308( if sd.shape.boundaries != cmfs.shape.boundaries: runtime_warning( - f'Trimming "{illuminant.name}" spectral distribution shape to ' + f'Trimming "{sd.name}" spectral distribution boundaries using ' f'"{cmfs.name}" colour matching functions shape.' ) sd = reshape_sd(sd, cmfs.shape, "Trim", copy=False) @@ -875,6 +875,7 @@ def sd_to_XYZ_tristimulus_weighting_factors_ASTME308( W = adjust_tristimulus_weighting_factors_ASTME308( W, SpectralShape(start_w, end_w, sd.shape.interval), sd.shape ) + R = sd.values XYZ = np.sum(W * R[..., None], axis=0) @@ -1010,6 +1011,18 @@ def sd_to_XYZ_ASTME308( "with measurement interval of 1, 5, 10 or 20nm!" ) + if sd.shape.interval in (10, 20) and ( + sd.shape.start % 10 != 0 or sd.shape.end % 10 != 0 + ): + runtime_warning( + f'"{sd.name}" spectral distribution shape does not start at a ' + f'tenth and will be aligned to "{cmfs.name}" colour matching ' + 'functions shape! Note that practise "ASTM E308-15" does not ' + "define a behaviour in this case." + ) + + sd = reshape_sd(sd, cmfs.shape, copy=False) + if use_practice_range: # pylint: disable=E1102 cmfs = reshape_msds(cmfs, SPECTRAL_SHAPE_ASTME308, "Trim", copy=False) @@ -1031,13 +1044,17 @@ def sd_to_XYZ_ASTME308( sd = sd.copy() if sd.shape.boundaries != cmfs.shape.boundaries: runtime_warning( - f'Trimming "{illuminant.name}" spectral distribution shape to ' + f'Trimming "{sd.name}" spectral distribution shape to ' f'"{cmfs.name}" colour matching functions shape.' ) - sd.trim(cmfs.shape) + sd = reshape_sd(sd, cmfs.shape, "Trim", copy=False) # Extrapolation of additional 20nm padding intervals. - sd.align(SpectralShape(sd.shape.start - 20, sd.shape.end + 20, 10)) + sd = reshape_sd( + sd, + SpectralShape(sd.shape.start - 20, sd.shape.end + 20, 10), + copy=False, + ) for i in range(2): sd[sd.wavelengths[i]] = ( 3 * sd.values[i + 2] - 3 * sd.values[i + 4] + sd.values[i + 6] @@ -1060,7 +1077,12 @@ def sd_to_XYZ_ASTME308( ) # Discarding the additional 20nm padding intervals. - sd.trim(SpectralShape(sd.shape.start + 20, sd.shape.end - 20, 10)) + sd = reshape_sd( + sd, + SpectralShape(sd.shape.start + 20, sd.shape.end - 20, 10), + "Trim", + copy=False, + ) XYZ = method(sd, cmfs, illuminant, k=k)