Coverage for models/tests/test_hunter_lab.py: 100%

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

2

3 from __future__ import annotations

4

5 from itertools import product

6

7 import numpy as np

8

9 from colour.colorimetry import TVS_ILLUMINANTS_HUNTERLAB

10 from colour.constants import TOLERANCE_ABSOLUTE_TESTS

11 from colour.models import (

12 Hunter_Lab_to_XYZ,

13 XYZ_to_Hunter_Lab,

14 XYZ_to_K_ab_HunterLab1966,

15)

16 from colour.utilities import domain_range_scale, ignore_numpy_errors

17

18 __author__ = "Colour Developers"

19 __copyright__ = "Copyright 2013 Colour Developers"

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

21 __maintainer__ = "Colour Developers"

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

23 __status__ = "Production"

24

25 __all__ = [

26 "TestXYZ_to_K_ab_HunterLab1966",

27 "TestXYZ_to_Hunter_Lab",

28 "TestHunter_Lab_to_XYZ",

29]

30

31

32 class TestXYZ_to_K_ab_HunterLab1966:

33 """

34 Define :func:`colour.models.hunter_lab.XYZ_to_K_ab_HunterLab1966`

35 definition unit tests methods.

36 """

37

38 def test_XYZ_to_K_ab_HunterLab1966(self) -> None:

39 """

40 Test :func:`colour.models.hunter_lab.XYZ_to_K_ab_HunterLab1966`

41 definition.

42 """

43

44 np.testing.assert_allclose(

45 XYZ_to_K_ab_HunterLab1966(

46 np.array([0.20654008, 0.12197225, 0.05136952]) * 100

47 ),

48 np.array([80.32152090, 14.59816495]),

49 atol=TOLERANCE_ABSOLUTE_TESTS,

50 )

51

52 np.testing.assert_allclose(

53 XYZ_to_K_ab_HunterLab1966(

54 np.array([0.14222010, 0.23042768, 0.10495772]) * 100

55 ),

56 np.array([66.65154834, 20.86664881]),

57 atol=TOLERANCE_ABSOLUTE_TESTS,

58 )

59

60 np.testing.assert_allclose(

61 XYZ_to_K_ab_HunterLab1966(

62 np.array([0.07818780, 0.06157201, 0.28099326]) * 100

63 ),

64 np.array([49.41960269, 34.14235426]),

65 atol=TOLERANCE_ABSOLUTE_TESTS,

66 )

67

68 def test_n_dimensional_XYZ_to_K_ab_HunterLab1966(self) -> None:

69 """

70 Test :func:`colour.models.hunter_lab.XYZ_to_K_ab_HunterLab1966`

71 definition n-dimensional support.

72 """

73

74 XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) * 100

75 K_ab = XYZ_to_K_ab_HunterLab1966(XYZ)

76

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

78 K_ab = np.tile(K_ab, (6, 1))

79 np.testing.assert_allclose(

80 XYZ_to_K_ab_HunterLab1966(XYZ), K_ab, atol=TOLERANCE_ABSOLUTE_TESTS

81 )

82

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

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

85 np.testing.assert_allclose(

86 XYZ_to_K_ab_HunterLab1966(XYZ), K_ab, atol=TOLERANCE_ABSOLUTE_TESTS

87 )

88

89 @ignore_numpy_errors

90 def test_nan_XYZ_to_K_ab_HunterLab1966(self) -> None:

91 """

92 Test :func:`colour.models.hunter_lab.XYZ_to_K_ab_HunterLab1966`

93 definition nan support.

94 """

95

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

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

98 XYZ_to_K_ab_HunterLab1966(cases)

99

100

101 class TestXYZ_to_Hunter_Lab:

102 """

103 Define :func:`colour.models.hunter_lab.XYZ_to_Hunter_Lab` definition unit

104 tests methods.

105 """

106

107 def test_XYZ_to_Hunter_Lab(self) -> None:

108 """Test :func:`colour.models.hunter_lab.XYZ_to_Hunter_Lab` definition."""

109

110 np.testing.assert_allclose(

111 XYZ_to_Hunter_Lab(np.array([0.20654008, 0.12197225, 0.05136952]) * 100),

112 np.array([34.92452577, 47.06189858, 14.38615107]),

113 atol=TOLERANCE_ABSOLUTE_TESTS,

114 )

115

116 np.testing.assert_allclose(

117 XYZ_to_Hunter_Lab(np.array([0.14222010, 0.23042768, 0.10495772]) * 100),

118 np.array([48.00288325, -28.98551622, 18.75564181]),

119 atol=TOLERANCE_ABSOLUTE_TESTS,

120 )

121

122 np.testing.assert_allclose(

123 XYZ_to_Hunter_Lab(np.array([0.07818780, 0.06157201, 0.28099326]) * 100),

124 np.array([24.81370791, 14.38300039, -53.25539126]),

125 atol=TOLERANCE_ABSOLUTE_TESTS,

126 )

127

128 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]

129 A = h_i["A"]

130 np.testing.assert_allclose(

131 XYZ_to_Hunter_Lab(

132 np.array([0.20654008, 0.12197225, 0.05136952]) * 100,

133 A.XYZ_n,

134 A.K_ab,

135 ),

136 np.array([34.92452577, 35.04243086, -2.47688619]),

137 atol=TOLERANCE_ABSOLUTE_TESTS,

138 )

139

140 D65 = h_i["D65"]

141 np.testing.assert_allclose(

142 XYZ_to_Hunter_Lab(

143 np.array([0.20654008, 0.12197225, 0.05136952]) * 100,

144 D65.XYZ_n,

145 D65.K_ab,

146 ),

147 np.array([34.92452577, 47.06189858, 14.38615107]),

148 atol=TOLERANCE_ABSOLUTE_TESTS,

149 )

150

151 np.testing.assert_allclose(

152 XYZ_to_Hunter_Lab(

153 np.array([0.20654008, 0.12197225, 0.05136952]) * 100,

154 D65.XYZ_n,

155 K_ab=None,

156 ),

157 np.array([34.92452577, 47.05669614, 14.38385238]),

158 atol=TOLERANCE_ABSOLUTE_TESTS,

159 )

160

161 def test_n_dimensional_XYZ_to_Hunter_Lab(self) -> None:

162 """

163 Test :func:`colour.models.hunter_lab.XYZ_to_Hunter_Lab` definition

164 n-dimensional support.

165 """

166

167 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]

168 D65 = h_i["D65"]

169

170 XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) * 100

171 XYZ_n = D65.XYZ_n

172 K_ab = D65.K_ab

173 Lab = XYZ_to_Hunter_Lab(XYZ, XYZ_n, K_ab)

174

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

176 Lab = np.tile(Lab, (6, 1))

177 np.testing.assert_allclose(

178 XYZ_to_Hunter_Lab(XYZ, XYZ_n, K_ab),

179 Lab,

180 atol=TOLERANCE_ABSOLUTE_TESTS,

181 )

182

183 XYZ_n = np.tile(XYZ_n, (6, 1))

184 K_ab = np.tile(K_ab, (6, 1))

185 np.testing.assert_allclose(

186 XYZ_to_Hunter_Lab(XYZ, XYZ_n, K_ab),

187 Lab,

188 atol=TOLERANCE_ABSOLUTE_TESTS,

189 )

190

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

192 XYZ_n = np.reshape(XYZ_n, (2, 3, 3))

193 K_ab = np.reshape(K_ab, (2, 3, 2))

194 Lab = np.reshape(Lab, (2, 3, 3))

195 np.testing.assert_allclose(

196 XYZ_to_Hunter_Lab(XYZ, XYZ_n, K_ab),

197 Lab,

198 atol=TOLERANCE_ABSOLUTE_TESTS,

199 )

200

201 def test_domain_range_scale_XYZ_to_Hunter_Lab(self) -> None:

202 """

203 Test :func:`colour.models.hunter_lab.XYZ_to_Hunter_Lab` definition

204 domain and range scale support.

205 """

206

207 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]

208 D65 = h_i["D65"]

209

210 XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) * 100

211 XYZ_n = D65.XYZ_n

212 K_ab = D65.K_ab

213 Lab = XYZ_to_Hunter_Lab(XYZ, XYZ_n, K_ab)

214

215 d_r = (("reference", 1), ("1", 0.01), ("100", 1))

216 for scale, factor in d_r:

217 with domain_range_scale(scale):

218 np.testing.assert_allclose(

219 XYZ_to_Hunter_Lab(XYZ * factor, XYZ_n * factor, K_ab),

220 Lab * factor,

221 atol=TOLERANCE_ABSOLUTE_TESTS,

222 )

223

224 @ignore_numpy_errors

225 def test_nan_XYZ_to_Hunter_Lab(self) -> None:

226 """

227 Test :func:`colour.models.hunter_lab.XYZ_to_Hunter_Lab` definition nan

228 support.

229 """

230

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

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

233 XYZ_to_Hunter_Lab(cases, cases, cases[..., 0:2])

234

235

236 class TestHunter_Lab_to_XYZ:

237 """

238 Define :func:`colour.models.hunter_lab.Hunter_Lab_to_XYZ` definition unit

239 tests methods.

240 """

241

242 def test_Hunter_Lab_to_XYZ(self) -> None:

243 """Test :func:`colour.models.hunter_lab.Hunter_Lab_to_XYZ` definition."""

244

245 np.testing.assert_allclose(

246 Hunter_Lab_to_XYZ(np.array([34.92452577, 47.06189858, 14.38615107])),

247 np.array([20.65400800, 12.19722500, 5.13695200]),

248 atol=TOLERANCE_ABSOLUTE_TESTS,

249 )

250

251 np.testing.assert_allclose(

252 Hunter_Lab_to_XYZ(np.array([48.00288325, -28.98551622, 18.75564181])),

253 np.array([14.22201000, 23.04276800, 10.49577200]),

254 atol=TOLERANCE_ABSOLUTE_TESTS,

255 )

256

257 np.testing.assert_allclose(

258 Hunter_Lab_to_XYZ(np.array([24.81370791, 14.38300039, -53.25539126])),

259 np.array([7.81878000, 6.15720100, 28.09932601]),

260 atol=TOLERANCE_ABSOLUTE_TESTS,

261 )

262

263 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]

264 A = h_i["A"]

265 np.testing.assert_allclose(

266 Hunter_Lab_to_XYZ(

267 np.array([34.92452577, 35.04243086, -2.47688619]),

268 A.XYZ_n,

269 A.K_ab,

270 ),

271 np.array([20.65400800, 12.19722500, 5.13695200]),

272 atol=TOLERANCE_ABSOLUTE_TESTS,

273 )

274

275 D65 = h_i["D65"]

276 np.testing.assert_allclose(

277 Hunter_Lab_to_XYZ(

278 np.array([34.92452577, 47.06189858, 14.38615107]),

279 D65.XYZ_n,

280 D65.K_ab,

281 ),

282 np.array([20.65400800, 12.19722500, 5.13695200]),

283 atol=TOLERANCE_ABSOLUTE_TESTS,

284 )

285

286 np.testing.assert_allclose(

287 Hunter_Lab_to_XYZ(

288 np.array([34.92452577, 47.05669614, 14.38385238]),

289 D65.XYZ_n,

290 K_ab=None,

291 ),

292 np.array([20.65400800, 12.19722500, 5.13695200]),

293 atol=TOLERANCE_ABSOLUTE_TESTS,

294 )

295

296 def test_n_dimensional_Hunter_Lab_to_XYZ(self) -> None:

297 """

298 Test :func:`colour.models.hunter_lab.Hunter_Lab_to_XYZ` definition

299 n-dimensional support.

300 """

301

302 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]

303 D65 = h_i["D65"]

304

305 Lab = np.array([34.92452577, 47.06189858, 14.38615107])

306 XYZ_n = D65.XYZ_n

307 K_ab = D65.K_ab

308 XYZ = Hunter_Lab_to_XYZ(Lab, XYZ_n, K_ab)

309

310 Lab = np.tile(Lab, (6, 1))

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

312 np.testing.assert_allclose(

313 Hunter_Lab_to_XYZ(Lab, XYZ_n, K_ab),

314 XYZ,

315 atol=TOLERANCE_ABSOLUTE_TESTS,

316 )

317

318 K_ab = np.tile(K_ab, (6, 1))

319 XYZ_n = np.tile(XYZ_n, (6, 1))

320 np.testing.assert_allclose(

321 Hunter_Lab_to_XYZ(Lab, XYZ_n, K_ab),

322 XYZ,

323 atol=TOLERANCE_ABSOLUTE_TESTS,

324 )

325

326 Lab = np.reshape(Lab, (2, 3, 3))

327 XYZ_n = np.reshape(XYZ_n, (2, 3, 3))

328 K_ab = np.reshape(K_ab, (2, 3, 2))

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

330 np.testing.assert_allclose(

331 Hunter_Lab_to_XYZ(Lab, XYZ_n, K_ab),

332 XYZ,

333 atol=TOLERANCE_ABSOLUTE_TESTS,

334 )

335

336 def test_domain_range_scale_Hunter_Lab_to_XYZ(self) -> None:

337 """

338 Test :func:`colour.models.hunter_lab.Hunter_Lab_to_XYZ` definition

339 domain and range scale support.

340 """

341

342 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]

343 D65 = h_i["D65"]

344

345 Lab = np.array([34.92452577, 47.06189858, 14.38615107])

346 XYZ_n = D65.XYZ_n

347 K_ab = D65.K_ab

348 XYZ = Hunter_Lab_to_XYZ(Lab, XYZ_n, K_ab)

349

350 d_r = (("reference", 1), ("1", 0.01), ("100", 1))

351 for scale, factor in d_r:

352 with domain_range_scale(scale):

353 np.testing.assert_allclose(

354 Hunter_Lab_to_XYZ(Lab * factor, XYZ_n * factor, K_ab),

355 XYZ * factor,

356 atol=TOLERANCE_ABSOLUTE_TESTS,

357 )

358

359 @ignore_numpy_errors

360 def test_nan_Hunter_Lab_to_XYZ(self) -> None:

361 """

362 Test :func:`colour.models.hunter_lab.Hunter_Lab_to_XYZ` definition

363 nan support.

364 """

365

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

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

368 Hunter_Lab_to_XYZ(cases, cases, cases[..., 0:2])