Coverage for corresponding/prediction.py: 64%

124 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-16 22:49 +1300

1""" 

2Corresponding Chromaticities Prediction 

3======================================= 

4 

5Define objects for computing corresponding chromaticities prediction under 

6different chromatic adaptation conditions. 

7 

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""" 

39 

40from __future__ import annotations 

41 

42import typing 

43from dataclasses import dataclass 

44 

45import numpy as np 

46 

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) 

58 

59if typing.TYPE_CHECKING: 

60 from colour.hints import ( 

61 Any, 

62 ArrayLike, 

63 Literal, 

64 LiteralChromaticAdaptationTransform, 

65 NDArrayFloat, 

66 Tuple, 

67 ) 

68 

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) 

87 

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" 

94 

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] 

107 

108 

109@dataclass(frozen=True) 

110class CorrespondingColourDataset(MixinDataclassIterable): 

111 """ 

112 Define a corresponding colour dataset for chromatic adaptation studies. 

113 

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. 

139 

140 Notes 

141 ----- 

142 - This class is compatible with *Luo and Rhodes (1999)* 

143 *Corresponding-Colour Datasets* datasets. 

144 

145 References 

146 ---------- 

147 :cite:`Luo1999` 

148 """ 

149 

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 

160 

161 def __post_init__(self) -> None: 

162 """Post-initialise the class.""" 

163 

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)) 

168 

169 

170@dataclass(frozen=True) 

171class CorrespondingChromaticitiesPrediction(MixinDataclassIterable): 

172 """ 

173 Define a chromatic adaptation model prediction for corresponding 

174 chromaticities. 

175 

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 """ 

190 

191 name: int 

192 uv_t: NDArrayFloat 

193 uv_m: NDArrayFloat 

194 uv_p: NDArrayFloat 

195 

196 def __post_init__(self) -> None: 

197 """Post-initialise the class.""" 

198 

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)) 

202 

203 

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. 

210 

211 Parameters 

212 ---------- 

213 experiment 

214 *Breneman (1987)* experiment number. 

215 

216 Returns 

217 ------- 

218 :class:`colour.CorrespondingColourDataset` 

219 :class:`colour.CorrespondingColourDataset` class instance. 

220 

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 """ 

259 

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 ) 

266 

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 ] 

281 

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 

288 

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 ) 

300 

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 ) 

319 

320 XYZ_cr = xyY_to_XYZ(xyY_cr) 

321 XYZ_ct = xyY_to_XYZ(xyY_ct) 

322 

323 return CorrespondingColourDataset( 

324 experiment, XYZ_r, XYZ_t, XYZ_cr, XYZ_ct, Y_r, Y_t, B_r, B_t, {} 

325 ) 

326 

327 

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. 

334 

335 Parameters 

336 ---------- 

337 experiment 

338 *Breneman (1987)* experiment number or 

339 :class:`colour.CorrespondingColourDataset` class instance. 

340 

341 Returns 

342 ------- 

343 :class:`tuple` 

344 Corresponding chromaticities prediction. 

345 

346 References 

347 ---------- 

348 :cite:`Breneman1987b`, :cite:`Fairchild1991a`, :cite:`Fairchild2013s` 

349 

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 """ 

369 

370 experiment_results = ( 

371 experiment 

372 if isinstance(experiment, CorrespondingColourDataset) 

373 else convert_experiment_results_Breneman1987(experiment) 

374 ) 

375 

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]) 

379 

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) 

382 

383 Y_n = experiment_results.Y_t 

384 

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) 

388 

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 ) 

395 

396 

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. 

403 

404 Parameters 

405 ---------- 

406 experiment 

407 *Breneman (1987)* experiment number or 

408 :class:`colour.CorrespondingColourDataset` class instance. 

409 

410 Returns 

411 ------- 

412 :class:`tuple` 

413 Corresponding chromaticities prediction. 

414 

415 References 

416 ---------- 

417 :cite:`Breneman1987b`, :cite:`CIETC1-321994b` 

418 

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 """ 

438 

439 experiment_results = ( 

440 experiment 

441 if isinstance(experiment, CorrespondingColourDataset) 

442 else convert_experiment_results_Breneman1987(experiment) 

443 ) 

444 

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]) 

448 

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) 

451 

452 Y_r = experiment_results.B_r 

453 E_o1, E_o2 = experiment_results.Y_t, experiment_results.Y_r 

454 

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) 

458 

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 ) 

465 

466 

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. 

473 

474 Parameters 

475 ---------- 

476 experiment 

477 *Breneman (1987)* experiment number or 

478 :class:`colour.CorrespondingColourDataset` class instance. 

479 

480 Returns 

481 ------- 

482 :class:`tuple` 

483 Corresponding chromaticities prediction. 

484 

485 References 

486 ---------- 

487 :cite:`Breneman1987b`, :cite:`Li2002a`, :cite:`Westland2012k` 

488 

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 """ 

508 

509 experiment_results = ( 

510 experiment 

511 if isinstance(experiment, CorrespondingColourDataset) 

512 else convert_experiment_results_Breneman1987(experiment) 

513 ) 

514 

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]) 

518 

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) 

521 

522 L_A1 = experiment_results.Y_t 

523 L_A2 = experiment_results.Y_r 

524 

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) 

528 

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 ) 

535 

536 

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. 

544 

545 Parameters 

546 ---------- 

547 experiment 

548 *Breneman (1987)* experiment number or 

549 :class:`colour.CorrespondingColourDataset` class instance. 

550 transform 

551 Chromatic adaptation transform. 

552 

553 Returns 

554 ------- 

555 :class:`tuple` 

556 Corresponding chromaticities prediction. 

557 

558 References 

559 ---------- 

560 :cite:`Breneman1987b`, :cite:`Fairchild2013t` 

561 

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 """ 

581 

582 experiment_results = ( 

583 experiment 

584 if isinstance(experiment, CorrespondingColourDataset) 

585 else convert_experiment_results_Breneman1987(experiment) 

586 ) 

587 

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]) 

591 

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) 

594 

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) 

598 

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 ) 

605 

606 

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. 

617 

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. 

633 

634 Returns 

635 ------- 

636 :class:`tuple` 

637 Corresponding chromaticities prediction. 

638 

639 References 

640 ---------- 

641 :cite:`Breneman1987b`, :cite:`Zhai2018` 

642 

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 """ 

662 

663 experiment_results = ( 

664 experiment 

665 if isinstance(experiment, CorrespondingColourDataset) 

666 else convert_experiment_results_Breneman1987(experiment) 

667 ) 

668 

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]) 

672 

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) 

675 

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) 

681 

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 ) 

688 

689 

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. 

701 

702References 

703---------- 

704:cite:`Breneman1987b`, :cite:`CIETC1-321994b`, :cite:`Fairchild1991a`, 

705:cite:`Fairchild2013s`, :cite:`Fairchild2013t`, :cite:`Li2002a`, 

706:cite:`Westland2012k`, :cite:`Zhai2018` 

707 

708Aliases: 

709 

710- 'vonkries': 'Von Kries' 

711""" 

712CORRESPONDING_CHROMATICITIES_PREDICTION_MODELS["vonkries"] = ( 

713 CORRESPONDING_CHROMATICITIES_PREDICTION_MODELS["Von Kries"] 

714) 

715 

716 

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. 

733 

734 Parameters 

735 ---------- 

736 experiment 

737 *Breneman (1987)* experiment number or 

738 :class:`colour.CorrespondingColourDataset` class instance. 

739 model 

740 Chromatic adaptation model. 

741 

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`. 

764 

765 Returns 

766 ------- 

767 :class:`tuple` 

768 Corresponding chromaticities prediction. 

769 

770 References 

771 ---------- 

772 :cite:`Breneman1987b`, :cite:`CIETC1-321994b`, :cite:`Fairchild1991a`, 

773 :cite:`Fairchild2013s`, :cite:`Fairchild2013t`, :cite:`Li2002a`, 

774 :cite:`Westland2012k`, :cite:`Zhai2018` 

775 

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 """ 

795 

796 function = CORRESPONDING_CHROMATICITIES_PREDICTION_MODELS[model] 

797 

798 return function(experiment, **filter_kwargs(function, **kwargs))