Coverage for colour/colorimetry/illuminants.py: 100%
38 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
1"""
2Illuminants
3===========
5Define objects for computing *CIE* standard illuminants and related daylight
6calculations:
8- :func:`colour.sd_CIE_standard_illuminant_A`
9- :func:`colour.sd_CIE_illuminant_D_series`
10- :func:`colour.daylight_locus_function`
12References
13----------
14- :cite:`CIETC1-482004` : CIE TC 1-48. (2004). EXPLANATORY COMMENTS - 5. In
15 CIE 015:2004 Colorimetry, 3rd Edition (pp. 68-68). ISBN:978-3-901906-33-6
16- :cite:`CIETC1-482004n` : CIE TC 1-48. (2004). 3.1 Recommendations
17 concerning standard physical data of illuminants. In CIE 015:2004
18 Colorimetry, 3rd Edition (pp. 12-13). ISBN:978-3-901906-33-6
19- :cite:`Wyszecki2000a` : Wyszecki, Günther, & Stiles, W. S. (2000).
20 Equation I(1.2.1). In Color Science: Concepts and Methods, Quantitative
21 Data and Formulae (p. 8). Wiley. ISBN:978-0-471-39918-6
22- :cite:`Wyszecki2000z` : Wyszecki, Günther, & Stiles, W. S. (2000). CIE
23 Method of Calculating D-Illuminants. In Color Science: Concepts and
24 Methods, Quantitative Data and Formulae (pp. 145-146). Wiley.
25 ISBN:978-0-471-39918-6
26"""
28from __future__ import annotations
30import typing
32import numpy as np
34from colour.algebra import LinearInterpolator
35from colour.colorimetry import (
36 SDS_BASIS_FUNCTIONS_CIE_ILLUMINANT_D_SERIES,
37 SPECTRAL_SHAPE_DEFAULT,
38 SpectralDistribution,
39 SpectralShape,
40 reshape_sd,
41)
43if typing.TYPE_CHECKING:
44 from colour.hints import ArrayLike, NDArrayFloat
46from colour.utilities import as_float, as_float_array, tsplit
48__author__ = "Colour Developers"
49__copyright__ = "Copyright 2013 Colour Developers"
50__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
51__maintainer__ = "Colour Developers"
52__email__ = "colour-developers@colour-science.org"
53__status__ = "Production"
55__all__ = [
56 "sd_CIE_standard_illuminant_A",
57 "sd_CIE_illuminant_D_series",
58 "daylight_locus_function",
59]
62def sd_CIE_standard_illuminant_A(
63 shape: SpectralShape = SPECTRAL_SHAPE_DEFAULT,
64) -> SpectralDistribution:
65 """
66 Represent typical domestic tungsten-filament lighting according to
67 *CIE Standard Illuminant A*.
69 Generate spectral distribution of *CIE Standard Illuminant A*, which
70 represents the spectral characteristics of a Planckian radiator at a
71 temperature of approximately 2856 K. This illuminant should be used in
72 all colorimetry applications involving incandescent lighting, unless
73 there are specific reasons for using a different illuminant.
75 Parameters
76 ----------
77 shape
78 Spectral shape used to create the spectral distribution of the
79 *CIE Standard Illuminant A*.
81 Returns
82 -------
83 :class:`colour.SpectralDistribution`
84 *CIE Standard Illuminant A* spectral distribution.
86 References
87 ----------
88 :cite:`CIETC1-482004n`
90 Examples
91 --------
92 >>> from colour import SpectralShape
93 >>> sd_CIE_standard_illuminant_A(SpectralShape(400, 700, 10))
94 ... # doctest: +ELLIPSIS
95 SpectralDistribution([[ 400. , 14.7080384...],
96 [ 410. , 17.6752521...],
97 [ 420. , 20.9949572...],
98 [ 430. , 24.6709226...],
99 [ 440. , 28.7027304...],
100 [ 450. , 33.0858929...],
101 [ 460. , 37.8120566...],
102 [ 470. , 42.8692762...],
103 [ 480. , 48.2423431...],
104 [ 490. , 53.9131532...],
105 [ 500. , 59.8610989...],
106 [ 510. , 66.0634727...],
107 [ 520. , 72.4958719...],
108 [ 530. , 79.1325945...],
109 [ 540. , 85.9470183...],
110 [ 550. , 92.9119589...],
111 [ 560. , 100. ...],
112 [ 570. , 107.1837952...],
113 [ 580. , 114.4363383...],
114 [ 590. , 121.7312009...],
115 [ 600. , 129.0427389...],
116 [ 610. , 136.3462674...],
117 [ 620. , 143.6182057...],
118 [ 630. , 150.8361944...],
119 [ 640. , 157.9791857...],
120 [ 650. , 165.0275098...],
121 [ 660. , 171.9629200...],
122 [ 670. , 178.7686175...],
123 [ 680. , 185.4292591...],
124 [ 690. , 191.9309499...],
125 [ 700. , 198.2612232...]],
126 SpragueInterpolator,
127 {},
128 Extrapolator,
129 {'method': 'Constant', 'left': None, 'right': None})
130 """
132 values = (
133 100
134 * (560 / shape.wavelengths) ** 5
135 * (
136 np.expm1((1.435 * 10**7) / (2848 * 560))
137 / np.expm1((1.435 * 10**7) / (2848 * shape.wavelengths))
138 )
139 )
141 return SpectralDistribution(
142 values, shape.wavelengths, name="CIE Standard Illuminant A"
143 )
146def sd_CIE_illuminant_D_series(
147 xy: ArrayLike,
148 M1_M2_rounding: bool = True,
149 shape: SpectralShape | None = None,
150) -> SpectralDistribution:
151 """
152 Return the spectral distribution of the specified *CIE Illuminant D
153 Series* using the specified *CIE xy* chromaticity coordinates.
155 Parameters
156 ----------
157 xy
158 *CIE xy* chromaticity coordinates.
159 M1_M2_rounding
160 Whether to round :math:`M1` and :math:`M2` variables to 3 decimal
161 places in order to yield the internationally agreed values.
162 shape
163 Specifies the shape of the returned SpectralDistribution. Optional,
164 default None.
166 Returns
167 -------
168 :class:`colour.SpectralDistribution`
169 *CIE Illuminant D Series* spectral distribution.
171 Notes
172 -----
173 - The nominal *CIE xy* chromaticity coordinates which have been
174 computed with :func:`colour.temperature.CCT_to_xy_CIE_D` must be
175 specified according to *CIE 015:2004* recommendation and thus
176 multiplied by 1.4388 / 1.4380.
177 - :math:`M1` and :math:`M2` variables are rounded to 3 decimal places
178 according to *CIE 015:2004* recommendation.
180 References
181 ----------
182 :cite:`CIETC1-482004`, :cite:`Wyszecki2000z`
184 Examples
185 --------
186 >>> from colour.utilities import numpy_print_options
187 >>> from colour.temperature import CCT_to_xy_CIE_D
188 >>> CCT_D65 = 6500 * 1.4388 / 1.4380
189 >>> xy = CCT_to_xy_CIE_D(CCT_D65)
190 >>> with numpy_print_options(suppress=True):
191 ... sd_CIE_illuminant_D_series(xy) # doctest: +ELLIPSIS
192 SpectralDistribution([[ 300. , 0.0341...],
193 [ 305. , 1.6643...],
194 [ 310. , 3.2945...],
195 [ 315. , 11.7652...],
196 [ 320. , 20.236 ...],
197 [ 325. , 28.6447...],
198 [ 330. , 37.0535...],
199 [ 335. , 38.5011...],
200 [ 340. , 39.9488...],
201 [ 345. , 42.4302...],
202 [ 350. , 44.9117...],
203 [ 355. , 45.775 ...],
204 [ 360. , 46.6383...],
205 [ 365. , 49.3637...],
206 [ 370. , 52.0891...],
207 [ 375. , 51.0323...],
208 [ 380. , 49.9755...],
209 [ 385. , 52.3118...],
210 [ 390. , 54.6482...],
211 [ 395. , 68.7015...],
212 [ 400. , 82.7549...],
213 [ 405. , 87.1204...],
214 [ 410. , 91.486 ...],
215 [ 415. , 92.4589...],
216 [ 420. , 93.4318...],
217 [ 425. , 90.0570...],
218 [ 430. , 86.6823...],
219 [ 435. , 95.7736...],
220 [ 440. , 104.8649...],
221 [ 445. , 110.9362...],
222 [ 450. , 117.0076...],
223 [ 455. , 117.4099...],
224 [ 460. , 117.8122...],
225 [ 465. , 116.3365...],
226 [ 470. , 114.8609...],
227 [ 475. , 115.3919...],
228 [ 480. , 115.9229...],
229 [ 485. , 112.3668...],
230 [ 490. , 108.8107...],
231 [ 495. , 109.0826...],
232 [ 500. , 109.3545...],
233 [ 505. , 108.5781...],
234 [ 510. , 107.8017...],
235 [ 515. , 106.2957...],
236 [ 520. , 104.7898...],
237 [ 525. , 106.2396...],
238 [ 530. , 107.6895...],
239 [ 535. , 106.0475...],
240 [ 540. , 104.4055...],
241 [ 545. , 104.2258...],
242 [ 550. , 104.0462...],
243 [ 555. , 102.0231...],
244 [ 560. , 100. ...],
245 [ 565. , 98.1671...],
246 [ 570. , 96.3342...],
247 [ 575. , 96.0611...],
248 [ 580. , 95.788 ...],
249 [ 585. , 92.2368...],
250 [ 590. , 88.6856...],
251 [ 595. , 89.3459...],
252 [ 600. , 90.0062...],
253 [ 605. , 89.8026...],
254 [ 610. , 89.5991...],
255 [ 615. , 88.6489...],
256 [ 620. , 87.6987...],
257 [ 625. , 85.4936...],
258 [ 630. , 83.2886...],
259 [ 635. , 83.4939...],
260 [ 640. , 83.6992...],
261 [ 645. , 81.863 ...],
262 [ 650. , 80.0268...],
263 [ 655. , 80.1207...],
264 [ 660. , 80.2146...],
265 [ 665. , 81.2462...],
266 [ 670. , 82.2778...],
267 [ 675. , 80.281 ...],
268 [ 680. , 78.2842...],
269 [ 685. , 74.0027...],
270 [ 690. , 69.7213...],
271 [ 695. , 70.6652...],
272 [ 700. , 71.6091...],
273 [ 705. , 72.9790...],
274 [ 710. , 74.349 ...],
275 [ 715. , 67.9765...],
276 [ 720. , 61.604 ...],
277 [ 725. , 65.7448...],
278 [ 730. , 69.8856...],
279 [ 735. , 72.4863...],
280 [ 740. , 75.087 ...],
281 [ 745. , 69.3398...],
282 [ 750. , 63.5927...],
283 [ 755. , 55.0054...],
284 [ 760. , 46.4182...],
285 [ 765. , 56.6118...],
286 [ 770. , 66.8054...],
287 [ 775. , 65.0941...],
288 [ 780. , 63.3828...],
289 [ 785. , 63.8434...],
290 [ 790. , 64.304 ...],
291 [ 795. , 61.8779...],
292 [ 800. , 59.4519...],
293 [ 805. , 55.7054...],
294 [ 810. , 51.959 ...],
295 [ 815. , 54.6998...],
296 [ 820. , 57.4406...],
297 [ 825. , 58.8765...],
298 [ 830. , 60.3125...]],
299 LinearInterpolator,
300 {},
301 Extrapolator,
302 {'method': 'Constant', 'left': None, 'right': None})
303 """
305 xy = as_float_array(xy)
307 x, y = tsplit(xy)
309 M = 0.0241 + 0.2562 * x - 0.7341 * y
310 M1 = (-1.3515 - 1.7703 * x + 5.9114 * y) / M
311 M2 = (0.0300 - 31.4424 * x + 30.0717 * y) / M
313 if M1_M2_rounding:
314 M1 = np.around(M1, 3)
315 M2 = np.around(M2, 3)
317 S0 = SDS_BASIS_FUNCTIONS_CIE_ILLUMINANT_D_SERIES["S0"]
318 S1 = SDS_BASIS_FUNCTIONS_CIE_ILLUMINANT_D_SERIES["S1"]
319 S2 = SDS_BASIS_FUNCTIONS_CIE_ILLUMINANT_D_SERIES["S2"]
321 if shape is not None:
322 S0 = reshape_sd(S0, shape=shape, copy=False)
323 S1 = reshape_sd(S1, shape=shape, copy=False)
324 S2 = reshape_sd(S2, shape=shape, copy=False)
326 distribution = S0.values + M1 * S1.values + M2 * S2.values
328 return SpectralDistribution(
329 distribution,
330 S0.wavelengths,
331 name=f"CIE xy ({xy[0]}, {xy[1]}) - CIE Illuminant D Series",
332 interpolator=LinearInterpolator,
333 )
336def daylight_locus_function(x_D: ArrayLike) -> NDArrayFloat:
337 """
338 Compute the *CIE y* chromaticity coordinate on the daylight locus.
340 Calculate the *CIE y* chromaticity coordinate on the daylight locus
341 for the specified *CIE x* chromaticity coordinate :math:`x_D` using
342 the quadratic relationship defined by *Wyszecki and Stiles*.
344 Parameters
345 ----------
346 x_D
347 *CIE x* chromaticity coordinate :math:`x_D` for which to compute
348 the corresponding *CIE y* coordinate on the daylight locus.
350 Returns
351 -------
352 :class:`numpy.ndarray`
353 *CIE y* chromaticity coordinate on the daylight locus
354 corresponding to the specified :math:`x_D`.
356 References
357 ----------
358 :cite:`Wyszecki2000a`
360 Examples
361 --------
362 >>> daylight_locus_function(0.31270) # doctest: +ELLIPSIS
363 0.3291051...
364 """
366 x_D = as_float_array(x_D)
368 y_D = -3.000 * x_D**2 + 2.870 * x_D - 0.275
370 return as_float(y_D)