Coverage for corresponding/prediction.py: 64%
124 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-16 22:49 +1300
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-16 22:49 +1300
1"""
2Corresponding Chromaticities Prediction
3=======================================
5Define objects for computing corresponding chromaticities prediction under
6different chromatic adaptation conditions.
8References
9----------
10- :cite:`Breneman1987b` : Breneman, E. J. (1987). Corresponding
11 chromaticities for different states of adaptation to complex visual fields.
12 Journal of the Optical Society of America A, 4(6), 1115.
13 doi:10.1364/JOSAA.4.001115
14- :cite:`CIETC1-321994b` : CIE TC 1-32. (1994). CIE 109-1994 A Method of
15 Predicting Corresponding Colours under Different Chromatic and Illuminance
16 Adaptations. Commission Internationale de l'Eclairage.
17 ISBN:978-3-900734-51-0
18- :cite:`Fairchild1991a` : Fairchild, M. D. (1991). Formulation and testing
19 of an incomplete-chromatic-adaptation model. Color Research & Application,
20 16(4), 243-250. doi:10.1002/col.5080160406
21- :cite:`Fairchild2013s` : Fairchild, M. D. (2013). FAIRCHILD'S 1990 MODEL.
22 In Color Appearance Models (3rd ed., pp. 4418-4495). Wiley. ISBN:B00DAYO8E2
23- :cite:`Fairchild2013t` : Fairchild, M. D. (2013). Chromatic Adaptation
24 Models. In Color Appearance Models (3rd ed., pp. 4179-4252). Wiley.
25 ISBN:B00DAYO8E2
26- :cite:`Li2002a` : Li, C., Luo, M. R., Rigg, B., & Hunt, R. W. G. (2002).
27 CMC 2000 chromatic adaptation transform: CMCCAT2000. Color Research &
28 Application, 27(1), 49-58. doi:10.1002/col.10005
29- :cite:`Luo1999` : Luo, M. Ronnier, & Rhodes, P. A. (1999).
30 Corresponding-colour datasets. Color Research & Application, 24(4),
31 295-296. doi:10.1002/(SICI)1520-6378(199908)24:4<295::AID-COL10>3.0.CO;2-K
32- :cite:`Westland2012k` : Westland, S., Ripamonti, C., & Cheung, V. (2012).
33 CMCCAT2000. In Computational Colour Science Using MATLAB (2nd ed., pp.
34 83-86). ISBN:978-0-470-66569-5
35- :cite:`Zhai2018` : Zhai, Q., & Luo, M. R. (2018). Study of chromatic
36 adaptation via neutral white matches on different viewing media. Optics
37 Express, 26(6), 7724. doi:10.1364/OE.26.007724
38"""
40from __future__ import annotations
42import typing
43from dataclasses import dataclass
45import numpy as np
47from colour.adaptation import (
48 chromatic_adaptation_CIE1994,
49 chromatic_adaptation_CMCCAT2000,
50 chromatic_adaptation_Fairchild1990,
51 chromatic_adaptation_VonKries,
52 chromatic_adaptation_Zhai2018,
53)
54from colour.corresponding import (
55 BRENEMAN_EXPERIMENT_PRIMARIES_CHROMATICITIES,
56 BRENEMAN_EXPERIMENTS,
57)
59if typing.TYPE_CHECKING:
60 from colour.hints import (
61 Any,
62 ArrayLike,
63 Literal,
64 LiteralChromaticAdaptationTransform,
65 NDArrayFloat,
66 Tuple,
67 )
69from colour.models import (
70 Luv_to_uv,
71 Luv_uv_to_xy,
72 XYZ_to_Luv,
73 XYZ_to_xy,
74 xy_to_XYZ,
75 xyY_to_XYZ,
76)
77from colour.utilities import (
78 CanonicalMapping,
79 MixinDataclassIterable,
80 as_float_array,
81 as_float_scalar,
82 attest,
83 domain_range_scale,
84 filter_kwargs,
85 full,
86)
88__author__ = "Colour Developers"
89__copyright__ = "Copyright 2013 Colour Developers"
90__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
91__maintainer__ = "Colour Developers"
92__email__ = "colour-developers@colour-science.org"
93__status__ = "Production"
95__all__ = [
96 "CorrespondingColourDataset",
97 "CorrespondingChromaticitiesPrediction",
98 "convert_experiment_results_Breneman1987",
99 "corresponding_chromaticities_prediction_Fairchild1990",
100 "corresponding_chromaticities_prediction_CIE1994",
101 "corresponding_chromaticities_prediction_CMCCAT2000",
102 "corresponding_chromaticities_prediction_VonKries",
103 "corresponding_chromaticities_prediction_Zhai2018",
104 "CORRESPONDING_CHROMATICITIES_PREDICTION_MODELS",
105 "corresponding_chromaticities_prediction",
106]
109@dataclass(frozen=True)
110class CorrespondingColourDataset(MixinDataclassIterable):
111 """
112 Define a corresponding colour dataset for chromatic adaptation studies.
114 Parameters
115 ----------
116 name
117 Corresponding colour dataset name.
118 XYZ_r
119 *CIE XYZ* tristimulus values of the reference illuminant.
120 XYZ_t
121 *CIE XYZ* tristimulus values of the test illuminant.
122 XYZ_cr
123 Corresponding *CIE XYZ* tristimulus values under the reference
124 illuminant.
125 XYZ_ct
126 Corresponding *CIE XYZ* tristimulus values under the test illuminant.
127 Y_r
128 Reference white luminance :math:`Y_r` in :math:`cd/m^2`.
129 Y_t
130 Test white luminance :math:`Y_t` in :math:`cd/m^2`.
131 B_r
132 Luminance factor :math:`B_r` of reference achromatic background as
133 percentage.
134 B_t
135 Luminance factor :math:`B_t` of test achromatic background as
136 percentage.
137 metadata
138 Dataset metadata.
140 Notes
141 -----
142 - This class is compatible with *Luo and Rhodes (1999)*
143 *Corresponding-Colour Datasets* datasets.
145 References
146 ----------
147 :cite:`Luo1999`
148 """
150 name: int
151 XYZ_r: NDArrayFloat
152 XYZ_t: NDArrayFloat
153 XYZ_cr: NDArrayFloat
154 XYZ_ct: NDArrayFloat
155 Y_r: float
156 Y_t: float
157 B_r: float
158 B_t: float
159 metadata: dict
161 def __post_init__(self) -> None:
162 """Post-initialise the class."""
164 object.__setattr__(self, "XYZ_r", as_float_array(self.XYZ_r))
165 object.__setattr__(self, "XYZ_t", as_float_array(self.XYZ_t))
166 object.__setattr__(self, "XYZ_cr", as_float_array(self.XYZ_cr))
167 object.__setattr__(self, "XYZ_ct", as_float_array(self.XYZ_ct))
170@dataclass(frozen=True)
171class CorrespondingChromaticitiesPrediction(MixinDataclassIterable):
172 """
173 Define a chromatic adaptation model prediction for corresponding
174 chromaticities.
176 Parameters
177 ----------
178 name
179 Test colour name used to identify the prediction instance.
180 uv_t
181 Chromaticity coordinates :math:`uv_t^p` of the test colour under
182 the test illuminant.
183 uv_m
184 Chromaticity coordinates :math:`uv_m^p` of the matching colour
185 under the reference illuminant.
186 uv_p
187 Chromaticity coordinates :math:`uv_p^p` of the predicted colour
188 as computed by the chromatic adaptation model.
189 """
191 name: int
192 uv_t: NDArrayFloat
193 uv_m: NDArrayFloat
194 uv_p: NDArrayFloat
196 def __post_init__(self) -> None:
197 """Post-initialise the class."""
199 object.__setattr__(self, "uv_t", as_float_array(self.uv_t))
200 object.__setattr__(self, "uv_m", as_float_array(self.uv_m))
201 object.__setattr__(self, "uv_p", as_float_array(self.uv_p))
204def convert_experiment_results_Breneman1987(
205 experiment: Literal[1, 2, 3, 4, 6, 8, 9, 11, 12],
206) -> CorrespondingColourDataset:
207 """
208 Convert *Breneman (1987)* experiment results to a
209 :class:`colour.CorrespondingColourDataset` class instance.
211 Parameters
212 ----------
213 experiment
214 *Breneman (1987)* experiment number.
216 Returns
217 -------
218 :class:`colour.CorrespondingColourDataset`
219 :class:`colour.CorrespondingColourDataset` class instance.
221 Examples
222 --------
223 >>> from pprint import pprint
224 >>> pprint(tuple(convert_experiment_results_Breneman1987(2).values))
225 ... # doctest: +ELLIPSIS
226 (2,
227 array([ 0.9582463..., 1. , 0.9436325...]),
228 array([ 0.9587332..., 1. , 0.4385796...]),
229 array([[ 388.125 , 405. , 345.625 ],
230 [ 266.8957925..., 135. , 28.5983365...],
231 [ 474.5717821..., 405. , 222.75 ...],
232 [ 538.3899082..., 405. , 24.8944954...],
233 [ 178.7430167..., 135. , 19.6089385...],
234 [ 436.6749547..., 405. , 26.5483725...],
235 [ 124.7746282..., 135. , 36.1965613...],
236 [ 77.0794172..., 135. , 60.5850563...],
237 [ 279.9390889..., 405. , 455.8395127...],
238 [ 149.5808157..., 135. , 498.7046827...],
239 [ 372.1113689..., 405. , 669.9883990...],
240 [ 212.3638968..., 135. , 414.6704871...]]),
241 array([[ 400.1039651..., 405. , 191.7287234...],
242 [ 271.0384615..., 135. , 13.5 ...],
243 [ 495.4705323..., 405. , 119.7290874...],
244 [ 580.7967033..., 405. , 6.6758241...],
245 [ 190.1933701..., 135. , 7.4585635...],
246 [ 473.7184115..., 405. , 10.2346570...],
247 [ 135.4936014..., 135. , 20.2376599...],
248 [ 86.4689781..., 135. , 35.2281021...],
249 [ 283.5396281..., 405. , 258.1775929...],
250 [ 119.7044335..., 135. , 282.6354679...],
251 [ 359.9532224..., 405. , 381.0031185...],
252 [ 181.8271461..., 135. , 204.0661252...]]),
253 1500.0,
254 1500.0,
255 0.3,
256 0.3,
257 {})
258 """
260 valid_experiment_results = [1, 2, 3, 4, 6, 8, 9, 11, 12]
261 attest(
262 experiment in valid_experiment_results,
263 f'"Breneman (1987)" experiment result is invalid, it must be one of '
264 f'"{valid_experiment_results}"!',
265 )
267 samples_luminance = [
268 0.270,
269 0.090,
270 0.270,
271 0.270,
272 0.090,
273 0.270,
274 0.090,
275 0.090,
276 0.270,
277 0.090,
278 0.270,
279 0.090,
280 ]
282 experiment_results = list(BRENEMAN_EXPERIMENTS[experiment])
283 illuminant_chromaticities = experiment_results.pop(0)
284 Y_r = Y_t = as_float_scalar(
285 BRENEMAN_EXPERIMENT_PRIMARIES_CHROMATICITIES[experiment].Y
286 )
287 B_r = B_t = 0.3
289 XYZ_t, XYZ_r = (
290 xy_to_XYZ(
291 np.hstack(
292 [
293 Luv_uv_to_xy(illuminant_chromaticities.values[1:3]),
294 full((2, 1), Y_r),
295 ]
296 )
297 )
298 / Y_r
299 )
301 xyY_cr, xyY_ct = [], []
302 for i, experiment_result in enumerate(experiment_results):
303 xyY_cr.append(
304 np.hstack(
305 [
306 Luv_uv_to_xy(experiment_result.values[2]),
307 samples_luminance[i] * Y_r,
308 ]
309 )
310 )
311 xyY_ct.append(
312 np.hstack(
313 [
314 Luv_uv_to_xy(experiment_result.values[1]),
315 samples_luminance[i] * Y_t,
316 ]
317 )
318 )
320 XYZ_cr = xyY_to_XYZ(xyY_cr)
321 XYZ_ct = xyY_to_XYZ(xyY_ct)
323 return CorrespondingColourDataset(
324 experiment, XYZ_r, XYZ_t, XYZ_cr, XYZ_ct, Y_r, Y_t, B_r, B_t, {}
325 )
328def corresponding_chromaticities_prediction_Fairchild1990(
329 experiment: (Literal[1, 2, 3, 4, 6, 8, 9, 11, 12] | CorrespondingColourDataset) = 1,
330) -> Tuple[CorrespondingChromaticitiesPrediction, ...]:
331 """
332 Predict corresponding chromaticities using the *Fairchild (1990)*
333 chromatic adaptation model.
335 Parameters
336 ----------
337 experiment
338 *Breneman (1987)* experiment number or
339 :class:`colour.CorrespondingColourDataset` class instance.
341 Returns
342 -------
343 :class:`tuple`
344 Corresponding chromaticities prediction.
346 References
347 ----------
348 :cite:`Breneman1987b`, :cite:`Fairchild1991a`, :cite:`Fairchild2013s`
350 Examples
351 --------
352 >>> from pprint import pprint
353 >>> pr = corresponding_chromaticities_prediction_Fairchild1990(2)
354 >>> pr = [(p.uv_m, p.uv_p) for p in pr]
355 >>> pprint(pr) # doctest: +ELLIPSIS
356 [(array([ 0.207, 0.486]), array([ 0.2089528..., 0.4724034...])),
357 (array([ 0.449, 0.511]), array([ 0.4375652..., 0.5121030...])),
358 (array([ 0.263, 0.505]), array([ 0.2621362..., 0.4972538...])),
359 (array([ 0.322, 0.545]), array([ 0.3235312..., 0.5475665...])),
360 (array([ 0.316, 0.537]), array([ 0.3151391..., 0.5398333...])),
361 (array([ 0.265, 0.553]), array([ 0.2634745..., 0.5544335...])),
362 (array([ 0.221, 0.538]), array([ 0.2211595..., 0.5324470...])),
363 (array([ 0.135, 0.532]), array([ 0.1396949..., 0.5207234...])),
364 (array([ 0.145, 0.472]), array([ 0.1512288..., 0.4533041...])),
365 (array([ 0.163, 0.331]), array([ 0.1715691..., 0.3026264...])),
366 (array([ 0.176, 0.431]), array([ 0.1825792..., 0.4077892...])),
367 (array([ 0.244, 0.349]), array([ 0.2418905..., 0.3413401...]))]
368 """
370 experiment_results = (
371 experiment
372 if isinstance(experiment, CorrespondingColourDataset)
373 else convert_experiment_results_Breneman1987(experiment)
374 )
376 with domain_range_scale("1"):
377 XYZ_t, XYZ_r = experiment_results.XYZ_t, experiment_results.XYZ_r
378 xy_t, xy_r = XYZ_to_xy([XYZ_t, XYZ_r])
380 uv_t = Luv_to_uv(XYZ_to_Luv(experiment_results.XYZ_ct, xy_t), xy_t)
381 uv_m = Luv_to_uv(XYZ_to_Luv(experiment_results.XYZ_cr, xy_r), xy_r)
383 Y_n = experiment_results.Y_t
385 XYZ_1 = experiment_results.XYZ_ct
386 XYZ_2 = chromatic_adaptation_Fairchild1990(XYZ_1, XYZ_t, XYZ_r, Y_n)
387 uv_p = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_r), xy_r)
389 return tuple(
390 CorrespondingChromaticitiesPrediction(
391 experiment_results.name, uv_t[i], uv_m[i], uv_p[i]
392 )
393 for i in range(len(uv_t))
394 )
397def corresponding_chromaticities_prediction_CIE1994(
398 experiment: (Literal[1, 2, 3, 4, 6, 8, 9, 11, 12] | CorrespondingColourDataset) = 1,
399) -> Tuple[CorrespondingChromaticitiesPrediction, ...]:
400 """
401 Predict corresponding chromaticities using the *CIE 1994*
402 chromatic adaptation model.
404 Parameters
405 ----------
406 experiment
407 *Breneman (1987)* experiment number or
408 :class:`colour.CorrespondingColourDataset` class instance.
410 Returns
411 -------
412 :class:`tuple`
413 Corresponding chromaticities prediction.
415 References
416 ----------
417 :cite:`Breneman1987b`, :cite:`CIETC1-321994b`
419 Examples
420 --------
421 >>> from pprint import pprint
422 >>> pr = corresponding_chromaticities_prediction_CIE1994(2)
423 >>> pr = [(p.uv_m, p.uv_p) for p in pr]
424 >>> pprint(pr) # doctest: +ELLIPSIS
425 [(array([ 0.207, 0.486]), array([ 0.2273130..., 0.5267609...])),
426 (array([ 0.449, 0.511]), array([ 0.4612181..., 0.5191849...])),
427 (array([ 0.263, 0.505]), array([ 0.2872404..., 0.5306938...])),
428 (array([ 0.322, 0.545]), array([ 0.3489822..., 0.5454398...])),
429 (array([ 0.316, 0.537]), array([ 0.3371612..., 0.5421567...])),
430 (array([ 0.265, 0.553]), array([ 0.2889416..., 0.5534074...])),
431 (array([ 0.221, 0.538]), array([ 0.2412195..., 0.5464301...])),
432 (array([ 0.135, 0.532]), array([ 0.1530344..., 0.5488239...])),
433 (array([ 0.145, 0.472]), array([ 0.1568709..., 0.5258835...])),
434 (array([ 0.163, 0.331]), array([ 0.1499762..., 0.4401747...])),
435 (array([ 0.176, 0.431]), array([ 0.1876711..., 0.5039627...])),
436 (array([ 0.244, 0.349]), array([ 0.2560012..., 0.4546263...]))]
437 """
439 experiment_results = (
440 experiment
441 if isinstance(experiment, CorrespondingColourDataset)
442 else convert_experiment_results_Breneman1987(experiment)
443 )
445 with domain_range_scale("1"):
446 XYZ_t, XYZ_r = experiment_results.XYZ_t, experiment_results.XYZ_r
447 xy_o1, xy_o2 = XYZ_to_xy([XYZ_t, XYZ_r])
449 uv_t = Luv_to_uv(XYZ_to_Luv(experiment_results.XYZ_ct, xy_o1), xy_o1)
450 uv_m = Luv_to_uv(XYZ_to_Luv(experiment_results.XYZ_cr, xy_o2), xy_o2)
452 Y_r = experiment_results.B_r
453 E_o1, E_o2 = experiment_results.Y_t, experiment_results.Y_r
455 XYZ_1 = experiment_results.XYZ_ct
456 XYZ_2 = chromatic_adaptation_CIE1994(XYZ_1, xy_o1, xy_o2, Y_r, E_o1, E_o2)
457 uv_p = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_o2), xy_o2)
459 return tuple(
460 CorrespondingChromaticitiesPrediction(
461 experiment_results.name, uv_t[i], uv_m[i], uv_p[i]
462 )
463 for i in range(len(uv_t))
464 )
467def corresponding_chromaticities_prediction_CMCCAT2000(
468 experiment: (Literal[1, 2, 3, 4, 6, 8, 9, 11, 12] | CorrespondingColourDataset) = 1,
469) -> Tuple[CorrespondingChromaticitiesPrediction, ...]:
470 """
471 Predict corresponding chromaticities using the *CMCCAT2000*
472 chromatic adaptation model.
474 Parameters
475 ----------
476 experiment
477 *Breneman (1987)* experiment number or
478 :class:`colour.CorrespondingColourDataset` class instance.
480 Returns
481 -------
482 :class:`tuple`
483 Corresponding chromaticities prediction.
485 References
486 ----------
487 :cite:`Breneman1987b`, :cite:`Li2002a`, :cite:`Westland2012k`
489 Examples
490 --------
491 >>> from pprint import pprint
492 >>> pr = corresponding_chromaticities_prediction_CMCCAT2000(2)
493 >>> pr = [(p.uv_m, p.uv_p) for p in pr]
494 >>> pprint(pr) # doctest: +ELLIPSIS
495 [(array([ 0.207, 0.486]), array([ 0.2083210..., 0.4727168...])),
496 (array([ 0.449, 0.511]), array([ 0.4459270..., 0.5077735...])),
497 (array([ 0.263, 0.505]), array([ 0.2640262..., 0.4955361...])),
498 (array([ 0.322, 0.545]), array([ 0.3316884..., 0.5431580...])),
499 (array([ 0.316, 0.537]), array([ 0.3222624..., 0.5357624...])),
500 (array([ 0.265, 0.553]), array([ 0.2710705..., 0.5501997...])),
501 (array([ 0.221, 0.538]), array([ 0.2261826..., 0.5294740...])),
502 (array([ 0.135, 0.532]), array([ 0.1439693..., 0.5190984...])),
503 (array([ 0.145, 0.472]), array([ 0.1494835..., 0.4556760...])),
504 (array([ 0.163, 0.331]), array([ 0.1563172..., 0.3164151...])),
505 (array([ 0.176, 0.431]), array([ 0.1763199..., 0.4127589...])),
506 (array([ 0.244, 0.349]), array([ 0.2287638..., 0.3499324...]))]
507 """
509 experiment_results = (
510 experiment
511 if isinstance(experiment, CorrespondingColourDataset)
512 else convert_experiment_results_Breneman1987(experiment)
513 )
515 with domain_range_scale("1"):
516 XYZ_w, XYZ_wr = experiment_results.XYZ_t, experiment_results.XYZ_r
517 xy_w, xy_wr = XYZ_to_xy([XYZ_w, XYZ_wr])
519 uv_t = Luv_to_uv(XYZ_to_Luv(experiment_results.XYZ_ct, xy_w), xy_w)
520 uv_m = Luv_to_uv(XYZ_to_Luv(experiment_results.XYZ_cr, xy_wr), xy_wr)
522 L_A1 = experiment_results.Y_t
523 L_A2 = experiment_results.Y_r
525 XYZ_1 = experiment_results.XYZ_ct
526 XYZ_2 = chromatic_adaptation_CMCCAT2000(XYZ_1, XYZ_w, XYZ_wr, L_A1, L_A2)
527 uv_p = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_wr), xy_wr)
529 return tuple(
530 CorrespondingChromaticitiesPrediction(
531 experiment_results.name, uv_t[i], uv_m[i], uv_p[i]
532 )
533 for i in range(len(uv_t))
534 )
537def corresponding_chromaticities_prediction_VonKries(
538 experiment: (Literal[1, 2, 3, 4, 6, 8, 9, 11, 12] | CorrespondingColourDataset) = 1,
539 transform: LiteralChromaticAdaptationTransform | str = "CAT02",
540) -> Tuple[CorrespondingChromaticitiesPrediction, ...]:
541 """
542 Predict corresponding chromaticities using the *Von Kries*
543 chromatic adaptation model.
545 Parameters
546 ----------
547 experiment
548 *Breneman (1987)* experiment number or
549 :class:`colour.CorrespondingColourDataset` class instance.
550 transform
551 Chromatic adaptation transform.
553 Returns
554 -------
555 :class:`tuple`
556 Corresponding chromaticities prediction.
558 References
559 ----------
560 :cite:`Breneman1987b`, :cite:`Fairchild2013t`
562 Examples
563 --------
564 >>> from pprint import pprint
565 >>> pr = corresponding_chromaticities_prediction_VonKries(2, "Bradford")
566 >>> pr = [(p.uv_m, p.uv_p) for p in pr]
567 >>> pprint(pr) # doctest: +ELLIPSIS
568 [(array([ 0.207, 0.486]), array([ 0.2082014..., 0.4722922...])),
569 (array([ 0.449, 0.511]), array([ 0.4489102..., 0.5071602...])),
570 (array([ 0.263, 0.505]), array([ 0.2643545..., 0.4959631...])),
571 (array([ 0.322, 0.545]), array([ 0.3348730..., 0.5471220...])),
572 (array([ 0.316, 0.537]), array([ 0.3248758..., 0.5390589...])),
573 (array([ 0.265, 0.553]), array([ 0.2733105..., 0.5555028...])),
574 (array([ 0.221, 0.538]), array([ 0.227148 ..., 0.5331318...])),
575 (array([ 0.135, 0.532]), array([ 0.1442730..., 0.5226804...])),
576 (array([ 0.145, 0.472]), array([ 0.1498745..., 0.4550785...])),
577 (array([ 0.163, 0.331]), array([ 0.1564975..., 0.3148796...])),
578 (array([ 0.176, 0.431]), array([ 0.1760593..., 0.4103772...])),
579 (array([ 0.244, 0.349]), array([ 0.2259805..., 0.3465291...]))]
580 """
582 experiment_results = (
583 experiment
584 if isinstance(experiment, CorrespondingColourDataset)
585 else convert_experiment_results_Breneman1987(experiment)
586 )
588 with domain_range_scale("1"):
589 XYZ_w, XYZ_wr = experiment_results.XYZ_t, experiment_results.XYZ_r
590 xy_w, xy_wr = XYZ_to_xy([XYZ_w, XYZ_wr])
592 uv_t = Luv_to_uv(XYZ_to_Luv(experiment_results.XYZ_ct, xy_w), xy_w)
593 uv_m = Luv_to_uv(XYZ_to_Luv(experiment_results.XYZ_cr, xy_wr), xy_wr)
595 XYZ_1 = experiment_results.XYZ_ct
596 XYZ_2 = chromatic_adaptation_VonKries(XYZ_1, XYZ_w, XYZ_wr, transform)
597 uv_p = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_wr), xy_wr)
599 return tuple(
600 CorrespondingChromaticitiesPrediction(
601 experiment_results.name, uv_t[i], uv_m[i], uv_p[i]
602 )
603 for i in range(len(uv_t))
604 )
607def corresponding_chromaticities_prediction_Zhai2018(
608 experiment: (Literal[1, 2, 3, 4, 6, 8, 9, 11, 12] | CorrespondingColourDataset) = 1,
609 D_b: ArrayLike = 1,
610 D_d: ArrayLike = 1,
611 XYZ_wo: ArrayLike = (1, 1, 1),
612 transform: Literal["CAT02", "CAT16"] | str = "CAT02",
613) -> Tuple[CorrespondingChromaticitiesPrediction, ...]:
614 """
615 Predict corresponding chromaticities using the *Zhai and Luo (2018)*
616 chromatic adaptation model.
618 Parameters
619 ----------
620 experiment
621 *Breneman (1987)* experiment number or
622 :class:`colour.CorrespondingColourDataset` class instance.
623 D_b
624 Degree of adaptation :math:`D_{\\beta}` of input illuminant
625 :math:`\\beta`.
626 D_d
627 Degree of adaptation :math:`D_{\\delta}` of output illuminant
628 :math:`\\delta`.
629 XYZ_wo
630 Baseline illuminant (:math:`BI`) :math:`o`.
631 transform
632 Chromatic adaptation transform.
634 Returns
635 -------
636 :class:`tuple`
637 Corresponding chromaticities prediction.
639 References
640 ----------
641 :cite:`Breneman1987b`, :cite:`Zhai2018`
643 Examples
644 --------
645 >>> from pprint import pprint
646 >>> pr = corresponding_chromaticities_prediction_Zhai2018(2)
647 >>> pr = [(p.uv_m, p.uv_p) for p in pr]
648 >>> pprint(pr) # doctest: +ELLIPSIS
649 [(array([ 0.207, 0.486]), array([ 0.2082238..., 0.4727943...])),
650 (array([ 0.449, 0.511]), array([ 0.4474691..., 0.5076681...])),
651 (array([ 0.263, 0.505]), array([ 0.2640379..., 0.4954003...])),
652 (array([ 0.322, 0.545]), array([ 0.3336937..., 0.5435500...])),
653 (array([ 0.316, 0.537]), array([ 0.3238490..., 0.5359889...])),
654 (array([ 0.265, 0.553]), array([ 0.2724846..., 0.5506939...])),
655 (array([ 0.221, 0.538]), array([ 0.2267596..., 0.5295259...])),
656 (array([ 0.135, 0.532]), array([ 0.1443208..., 0.5190035...])),
657 (array([ 0.145, 0.472]), array([ 0.1500723..., 0.4561352...])),
658 (array([ 0.163, 0.331]), array([ 0.1570902..., 0.3245137...])),
659 (array([ 0.176, 0.431]), array([ 0.1763887..., 0.4146000...])),
660 (array([ 0.244, 0.349]), array([ 0.2267005..., 0.3551480...]))]
661 """
663 experiment_results = (
664 experiment
665 if isinstance(experiment, CorrespondingColourDataset)
666 else convert_experiment_results_Breneman1987(experiment)
667 )
669 with domain_range_scale("1"):
670 XYZ_w, XYZ_wr = experiment_results.XYZ_t, experiment_results.XYZ_r
671 xy_w, xy_wr = XYZ_to_xy([XYZ_w, XYZ_wr])
673 uv_t = Luv_to_uv(XYZ_to_Luv(experiment_results.XYZ_ct, xy_w), xy_w)
674 uv_m = Luv_to_uv(XYZ_to_Luv(experiment_results.XYZ_cr, xy_wr), xy_wr)
676 XYZ_1 = experiment_results.XYZ_ct
677 XYZ_2 = chromatic_adaptation_Zhai2018(
678 XYZ_1, XYZ_w, XYZ_wr, D_b, D_d, XYZ_wo, transform
679 )
680 uv_p = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_wr), xy_wr)
682 return tuple(
683 CorrespondingChromaticitiesPrediction(
684 experiment_results.name, uv_t[i], uv_m[i], uv_p[i]
685 )
686 for i in range(len(uv_t))
687 )
690CORRESPONDING_CHROMATICITIES_PREDICTION_MODELS = CanonicalMapping(
691 {
692 "CIE 1994": corresponding_chromaticities_prediction_CIE1994,
693 "CMCCAT2000": corresponding_chromaticities_prediction_CMCCAT2000,
694 "Fairchild 1990": corresponding_chromaticities_prediction_Fairchild1990,
695 "Von Kries": corresponding_chromaticities_prediction_VonKries,
696 "Zhai 2018": corresponding_chromaticities_prediction_Zhai2018,
697 }
698)
699CORRESPONDING_CHROMATICITIES_PREDICTION_MODELS.__doc__ = """
700Supported corresponding chromaticities prediction models.
702References
703----------
704:cite:`Breneman1987b`, :cite:`CIETC1-321994b`, :cite:`Fairchild1991a`,
705:cite:`Fairchild2013s`, :cite:`Fairchild2013t`, :cite:`Li2002a`,
706:cite:`Westland2012k`, :cite:`Zhai2018`
708Aliases:
710- 'vonkries': 'Von Kries'
711"""
712CORRESPONDING_CHROMATICITIES_PREDICTION_MODELS["vonkries"] = (
713 CORRESPONDING_CHROMATICITIES_PREDICTION_MODELS["Von Kries"]
714)
717def corresponding_chromaticities_prediction(
718 experiment: (Literal[1, 2, 3, 4, 6, 8, 9, 11, 12] | CorrespondingColourDataset) = 1,
719 model: (
720 Literal[
721 "CIE 1994",
722 "CMCCAT2000",
723 "Fairchild 1990",
724 "Von Kries",
725 "Zhai 2018",
726 ]
727 | str
728 ) = "Von Kries",
729 **kwargs: Any,
730) -> Tuple[CorrespondingChromaticitiesPrediction, ...]:
731 """
732 Predict corresponding chromaticities.
734 Parameters
735 ----------
736 experiment
737 *Breneman (1987)* experiment number or
738 :class:`colour.CorrespondingColourDataset` class instance.
739 model
740 Chromatic adaptation model.
742 Other Parameters
743 ----------------
744 D_b
745 {:func:`colour.corresponding.\
746corresponding_chromaticities_prediction_Zhai2018`},
747 Degree of adaptation :math:`D_{\\beta}` of input illuminant
748 :math:`\\beta`.
749 D_d
750 {:func:`colour.corresponding.\
751corresponding_chromaticities_prediction_Zhai2018`},
752 Degree of adaptation :math:`D_{\\delta}` of output illuminant
753 :math:`\\delta`.
754 transform
755 {:func:`colour.corresponding.\
756corresponding_chromaticities_prediction_VonKries`,
757 :func:`colour.corresponding.\
758corresponding_chromaticities_prediction_Zhai2018`},
759 Chromatic adaptation transform.
760 XYZ_wo
761 {:func:`colour.corresponding.\
762corresponding_chromaticities_prediction_Zhai2018`},
763 Baseline illuminant (:math:`BI`) :math:`o`.
765 Returns
766 -------
767 :class:`tuple`
768 Corresponding chromaticities prediction.
770 References
771 ----------
772 :cite:`Breneman1987b`, :cite:`CIETC1-321994b`, :cite:`Fairchild1991a`,
773 :cite:`Fairchild2013s`, :cite:`Fairchild2013t`, :cite:`Li2002a`,
774 :cite:`Westland2012k`, :cite:`Zhai2018`
776 Examples
777 --------
778 >>> from pprint import pprint
779 >>> pr = corresponding_chromaticities_prediction(2, "CMCCAT2000")
780 >>> pr = [(p.uv_m, p.uv_p) for p in pr]
781 >>> pprint(pr) # doctest: +SKIP
782 [((0.207, 0.486), (0.2083210..., 0.4727168...)),
783 ((0.449, 0.511), (0.4459270..., 0.5077735...)),
784 ((0.263, 0.505), (0.2640262..., 0.4955361...)),
785 ((0.322, 0.545), (0.3316884..., 0.5431580...)),
786 ((0.316, 0.537), (0.3222624..., 0.5357624...)),
787 ((0.265, 0.553), (0.2710705..., 0.5501997...)),
788 ((0.221, 0.538), (0.2261826..., 0.5294740...)),
789 ((0.135, 0.532), (0.1439693..., 0.5190984...)),
790 ((0.145, 0.472), (0.1494835..., 0.4556760...)),
791 ((0.163, 0.331), (0.1563172..., 0.3164151...)),
792 ((0.176, 0.431), (0.1763199..., 0.4127589...)),
793 ((0.244, 0.349), (0.2287638..., 0.3499324...))]
794 """
796 function = CORRESPONDING_CHROMATICITIES_PREDICTION_MODELS[model]
798 return function(experiment, **filter_kwargs(function, **kwargs))