Skip to content

Commit ca0bba3

Browse files
tjdcsKelSolaar
andauthored
PR: Improve CFI 2017 and TM30-18 Performance (#1120)
* Update various docstrings. * 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". * Implement support for better `ndarray` copy management in `colour.continuous.Signal` class. * Optionally compute hue quadrature * Optimize blackbody spectrum generation * Reshape within the daylight spectrum function * Optimize CCT computation * lazy compute NPM for RGB spaces Saves a ton of time on first colour import * Various speedups in CFI17 Re-architect output types TCS computation vectorize instead of list comp * Use shape broadcasting to skip list comprehension * Improve hashing speed of signals * Improve spectrum init time * address review and tests * accelerate hash functions * switch to optional xxhash feature * Remove illuminant modifications side effect * re-architect output to include CAM * Re-evaluate speed in planck generation * Improve default interpolation performance Repair documenation build error fix test due to default interpolation change [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci fix peculier init case in MaxOS environment fix type checking Auto stash before revert of "Improve default interpolation performance" * fix tests fix domain / range copy on signal init fix doctests * trim could cause an incorrect result in some edge cases (neq interval) * Hash signal objects now that we have the power of xxhash * resolve old comments on PR * Improve hue quadrature computation consistency in CAMs. * Improve spectral generator default interpolation changes. - Remove unnecessary interpolator change. - Improve documentation around spectral generator interpolation changes. * Improve unit tests for `colour.planck_law` definition. * Remove colour quality scale unnecessary unit test changes. * Revert `DataColorimetry_TCS_CIE2017` fields to "Colour" 0.4.2 ordering. * Update various doctests. * Update various imports. * Varnish some performance code changes. * Imeplement or simplify directory change in various utility scripts. * Update various docstrings. --------- Co-authored-by: Thomas Mansencal <[email protected]>
1 parent a3ab592 commit ca0bba3

32 files changed

+651
-345
lines changed

colour/appearance/cam16.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ def XYZ_to_CAM16(
173173
surround: InductionFactors_CIECAM02
174174
| InductionFactors_CAM16 = VIEWING_CONDITIONS_CAM16["Average"],
175175
discount_illuminant: bool = False,
176+
compute_H: bool = True,
176177
) -> CAM_Specification_CAM16:
177178
"""
178179
Compute the *CAM16* colour appearance model correlates from given
@@ -198,6 +199,9 @@ def XYZ_to_CAM16(
198199
Surround viewing conditions induction factors.
199200
discount_illuminant
200201
Truth value indicating if the illuminant should be discounted.
202+
compute_H
203+
Whether to compute *Hue* :math:`h` quadrature :math:`H`. :math:`H` is
204+
rarely used, and expensive to compute.
201205
202206
Returns
203207
-------
@@ -304,7 +308,7 @@ def XYZ_to_CAM16(
304308
e_t = eccentricity_factor(h)
305309

306310
# Computing hue :math:`h` quadrature :math:`H`.
307-
H = hue_quadrature(h)
311+
H = hue_quadrature(h) if compute_H else np.full(h.shape, np.nan)
308312
# TODO: Compute hue composition.
309313

310314
# Step 6

colour/appearance/ciecam02.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ def XYZ_to_CIECAM02(
231231
"Average"
232232
],
233233
discount_illuminant: bool = False,
234+
compute_H: bool = True,
234235
) -> CAM_Specification_CIECAM02:
235236
"""
236237
Compute the *CIECAM02* colour appearance model correlates from given
@@ -256,6 +257,9 @@ def XYZ_to_CIECAM02(
256257
Surround viewing conditions induction factors.
257258
discount_illuminant
258259
Truth value indicating if the illuminant should be discounted.
260+
compute_H
261+
Whether to compute *Hue* :math:`h` quadrature :math:`H`. :math:`H` is
262+
rarely used, and expensive to compute.
259263
260264
Returns
261265
-------
@@ -368,7 +372,7 @@ def XYZ_to_CIECAM02(
368372
h = hue_angle(a, b)
369373

370374
# Computing hue :math:`h` quadrature :math:`H`.
371-
H = hue_quadrature(h)
375+
H = hue_quadrature(h) if compute_H else np.full(h.shape, np.nan)
372376
# TODO: Compute hue composition.
373377

374378
# Computing eccentricity factor *e_t*.

colour/appearance/ciecam16.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ def XYZ_to_CIECAM16(
168168
surround: InductionFactors_CIECAM02
169169
| InductionFactors_CIECAM16 = VIEWING_CONDITIONS_CIECAM16["Average"],
170170
discount_illuminant: bool = False,
171+
compute_H: bool = True,
171172
) -> CAM_Specification_CIECAM16:
172173
"""
173174
Compute the *CIECAM16* colour appearance model correlates from given
@@ -193,6 +194,9 @@ def XYZ_to_CIECAM16(
193194
Surround viewing conditions induction factors.
194195
discount_illuminant
195196
Truth value indicating if the illuminant should be discounted.
197+
compute_H
198+
Whether to compute *Hue* :math:`h` quadrature :math:`H`. :math:`H` is
199+
rarely used, and expensive to compute.
196200
197201
Returns
198202
-------
@@ -316,7 +320,7 @@ def XYZ_to_CIECAM16(
316320
e_t = eccentricity_factor(h)
317321

318322
# Computing hue :math:`h` quadrature :math:`H`.
319-
H = hue_quadrature(h)
323+
H = hue_quadrature(h) if compute_H else np.full(h.shape, np.nan)
320324
# TODO: Compute hue composition.
321325

322326
# Step 6

colour/appearance/hellwig2022.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ def XYZ_to_Hellwig2022(
188188
surround: InductionFactors_CIECAM02
189189
| InductionFactors_Hellwig2022 = VIEWING_CONDITIONS_HELLWIG2022["Average"],
190190
discount_illuminant: bool = False,
191+
compute_H: bool = True,
191192
) -> CAM_Specification_Hellwig2022:
192193
"""
193194
Compute the *Hellwig and Fairchild (2022)* colour appearance model
@@ -216,6 +217,9 @@ def XYZ_to_Hellwig2022(
216217
Surround viewing conditions induction factors.
217218
discount_illuminant
218219
Truth value indicating if the illuminant should be discounted.
220+
compute_H
221+
Whether to compute *Hue* :math:`h` quadrature :math:`H`. :math:`H` is
222+
rarely used, and expensive to compute.
219223
220224
Returns
221225
-------
@@ -346,7 +350,7 @@ def XYZ_to_Hellwig2022(
346350
e_t = eccentricity_factor(h)
347351

348352
# Computing hue :math:`h` quadrature :math:`H`.
349-
H = hue_quadrature(h)
353+
H = hue_quadrature(h) if compute_H else np.full(h.shape, np.nan)
350354
# TODO: Compute hue composition.
351355

352356
# Step 6

colour/appearance/kim2009.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,9 @@ def XYZ_to_Kim2009(
219219
L_A: ArrayLike,
220220
media: MediaParameters_Kim2009 = MEDIA_PARAMETERS_KIM2009["CRT Displays"],
221221
surround: InductionFactors_Kim2009 = VIEWING_CONDITIONS_KIM2009["Average"],
222-
discount_illuminant: bool = False,
223222
n_c: float = 0.57,
223+
discount_illuminant: bool = False,
224+
compute_H: bool = True,
224225
) -> CAM_Specification_Kim2009:
225226
"""
226227
Compute the *Kim, Weyrich and Kautz (2009)* colour appearance model
@@ -241,6 +242,9 @@ def XYZ_to_Kim2009(
241242
Surround viewing conditions induction factors.
242243
discount_illuminant
243244
Truth value indicating if the illuminant should be discounted.
245+
compute_H
246+
Whether to compute *Hue* :math:`h` quadrature :math:`H`. :math:`H` is
247+
rarely used, and expensive to compute.
244248
n_c
245249
Cone response sigmoidal curve modulating factor :math:`n_c`.
246250
@@ -365,7 +369,7 @@ def XYZ_to_Kim2009(
365369
h = np.degrees(np.arctan2(b, a)) % 360
366370

367371
# Computing hue :math:`h` quadrature :math:`H`.
368-
H = hue_quadrature(h)
372+
H = hue_quadrature(h) if compute_H else np.full(h.shape, np.nan)
369373

370374
return CAM_Specification_Kim2009(
371375
as_float(from_range_100(J)),
@@ -385,8 +389,8 @@ def Kim2009_to_XYZ(
385389
L_A: ArrayLike,
386390
media: MediaParameters_Kim2009 = MEDIA_PARAMETERS_KIM2009["CRT Displays"],
387391
surround: InductionFactors_Kim2009 = VIEWING_CONDITIONS_KIM2009["Average"],
388-
discount_illuminant: bool = False,
389392
n_c: float = 0.57,
393+
discount_illuminant: bool = False,
390394
) -> NDArrayFloat:
391395
"""
392396
Convert from *Kim, Weyrich and Kautz (2009)* specification to *CIE XYZ*

colour/appearance/zcam.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ def XYZ_to_ZCAM(
308308
Y_b: ArrayLike,
309309
surround: InductionFactors_ZCAM = VIEWING_CONDITIONS_ZCAM["Average"],
310310
discount_illuminant: bool = False,
311+
compute_H: bool = True,
311312
) -> CAM_Specification_ZCAM:
312313
"""
313314
Compute the *ZCAM* colour appearance model correlates from given *CIE XYZ*
@@ -335,6 +336,9 @@ def XYZ_to_ZCAM(
335336
Surround viewing conditions induction factors.
336337
discount_illuminant
337338
Truth value indicating if the illuminant should be discounted.
339+
compute_H
340+
Whether to compute *Hue* :math:`h` quadrature :math:`H`. :math:`H` is
341+
rarely used, and expensive to compute.
338342
339343
Returns
340344
-------
@@ -460,7 +464,7 @@ def XYZ_to_ZCAM(
460464
h_z = hue_angle(a_z, b_z)
461465

462466
# Step 4 (Forward) - Computing hue quadrature :math:`H`.
463-
H = hue_quadrature(h_z)
467+
H = hue_quadrature(h_z) if compute_H else np.full(h_z.shape, np.nan)
464468

465469
# Computing eccentricity factor :math:`e_z`.
466470
e_z = 1.015 + np.cos(np.radians(89.038 + h_z % 360))

colour/colorimetry/blackbody.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import numpy as np
2020

21-
from colour.algebra import sdiv, sdiv_mode
2221
from colour.colorimetry import (
2322
SPECTRAL_SHAPE_DEFAULT,
2423
SpectralDistribution,
@@ -27,6 +26,7 @@
2726
from colour.constants import CONSTANT_BOLTZMANN, CONSTANT_LIGHT_SPEED
2827
from colour.hints import ArrayLike, NDArrayFloat
2928
from colour.utilities import as_float, as_float_array
29+
from colour.utilities.common import attest
3030

3131
__author__ = "Colour Developers"
3232
__copyright__ = "Copyright 2013 Colour Developers"
@@ -124,13 +124,12 @@ def planck_law(
124124
l = as_float_array(wavelength) # noqa: E741
125125
t = as_float_array(temperature)
126126

127+
attest(np.all(l > 0), "Wavelengths must be positive real numbers!")
128+
127129
l = np.ravel(l)[..., None] # noqa: E741
128130
t = np.ravel(t)[None, ...]
129131

130-
with sdiv_mode():
131-
d = sdiv(c2, (n * l * t))
132-
133-
d[d != 0] = np.expm1(d[d != 0]) ** -1
132+
d = 1 / np.expm1(c2 / (n * l * t))
134133
p = ((c1 * n**-2 * l**-5) / np.pi) * d
135134

136135
return as_float(np.squeeze(p))

colour/colorimetry/generation.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
import numpy as np
3838

39+
from colour.algebra.interpolation import LinearInterpolator
3940
from colour.colorimetry import (
4041
SPECTRAL_SHAPE_DEFAULT,
4142
MultiSpectralDistributions,
@@ -113,6 +114,7 @@ def sd_constant(
113114
-----
114115
- By default, the spectral distribution will use the shape given by
115116
:attr:`colour.SPECTRAL_SHAPE_DEFAULT` attribute.
117+
- The interpolator is set to :class:`colour.LinearInterpolator` class.
116118
117119
Examples
118120
--------
@@ -123,7 +125,7 @@ def sd_constant(
123125
100.0
124126
"""
125127

126-
settings = {"name": f"{k} Constant"}
128+
settings = {"name": f"{k} Constant", "interpolator": LinearInterpolator}
127129
settings.update(kwargs)
128130

129131
values = full(len(shape.wavelengths), k)
@@ -157,6 +159,7 @@ def sd_zeros(
157159
-----
158160
- By default, the spectral distribution will use the shape given by
159161
:attr:`colour.SPECTRAL_SHAPE_DEFAULT` attribute.
162+
- The interpolator is set to :class:`colour.LinearInterpolator` class.
160163
161164
Examples
162165
--------
@@ -196,6 +199,7 @@ def sd_ones(
196199
-----
197200
- By default, the spectral distribution will use the shape given by
198201
:attr:`colour.SPECTRAL_SHAPE_DEFAULT` attribute.
202+
- The interpolator is set to :class:`colour.LinearInterpolator` class.
199203
200204
Examples
201205
--------
@@ -244,6 +248,7 @@ def msds_constant(
244248
-----
245249
- By default, the multi-spectral distributions will use the shape given
246250
by :attr:`colour.SPECTRAL_SHAPE_DEFAULT` attribute.
251+
- The interpolator is set to :class:`colour.LinearInterpolator` class.
247252
248253
Examples
249254
--------
@@ -256,7 +261,7 @@ def msds_constant(
256261
['a', 'b', 'c']
257262
"""
258263

259-
settings = {"name": f"{k} Constant"}
264+
settings = {"name": f"{k} Constant", "interpolator": LinearInterpolator}
260265
settings.update(kwargs)
261266

262267
wavelengths = shape.wavelengths
@@ -299,6 +304,7 @@ def msds_zeros(
299304
-----
300305
- By default, the multi-spectral distributions will use the shape given
301306
by :attr:`colour.SPECTRAL_SHAPE_DEFAULT` attribute.
307+
- The interpolator is set to :class:`colour.LinearInterpolator` class.
302308
303309
Examples
304310
--------
@@ -346,6 +352,7 @@ def msds_ones(
346352
-----
347353
- By default, the multi-spectral distributions will use the shape given
348354
by :attr:`colour.SPECTRAL_SHAPE_DEFAULT` attribute.
355+
- The interpolator is set to :class:`colour.LinearInterpolator` class.
349356
350357
Examples
351358
--------
@@ -755,7 +762,7 @@ def sd_multi_leds_Ohno2005(
755762

756763
sd = sd_zeros(shape)
757764

758-
for (peak_wavelength, fwhm_s, peak_power_ratio) in zip(
765+
for peak_wavelength, fwhm_s, peak_power_ratio in zip(
759766
peak_wavelengths, fwhm, peak_power_ratios
760767
):
761768
sd += (

colour/colorimetry/illuminants.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
SDS_BASIS_FUNCTIONS_CIE_ILLUMINANT_D_SERIES,
3535
SpectralDistribution,
3636
SpectralShape,
37+
reshape_sd,
3738
)
3839
from colour.hints import ArrayLike, NDArrayFloat
3940
from colour.utilities import as_float_array, as_float, tsplit
@@ -136,7 +137,9 @@ def sd_CIE_standard_illuminant_A(
136137

137138

138139
def sd_CIE_illuminant_D_series(
139-
xy: ArrayLike, M1_M2_rounding: bool = True
140+
xy: ArrayLike,
141+
M1_M2_rounding: bool = True,
142+
shape: SpectralShape | None = None,
140143
) -> SpectralDistribution:
141144
"""
142145
Return the spectral distribution of given *CIE Illuminant D Series* using
@@ -149,6 +152,9 @@ def sd_CIE_illuminant_D_series(
149152
M1_M2_rounding
150153
Whether to round :math:`M1` and :math:`M2` variables to 3 decimal
151154
places in order to yield the internationally agreed values.
155+
shape
156+
Specifies the shape of the returned SpectralDistribution. Optional,
157+
default None.
152158
153159
Returns
154160
-------
@@ -306,6 +312,11 @@ def sd_CIE_illuminant_D_series(
306312
S1 = SDS_BASIS_FUNCTIONS_CIE_ILLUMINANT_D_SERIES["S1"]
307313
S2 = SDS_BASIS_FUNCTIONS_CIE_ILLUMINANT_D_SERIES["S2"]
308314

315+
if shape is not None:
316+
S0 = reshape_sd(S0, shape=shape, copy=False)
317+
S1 = reshape_sd(S1, shape=shape, copy=False)
318+
S2 = reshape_sd(S2, shape=shape, copy=False)
319+
309320
distribution = S0.values + M1 * S1.values + M2 * S2.values
310321

311322
return SpectralDistribution(

0 commit comments

Comments
 (0)