Coverage for colour/appearance/tests/test_llab.py: 100%

125 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-15 19:01 +1300

1"""Define the unit tests for the :mod:`colour.appearance.kim2009` module.""" 

2 

3from __future__ import annotations 

4 

5from itertools import product 

6 

7import numpy as np 

8import pytest 

9 

10from colour.appearance import ( 

11 MEDIA_PARAMETERS_KIM2009, 

12 VIEWING_CONDITIONS_KIM2009, 

13 CAM_Specification_Kim2009, 

14 InductionFactors_Kim2009, 

15 Kim2009_to_XYZ, 

16 MediaParameters_Kim2009, 

17 XYZ_to_Kim2009, 

18) 

19from colour.constants import TOLERANCE_ABSOLUTE_TESTS 

20from colour.utilities import ( 

21 as_float_array, 

22 domain_range_scale, 

23 ignore_numpy_errors, 

24 tsplit, 

25) 

26 

27__author__ = "Colour Developers" 

28__copyright__ = "Copyright 2013 Colour Developers" 

29__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause" 

30__maintainer__ = "Colour Developers" 

31__email__ = "colour-developers@colour-science.org" 

32__status__ = "Production" 

33 

34__all__ = [ 

35 "TestXYZ_to_Kim2009", 

36 "TestKim2009_to_XYZ", 

37] 

38 

39 

40class TestXYZ_to_Kim2009: 

41 """ 

42 Define :func:`colour.appearance.kim2009.XYZ_to_Kim2009` definition unit 

43 tests methods. 

44 """ 

45 

46 def test_XYZ_to_Kim2009(self) -> None: 

47 """Test :func:`colour.appearance.kim2009.XYZ_to_Kim2009` definition.""" 

48 

49 XYZ = np.array([19.01, 20.00, 21.78]) 

50 XYZ_w = np.array([95.05, 100.00, 108.88]) 

51 L_a = 318.31 

52 media = MEDIA_PARAMETERS_KIM2009["CRT Displays"] 

53 surround = VIEWING_CONDITIONS_KIM2009["Average"] 

54 np.testing.assert_allclose( 

55 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround), 

56 np.array( 

57 [ 

58 28.86190898, 

59 0.55924559, 

60 219.04806678, 

61 9.38377973, 

62 52.71388839, 

63 0.46417384, 

64 278.06028246, 

65 np.nan, 

66 ] 

67 ), 

68 atol=TOLERANCE_ABSOLUTE_TESTS, 

69 ) 

70 

71 XYZ = np.array([57.06, 43.06, 31.96]) 

72 L_a = 31.83 

73 np.testing.assert_allclose( 

74 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround), 

75 np.array( 

76 [ 

77 70.15940419, 

78 57.89295872, 

79 21.27017200, 

80 61.23630434, 

81 128.14034598, 

82 48.05115573, 

83 1.41841443, 

84 np.nan, 

85 ] 

86 ), 

87 atol=TOLERANCE_ABSOLUTE_TESTS, 

88 ) 

89 

90 XYZ = np.array([3.53, 6.56, 2.14]) 

91 XYZ_w = np.array([109.85, 100.00, 35.58]) 

92 L_a = 318.31 

93 np.testing.assert_allclose( 

94 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround), 

95 np.array( 

96 [ 

97 -4.83430022, 

98 37.42013921, 

99 177.12166057, 

100 np.nan, 

101 -8.82944930, 

102 31.05871555, 

103 220.36270343, 

104 np.nan, 

105 ] 

106 ), 

107 atol=TOLERANCE_ABSOLUTE_TESTS, 

108 ) 

109 

110 XYZ = np.array([19.01, 20.00, 21.78]) 

111 L_a = 31.83 

112 np.testing.assert_allclose( 

113 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround), 

114 np.array( 

115 [ 

116 47.20460719, 

117 56.35723637, 

118 241.04877377, 

119 73.65830083, 

120 86.21530880, 

121 46.77650619, 

122 301.77516676, 

123 np.nan, 

124 ] 

125 ), 

126 atol=TOLERANCE_ABSOLUTE_TESTS, 

127 ) 

128 

129 def test_n_dimensional_XYZ_to_Kim2009(self) -> None: 

130 """ 

131 Test :func:`colour.appearance.kim2009.XYZ_to_Kim2009` definition 

132 n-dimensional support. 

133 """ 

134 

135 XYZ = np.array([19.01, 20.00, 21.78]) 

136 XYZ_w = np.array([95.05, 100.00, 108.88]) 

137 L_a = 318.31 

138 media = MEDIA_PARAMETERS_KIM2009["CRT Displays"] 

139 surround = VIEWING_CONDITIONS_KIM2009["Average"] 

140 specification = XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround) 

141 

142 XYZ = np.tile(XYZ, (6, 1)) 

143 specification = np.tile(specification, (6, 1)) 

144 np.testing.assert_allclose( 

145 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround), 

146 specification, 

147 atol=TOLERANCE_ABSOLUTE_TESTS, 

148 ) 

149 

150 XYZ_w = np.tile(XYZ_w, (6, 1)) 

151 np.testing.assert_allclose( 

152 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround), 

153 specification, 

154 atol=TOLERANCE_ABSOLUTE_TESTS, 

155 ) 

156 

157 XYZ = np.reshape(XYZ, (2, 3, 3)) 

158 XYZ_w = np.reshape(XYZ_w, (2, 3, 3)) 

159 specification = np.reshape(specification, (2, 3, 8)) 

160 np.testing.assert_allclose( 

161 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround), 

162 specification, 

163 atol=TOLERANCE_ABSOLUTE_TESTS, 

164 ) 

165 

166 @ignore_numpy_errors 

167 def test_domain_range_scale_XYZ_to_Kim2009(self) -> None: 

168 """ 

169 Test :func:`colour.appearance.kim2009.XYZ_to_Kim2009` definition 

170 domain and range scale support. 

171 """ 

172 

173 XYZ = np.array([19.01, 20.00, 21.78]) 

174 XYZ_w = np.array([95.05, 100.00, 108.88]) 

175 L_a = 318.31 

176 media = MEDIA_PARAMETERS_KIM2009["CRT Displays"] 

177 surround = VIEWING_CONDITIONS_KIM2009["Average"] 

178 specification = XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround) 

179 

180 d_r = ( 

181 ("reference", 1, 1), 

182 ( 

183 "1", 

184 0.01, 

185 np.array( 

186 [ 

187 1 / 100, 

188 1 / 100, 

189 1 / 360, 

190 1 / 100, 

191 1 / 100, 

192 1 / 100, 

193 1 / 400, 

194 np.nan, 

195 ] 

196 ), 

197 ), 

198 ( 

199 "100", 

200 1, 

201 np.array([1, 1, 100 / 360, 1, 1, 1, 100 / 400, np.nan]), 

202 ), 

203 ) 

204 for scale, factor_a, factor_b in d_r: 

205 with domain_range_scale(scale): 

206 np.testing.assert_allclose( 

207 XYZ_to_Kim2009( 

208 XYZ * factor_a, XYZ_w * factor_a, L_a, media, surround 

209 ), 

210 as_float_array(specification) * factor_b, 

211 atol=TOLERANCE_ABSOLUTE_TESTS, 

212 ) 

213 

214 @ignore_numpy_errors 

215 def test_nan_XYZ_to_Kim2009(self) -> None: 

216 """ 

217 Test :func:`colour.appearance.kim2009.XYZ_to_Kim2009` definition 

218 nan support. 

219 """ 

220 

221 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan] 

222 cases = np.array(list(set(product(cases, repeat=3)))) 

223 media = MediaParameters_Kim2009(cases[0, 0]) 

224 surround = InductionFactors_Kim2009(cases[0, 0], cases[0, 0], cases[0, 0]) 

225 XYZ_to_Kim2009(cases, cases, cases[0, 0], media, surround) 

226 

227 

228class TestKim2009_to_XYZ: 

229 """ 

230 Define :func:`colour.appearance.kim2009.Kim2009_to_XYZ` definition unit 

231 tests methods. 

232 """ 

233 

234 def test_Kim2009_to_XYZ(self) -> None: 

235 """Test :func:`colour.appearance.kim2009.Kim2009_to_XYZ` definition.""" 

236 

237 specification = CAM_Specification_Kim2009( 

238 28.86190898, 

239 0.55924559, 

240 219.04806678, 

241 9.38377973, 

242 52.71388839, 

243 0.46417384, 

244 278.06028246, 

245 np.nan, 

246 ) 

247 XYZ_w = np.array([95.05, 100.00, 108.88]) 

248 L_a = 318.31 

249 media = MEDIA_PARAMETERS_KIM2009["CRT Displays"] 

250 surround = VIEWING_CONDITIONS_KIM2009["Average"] 

251 np.testing.assert_allclose( 

252 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround), 

253 np.array([19.01, 20.00, 21.78]), 

254 atol=0.01, 

255 ) 

256 

257 specification = CAM_Specification_Kim2009( 

258 70.15940419, 

259 57.89295872, 

260 21.27017200, 

261 61.23630434, 

262 128.14034598, 

263 48.05115573, 

264 1.41841443, 

265 np.nan, 

266 ) 

267 L_a = 31.83 

268 np.testing.assert_allclose( 

269 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround), 

270 np.array([57.06, 43.06, 31.96]), 

271 atol=0.01, 

272 ) 

273 

274 specification = CAM_Specification_Kim2009( 

275 -4.83430022, 

276 37.42013921, 

277 177.12166057, 

278 np.nan, 

279 -8.82944930, 

280 31.05871555, 

281 220.36270343, 

282 np.nan, 

283 ) 

284 XYZ_w = np.array([109.85, 100.00, 35.58]) 

285 L_a = 318.31 

286 np.testing.assert_allclose( 

287 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround), 

288 np.array([3.53, 6.56, 2.14]), 

289 atol=0.01, 

290 ) 

291 

292 specification = CAM_Specification_Kim2009( 

293 47.20460719, 

294 56.35723637, 

295 241.04877377, 

296 73.65830083, 

297 86.21530880, 

298 46.77650619, 

299 301.77516676, 

300 np.nan, 

301 ) 

302 L_a = 31.83 

303 np.testing.assert_allclose( 

304 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround), 

305 np.array([19.01, 20.00, 21.78]), 

306 atol=0.01, 

307 ) 

308 

309 def test_n_dimensional_Kim2009_to_XYZ(self) -> None: 

310 """ 

311 Test :func:`colour.appearance.kim2009.Kim2009_to_XYZ` definition 

312 n-dimensional support. 

313 """ 

314 

315 XYZ = np.array([19.01, 20.00, 21.78]) 

316 XYZ_w = np.array([95.05, 100.00, 108.88]) 

317 L_a = 318.31 

318 media = MEDIA_PARAMETERS_KIM2009["CRT Displays"] 

319 surround = VIEWING_CONDITIONS_KIM2009["Average"] 

320 specification = XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround) 

321 XYZ = Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround) 

322 

323 specification = CAM_Specification_Kim2009( 

324 *np.transpose(np.tile(tsplit(specification), (6, 1))).tolist() 

325 ) 

326 XYZ = np.tile(XYZ, (6, 1)) 

327 np.testing.assert_allclose( 

328 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround), 

329 XYZ, 

330 atol=TOLERANCE_ABSOLUTE_TESTS, 

331 ) 

332 

333 XYZ_w = np.tile(XYZ_w, (6, 1)) 

334 np.testing.assert_allclose( 

335 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround), 

336 XYZ, 

337 atol=TOLERANCE_ABSOLUTE_TESTS, 

338 ) 

339 

340 specification = CAM_Specification_Kim2009( 

341 *tsplit(np.reshape(specification, (2, 3, 8))).tolist() 

342 ) 

343 XYZ_w = np.reshape(XYZ_w, (2, 3, 3)) 

344 XYZ = np.reshape(XYZ, (2, 3, 3)) 

345 np.testing.assert_allclose( 

346 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround), 

347 XYZ, 

348 atol=TOLERANCE_ABSOLUTE_TESTS, 

349 ) 

350 

351 @ignore_numpy_errors 

352 def test_domain_range_scale_Kim2009_to_XYZ(self) -> None: 

353 """ 

354 Test :func:`colour.appearance.kim2009.Kim2009_to_XYZ` definition 

355 domain and range scale support. 

356 """ 

357 

358 XYZ_i = np.array([19.01, 20.00, 21.78]) 

359 XYZ_w = np.array([95.05, 100.00, 108.88]) 

360 L_a = 318.31 

361 media = MEDIA_PARAMETERS_KIM2009["CRT Displays"] 

362 surround = VIEWING_CONDITIONS_KIM2009["Average"] 

363 specification = XYZ_to_Kim2009(XYZ_i, XYZ_w, L_a, media, surround) 

364 XYZ = Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround) 

365 

366 d_r = ( 

367 ("reference", 1, 1), 

368 ( 

369 "1", 

370 np.array( 

371 [ 

372 1 / 100, 

373 1 / 100, 

374 1 / 360, 

375 1 / 100, 

376 1 / 100, 

377 1 / 100, 

378 1 / 400, 

379 np.nan, 

380 ] 

381 ), 

382 0.01, 

383 ), 

384 ( 

385 "100", 

386 np.array([1, 1, 100 / 360, 1, 1, 1, 100 / 400, np.nan]), 

387 1, 

388 ), 

389 ) 

390 for scale, factor_a, factor_b in d_r: 

391 with domain_range_scale(scale): 

392 np.testing.assert_allclose( 

393 Kim2009_to_XYZ( 

394 specification * factor_a, 

395 XYZ_w * factor_b, 

396 L_a, 

397 media, 

398 surround, 

399 ), 

400 XYZ * factor_b, 

401 atol=TOLERANCE_ABSOLUTE_TESTS, 

402 ) 

403 

404 @ignore_numpy_errors 

405 def test_raise_exception_Kim2009_to_XYZ(self) -> None: 

406 """ 

407 Test :func:`colour.appearance.kim2009.Kim2009_to_XYZ` definition 

408 raised exception. 

409 """ 

410 

411 pytest.raises( 

412 ValueError, 

413 Kim2009_to_XYZ, 

414 CAM_Specification_Kim2009( 

415 41.731091132513917, 

416 None, 

417 219.04843265831178, 

418 ), 

419 np.array([95.05, 100.00, 108.88]), 

420 318.31, 

421 20.0, 

422 VIEWING_CONDITIONS_KIM2009["Average"], 

423 ) 

424 

425 @ignore_numpy_errors 

426 def test_nan_Kim2009_to_XYZ(self) -> None: 

427 """ 

428 Test :func:`colour.appearance.kim2009.Kim2009_to_XYZ` definition nan 

429 support. 

430 """ 

431 

432 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan] 

433 cases = np.array(list(set(product(cases, repeat=3)))) 

434 media = MediaParameters_Kim2009(cases[0, 0]) 

435 surround = InductionFactors_Kim2009(cases[0, 0], cases[0, 0], cases[0, 0]) 

436 Kim2009_to_XYZ( 

437 CAM_Specification_Kim2009( 

438 cases[..., 0], cases[..., 0], cases[..., 0], M=50 

439 ), 

440 cases, 

441 cases[0, 0], 

442 media, 

443 surround, 

444 )