Coverage for models/rgb/tests/test_derivation.py: 100%

1"""Define the unit tests for the :mod:`colour.models.rgb.derivation` module."""

2

3 from __future__ import annotations

4

5 import contextlib

6 import re

7 from itertools import product

8

9 import numpy as np

10 from numpy.linalg import LinAlgError

11

12 from colour.constants import TOLERANCE_ABSOLUTE_TESTS

13 from colour.models import (

14 RGB_luminance,

15 RGB_luminance_equation,

16 chromatically_adapted_primaries,

17 normalised_primary_matrix,

18 primaries_whitepoint,

19)

20 from colour.models.rgb.derivation import xy_to_z

21 from colour.utilities import ignore_numpy_errors

22

23 __author__ = "Colour Developers"

24 __copyright__ = "Copyright 2013 Colour Developers"

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

26 __maintainer__ = "Colour Developers"

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

28 __status__ = "Production"

29

30 __all__ = [

31 "Testxy_to_z",

32 "TestNormalisedPrimaryMatrix",

33 "TestChromaticallyAdaptedPrimaries",

34 "TestPrimariesWhitepoint",

35 "TestRGBLuminanceEquation",

36 "TestRGBLuminance",

37]

38

39

40 class Testxy_to_z:

41 """

42 Define :func:`colour.models.rgb.derivation.xy_to_z` definition unit

43 tests methods.

44 """

45

46 def test_xy_to_z(self) -> None:

47 """Test :func:`colour.models.rgb.derivation.xy_to_z` definition."""

48

49 np.testing.assert_allclose(

50 xy_to_z(np.array([0.2500, 0.2500])),

51 0.50000000,

52 atol=TOLERANCE_ABSOLUTE_TESTS,

53 )

54

55 np.testing.assert_allclose(

56 xy_to_z(np.array([0.0001, -0.0770])),

57 1.07690000,

58 atol=TOLERANCE_ABSOLUTE_TESTS,

59 )

60

61 np.testing.assert_allclose(

62 xy_to_z(np.array([0.0000, 1.0000])),

63 0.00000000,

64 atol=TOLERANCE_ABSOLUTE_TESTS,

65 )

66

67 def test_n_dimensional_xy_to_z(self) -> None:

68 """

69 Test :func:`colour.models.rgb.derivation.xy_to_z` definition

70 n-dimensional arrays support.

71 """

72

73 xy = np.array([0.25, 0.25])

74 z = xy_to_z(xy)

75

76 xy = np.tile(xy, (6, 1))

77 z = np.tile(

78 z,

79 6,

80 )

81 np.testing.assert_allclose(xy_to_z(xy), z, atol=TOLERANCE_ABSOLUTE_TESTS)

82

83 xy = np.reshape(xy, (2, 3, 2))

84 z = np.reshape(z, (2, 3))

85 np.testing.assert_allclose(xy_to_z(xy), z, atol=TOLERANCE_ABSOLUTE_TESTS)

86

87 @ignore_numpy_errors

88 def test_nan_xy_to_z(self) -> None:

89 """

90 Test :func:`colour.models.rgb.derivation.xy_to_z` definition nan

91 support.

92 """

93

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

95 cases = np.array(list(set(product(cases, repeat=2))))

96 xy_to_z(cases)

97

98

99 class TestNormalisedPrimaryMatrix:

100 """

101 Define :func:`colour.models.rgb.derivation.normalised_primary_matrix`

102 definition unit tests methods.

103 """

104

105 def test_normalised_primary_matrix(self) -> None:

106 """

107 Test :func:`colour.models.rgb.derivation.normalised_primary_matrix`

108 definition.

109 """

110

111 np.testing.assert_allclose(

112 normalised_primary_matrix(

113 np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),

114 np.array([0.32168, 0.33767]),

115 ),

116 np.array(

117 [

118 [0.95255240, 0.00000000, 0.00009368],

119 [0.34396645, 0.72816610, -0.07213255],

120 [0.00000000, 0.00000000, 1.00882518],

121 ]

122 ),

123 atol=TOLERANCE_ABSOLUTE_TESTS,

124 )

125

126 np.testing.assert_allclose(

127 normalised_primary_matrix(

128 np.array([0.640, 0.330, 0.300, 0.600, 0.150, 0.060]),

129 np.array([0.3127, 0.3290]),

130 ),

131 np.array(

132 [

133 [0.41239080, 0.35758434, 0.18048079],

134 [0.21263901, 0.71516868, 0.07219232],

135 [0.01933082, 0.11919478, 0.95053215],

136 ]

137 ),

138 atol=TOLERANCE_ABSOLUTE_TESTS,

139 )

140

141 @ignore_numpy_errors

142 def test_nan_normalised_primary_matrix(self) -> None:

143 """

144 Test :func:`colour.models.rgb.derivation.normalised_primary_matrix`

145 definition nan support.

146 """

147

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

149 cases = np.array(list(set(product(cases, repeat=2))))

150 for case in cases:

151 P = np.array(np.vstack([case, case, case]))

152 W = case

153 with contextlib.suppress(LinAlgError):

154 normalised_primary_matrix(P, W)

155

156

157 class TestChromaticallyAdaptedPrimaries:

158 """

159 Define :func:`colour.models.rgb.derivation.\

160 chromatically_adapted_primaries` definition unit tests methods.

161 """

162

163 def test_chromatically_adapted_primaries(self) -> None:

164 """

165 Test :func:`colour.models.rgb.derivation.\

166 chromatically_adapted_primaries` definition.

167 """

168

169 np.testing.assert_allclose(

170 chromatically_adapted_primaries(

171 np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),

172 np.array([0.32168, 0.33767]),

173 np.array([0.34570, 0.35850]),

174 ),

175 np.array(

176 [

177 [0.73431182, 0.26694964],

178 [0.02211963, 0.98038009],

179 [-0.05880375, -0.12573056],

180 ]

181 ),

182 atol=TOLERANCE_ABSOLUTE_TESTS,

183 )

184

185 np.testing.assert_allclose(

186 chromatically_adapted_primaries(

187 np.array([0.640, 0.330, 0.300, 0.600, 0.150, 0.060]),

188 np.array([0.31270, 0.32900]),

189 np.array([0.34570, 0.35850]),

190 ),

191 np.array(

192 [

193 [0.64922534, 0.33062196],

194 [0.32425276, 0.60237128],

195 [0.15236177, 0.06118676],

196 ]

197 ),

198 atol=TOLERANCE_ABSOLUTE_TESTS,

199 )

200

201 np.testing.assert_allclose(

202 chromatically_adapted_primaries(

203 np.array([0.640, 0.330, 0.300, 0.600, 0.150, 0.060]),

204 np.array([0.31270, 0.32900]),

205 np.array([0.34570, 0.35850]),

206 "Bradford",

207 ),

208 np.array(

209 [

210 [0.64844144, 0.33085331],

211 [0.32119518, 0.59784434],

212 [0.15589322, 0.06604921],

213 ]

214 ),

215 atol=TOLERANCE_ABSOLUTE_TESTS,

216 )

217

218 @ignore_numpy_errors

219 def test_nan_chromatically_adapted_primaries(self) -> None:

220 """

221 Test :func:`colour.models.rgb.derivation.\

222 chromatically_adapted_primaries` definition nan support.

223 """

224

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

226 cases = np.array(list(set(product(cases, repeat=2))))

227 for case in cases:

228 P = np.array(np.vstack([case, case, case]))

229 W = case

230 chromatically_adapted_primaries(P, W, W)

231

232

233 class TestPrimariesWhitepoint:

234 """

235 Define :func:`colour.models.rgb.derivation.primaries_whitepoint`

236 definition unit tests methods.

237 """

238

239 def test_primaries_whitepoint(self) -> None:

240 """

241 Test :func:`colour.models.rgb.derivation.primaries_whitepoint`

242 definition.

243 """

244

245 P, W = primaries_whitepoint(

246 np.array(

247 [

248 [0.95255240, 0.00000000, 0.00009368],

249 [0.34396645, 0.72816610, -0.07213255],

250 [0.00000000, 0.00000000, 1.00882518],

251 ]

252 )

253 )

254 np.testing.assert_allclose(

255 P,

256 np.array(

257 [

258 [0.73470, 0.26530],

259 [0.00000, 1.00000],

260 [0.00010, -0.07700],

261 ]

262 ),

263 atol=TOLERANCE_ABSOLUTE_TESTS,

264 )

265 np.testing.assert_allclose(

266 W, np.array([0.32168, 0.33767]), atol=TOLERANCE_ABSOLUTE_TESTS

267 )

268

269 P, W = primaries_whitepoint(

270 np.array(

271 [

272 [0.41240000, 0.35760000, 0.18050000],

273 [0.21260000, 0.71520000, 0.07220000],

274 [0.01930000, 0.11920000, 0.95050000],

275 ]

276 )

277 )

278 np.testing.assert_allclose(

279 P,

280 np.array(

281 [

282 [0.64007450, 0.32997051],

283 [0.30000000, 0.60000000],

284 [0.15001662, 0.06000665],

285 ]

286 ),

287 atol=TOLERANCE_ABSOLUTE_TESTS,

288 )

289 np.testing.assert_allclose(

290 W,

291 np.array([0.31271591, 0.32900148]),

292 atol=TOLERANCE_ABSOLUTE_TESTS,

293 )

294

295 @ignore_numpy_errors

296 def test_nan_primaries_whitepoint(self) -> None:

297 """

298 Test :func:`colour.models.rgb.derivation.primaries_whitepoint`

299 definition nan support.

300 """

301

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

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

304 for case in cases:

305 M = np.array(np.vstack([case, case, case]))

306 primaries_whitepoint(M)

307

308

309 class TestRGBLuminanceEquation:

310 """

311 Define :func:`colour.models.rgb.derivation.RGB_luminance_equation`

312 definition unit tests methods.

313 """

314

315 def test_RGB_luminance_equation(self) -> None:

316 """

317 Test :func:`colour.models.rgb.derivation.RGB_luminance_equation`

318 definition.

319 """

320

321 assert isinstance(

322 RGB_luminance_equation(

323 np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),

324 np.array([0.32168, 0.33767]),

325 ),

326 str,

327 )

328

329 # TODO: Simplify that monster.

330 pattern = (

331 "Y\\s?=\\s?[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?."

332 "\\(R\\)\\s?[+-]\\s?[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?."

333 "\\(G\\)\\s?[+-]\\s?[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?."

334 "\\(B\\)"

335 )

336 P = np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700])

337 assert re.match(

338 pattern,

339 RGB_luminance_equation(P, np.array([0.32168, 0.33767])),

340 )

341

342

343 class TestRGBLuminance:

344 """

345 Define :func:`colour.models.rgb.derivation.RGB_luminance` definition

346 unit tests methods.

347 """

348

349 def test_RGB_luminance(self) -> None:

350 """

351 Test :func:`colour.models.rgb.derivation.RGB_luminance`

352 definition.

353 """

354

355 np.testing.assert_allclose(

356 RGB_luminance(

357 np.array([0.18, 0.18, 0.18]),

358 np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),

359 np.array([0.32168, 0.33767]),

360 ),

361 0.18000000,

362 atol=TOLERANCE_ABSOLUTE_TESTS,

363 )

364

365 np.testing.assert_allclose(

366 RGB_luminance(

367 np.array([0.21959402, 0.06986677, 0.04703877]),

368 np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),

369 np.array([0.32168, 0.33767]),

370 ),

371 0.123014562384318,

372 atol=TOLERANCE_ABSOLUTE_TESTS,

373 )

374

375 np.testing.assert_allclose(

376 RGB_luminance(

377 np.array([0.45620519, 0.03081071, 0.04091952]),

378 np.array([0.6400, 0.3300, 0.3000, 0.6000, 0.1500, 0.0600]),

379 np.array([0.31270, 0.32900]),

380 ),

381 0.121995947729870,

382 atol=TOLERANCE_ABSOLUTE_TESTS,

383 )

384

385 def test_n_dimensional_RGB_luminance(self) -> None:

386 """

387 Test :func:`colour.models.rgb.derivation.RGB_luminance` definition

388 n_dimensional arrays support.

389 """

390

391 RGB = (np.array([0.18, 0.18, 0.18]),)

392 P = (np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),)

393 W = np.array([0.32168, 0.33767])

394 Y = RGB_luminance(RGB, P, W)

395

396 RGB = np.tile(RGB, (6, 1))

397 Y = np.tile(Y, 6)

398 np.testing.assert_allclose(

399 RGB_luminance(RGB, P, W), Y, atol=TOLERANCE_ABSOLUTE_TESTS

400 )

401

402 RGB = np.reshape(RGB, (2, 3, 3))

403 Y = np.reshape(Y, (2, 3))

404 np.testing.assert_allclose(

405 RGB_luminance(RGB, P, W), Y, atol=TOLERANCE_ABSOLUTE_TESTS

406 )

407

408 @ignore_numpy_errors

409 def test_nan_RGB_luminance(self) -> None:

410 """

411 Test :func:`colour.models.rgb.derivation.RGB_luminance`

412 definition nan support.

413 """

414

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

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

417 for case in cases:

418 RGB = case

419 P = np.array(np.vstack([case[0:2], case[0:2], case[0:2]]))

420 W = case[0:2]

421 with contextlib.suppress(LinAlgError):

422 RGB_luminance(RGB, P, W)