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

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

2

3 from __future__ import annotations

4

5 from itertools import product

6

7 import numpy as np

8

9 from colour.constants import TOLERANCE_ABSOLUTE_TESTS

10 from colour.models import (

11 XYZ_to_sUCS,

12 sUCS_chroma,

13 sUCS_hue_angle,

14 sUCS_Iab_to_sUCS_ICh,

15 sUCS_ICh_to_sUCS_Iab,

16 sUCS_to_XYZ,

17)

18 from colour.utilities import domain_range_scale, ignore_numpy_errors

19

20 __author__ = "UltraMo114(Molin Li), Colour Developers"

21 __copyright__ = "Copyright 2013 Colour Developers"

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

23 __maintainer__ = "Colour Developers"

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

25 __status__ = "Production"

26

27 __all__ = [

28 "TestXYZ_to_sUCS",

29 "TestsUCS_to_XYZ",

30 "TestsUCSChroma",

31 "TestsUCSHueAngle",

32 "TestsUCS_Iab_to_sUCS_ICh",

33 "TestsUCS_ICh_to_sUCS_Iab",

34]

35

36

37 class TestXYZ_to_sUCS:

38 """Define :func:`colour.models.sucs.XYZ_to_sUCS` definition unit tests methods."""

39

40 def test_XYZ_to_sUCS(self) -> None:

41 """Test :func:`colour.models.sucs.XYZ_to_sUCS` definition."""

42

43 np.testing.assert_allclose(

44 XYZ_to_sUCS(np.array([0.20654008, 0.12197225, 0.05136952])),

45 np.array([42.62923653, 36.97646831, 14.12301358]),

46 atol=TOLERANCE_ABSOLUTE_TESTS,

47 )

48

49 np.testing.assert_allclose(

50 XYZ_to_sUCS(np.array([0.14222010, 0.23042768, 0.10495772])),

51 np.array([51.93649255, -18.89245582, 15.76112395]),

52 atol=TOLERANCE_ABSOLUTE_TESTS,

53 )

54

55 np.testing.assert_allclose(

56 XYZ_to_sUCS(np.array([0.07818780, 0.06157201, 0.28099326])),

57 np.array([29.79456846, -6.83806757, -25.33884097]),

58 atol=TOLERANCE_ABSOLUTE_TESTS,

59 )

60

61 def test_n_dimensional_XYZ_to_sUCS(self) -> None:

62 """

63 Test :func:`colour.models.sucs.XYZ_to_sUCS` definition n-dimensional

64 support.

65 """

66

67 XYZ = np.array([0.20654008, 0.12197225, 0.05136952])

68 Iab = XYZ_to_sUCS(XYZ)

69

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

71 Iab = np.tile(Iab, (6, 1))

72 np.testing.assert_allclose(XYZ_to_sUCS(XYZ), Iab, atol=TOLERANCE_ABSOLUTE_TESTS)

73

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

75 Iab = np.reshape(Iab, (2, 3, 3))

76 np.testing.assert_allclose(XYZ_to_sUCS(XYZ), Iab, atol=TOLERANCE_ABSOLUTE_TESTS)

77

78 def test_domain_range_scale_XYZ_to_sUCS(self) -> None:

79 """

80 Test :func:`colour.models.sucs.XYZ_to_sUCS` definition domain and

81 range scale support.

82 """

83

84 XYZ = np.array([0.20654008, 0.12197225, 0.05136952])

85 Iab = XYZ_to_sUCS(XYZ)

86

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

88 for scale, factor_a, factor_b in d_r:

89 with domain_range_scale(scale):

90 np.testing.assert_allclose(

91 XYZ_to_sUCS(XYZ * factor_a),

92 Iab * factor_b,

93 atol=TOLERANCE_ABSOLUTE_TESTS,

94 )

95

96 @ignore_numpy_errors

97 def test_nan_XYZ_to_sUCS(self) -> None:

98 """Test :func:`colour.models.sucs.XYZ_to_sUCS` definition nan support."""

99

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

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

102 XYZ_to_sUCS(cases)

103

104

105 class TestsUCS_to_XYZ:

106 """

107 Define :func:`colour.models.sucs.sUCS_to_XYZ` definition unit tests

108 methods.

109 """

110

111 def test_sUCS_to_XYZ(self) -> None:

112 """Test :func:`colour.models.sucs.sUCS_to_XYZ` definition."""

113

114 np.testing.assert_allclose(

115 sUCS_to_XYZ(np.array([42.62923653, 36.97646831, 14.12301358])),

116 np.array([0.20654008, 0.12197225, 0.05136952]),

117 atol=TOLERANCE_ABSOLUTE_TESTS,

118 )

119

120 np.testing.assert_allclose(

121 sUCS_to_XYZ(np.array([51.93649255, -18.89245582, 15.76112395])),

122 np.array([0.14222010, 0.23042768, 0.10495772]),

123 atol=TOLERANCE_ABSOLUTE_TESTS,

124 )

125

126 np.testing.assert_allclose(

127 sUCS_to_XYZ(np.array([29.79456846, -6.83806757, -25.33884097])),

128 np.array([0.07818780, 0.06157201, 0.28099326]),

129 atol=TOLERANCE_ABSOLUTE_TESTS,

130 )

131

132 def test_n_dimensional_sUCS_to_XYZ(self) -> None:

133 """

134 Test :func:`colour.models.sucs.sUCS_to_XYZ` definition n-dimensional

135 support.

136 """

137

138 Iab = np.array([42.62923653, 36.97646831, 14.12301358])

139 XYZ = sUCS_to_XYZ(Iab)

140

141 Iab = np.tile(Iab, (6, 1))

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

143 np.testing.assert_allclose(sUCS_to_XYZ(Iab), XYZ, atol=TOLERANCE_ABSOLUTE_TESTS)

144

145 Iab = np.reshape(Iab, (2, 3, 3))

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

147 np.testing.assert_allclose(sUCS_to_XYZ(Iab), XYZ, atol=TOLERANCE_ABSOLUTE_TESTS)

148

149 def test_domain_range_scale_sUCS_to_XYZ(self) -> None:

150 """

151 Test :func:`colour.models.sucs.sUCS_to_XYZ` definition domain and

152 range scale support.

153 """

154

155 Iab = np.array([42.62923653, 36.97646831, 14.12301358])

156 XYZ = sUCS_to_XYZ(Iab)

157

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

159 for scale, factor_a, factor_b in d_r:

160 with domain_range_scale(scale):

161 np.testing.assert_allclose(

162 sUCS_to_XYZ(Iab * factor_a),

163 XYZ * factor_b,

164 atol=TOLERANCE_ABSOLUTE_TESTS,

165 )

166

167 @ignore_numpy_errors

168 def test_nan_sUCS_to_XYZ(self) -> None:

169 """Test :func:`colour.models.sucs.sUCS_to_XYZ` definition nan support."""

170

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

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

173 sUCS_to_XYZ(cases)

174

175

176 class TestsUCSChroma:

177 """

178 Define :func:`colour.models.sucs.sUCS_chroma` definition unit tests

179 methods.

180 """

181

182 def test_sUCS_hue_angle(self) -> None:

183 """Test :func:`colour.models.sucs.sUCS_chroma` definition."""

184

185 np.testing.assert_allclose(

186 sUCS_chroma(np.array([42.62923653, 36.97646831, 14.12301358])),

187 40.420511061137226,

188 atol=TOLERANCE_ABSOLUTE_TESTS,

189 )

190

191 np.testing.assert_allclose(

192 sUCS_chroma(np.array([51.93649255, -18.89245582, 15.76112395])),

193 29.437831501432590,

194 atol=TOLERANCE_ABSOLUTE_TESTS,

195 )

196

197 np.testing.assert_allclose(

198 sUCS_chroma(np.array([29.79456846, -6.83806757, -25.33884097])),

199 30.800979756091614,

200 atol=TOLERANCE_ABSOLUTE_TESTS,

201 )

202

203 def test_n_dimensional_sUCS_hue_angle(self) -> None:

204 """

205 Test :func:`colour.models.sucs.sUCS_chroma` definition n-dimensional

206 support.

207 """

208

209 Iab = np.array([42.62923653, 36.97646831, 14.12301358])

210 C = sUCS_chroma(Iab)

211

212 Iab = np.tile(Iab, (6, 1))

213 C = np.tile(C, 6)

214 np.testing.assert_allclose(sUCS_chroma(Iab), C, atol=TOLERANCE_ABSOLUTE_TESTS)

215

216 Iab = np.reshape(Iab, (2, 3, 3))

217 C = np.reshape(C, (2, 3))

218 np.testing.assert_allclose(sUCS_chroma(Iab), C, atol=TOLERANCE_ABSOLUTE_TESTS)

219

220 def test_domain_range_scale_sUCS_chroma(self) -> None:

221 """

222 Test :func:`colour.models.sucs.sUCS_chroma` definition domain and

223 range scale support.

224 """

225

226 Iab = np.array([42.62923653, 36.97646831, 14.12301358])

227 C = sUCS_chroma(Iab)

228

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

230 for scale, factor_a, factor_b in d_r:

231 with domain_range_scale(scale):

232 np.testing.assert_allclose(

233 sUCS_chroma(Iab * factor_a),

234 C * factor_b,

235 atol=TOLERANCE_ABSOLUTE_TESTS,

236 )

237

238 @ignore_numpy_errors

239 def test_nan_sUCS_hue_angle(self) -> None:

240 """Test :func:`colour.models.sucs.sUCS_chroma` definition nan support."""

241

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

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

244 sUCS_chroma(cases)

245

246

247 class TestsUCSHueAngle:

248 """

249 Define :func:`colour.models.sucs.sUCS_hue_angle` definition unit tests

250 methods.

251 """

252

253 def test_sUCS_hue_angle(self) -> None:

254 """Test :func:`colour.models.sucs.sUCS_hue_angle` definition."""

255

256 np.testing.assert_allclose(

257 sUCS_hue_angle(np.array([42.62923653, 36.97646831, 14.12301358])),

258 20.904156072136217,

259 atol=TOLERANCE_ABSOLUTE_TESTS,

260 )

261

262 np.testing.assert_allclose(

263 sUCS_hue_angle(np.array([51.93649255, -18.89245582, 15.76112395])),

264 140.163281067124470,

265 atol=TOLERANCE_ABSOLUTE_TESTS,

266 )

267

268 np.testing.assert_allclose(

269 sUCS_hue_angle(np.array([29.79456846, -6.83806757, -25.33884097])),

270 254.897631851863850,

271 atol=TOLERANCE_ABSOLUTE_TESTS,

272 )

273

274 def test_n_dimensional_sUCS_hue_angle(self) -> None:

275 """

276 Test :func:`colour.models.sucs.sUCS_hue_angle` definition n-dimensional

277 support.

278 """

279

280 Iab = np.array([42.62923653, 36.97646831, 14.12301358])

281 hue = sUCS_hue_angle(Iab)

282

283 Iab = np.tile(Iab, (6, 1))

284 hue = np.tile(hue, 6)

285 np.testing.assert_allclose(

286 sUCS_hue_angle(Iab), hue, atol=TOLERANCE_ABSOLUTE_TESTS

287 )

288

289 Iab = np.reshape(Iab, (2, 3, 3))

290 hue = np.reshape(hue, (2, 3))

291 np.testing.assert_allclose(

292 sUCS_hue_angle(Iab), hue, atol=TOLERANCE_ABSOLUTE_TESTS

293 )

294

295 def test_domain_range_scale_sUCS_hue_angle(self) -> None:

296 """

297 Test :func:`colour.models.sucs.sUCS_hue_angle` definition domain and

298 range scale support.

299 """

300

301 Iab = np.array([42.62923653, 36.97646831, 14.12301358])

302 hue = sUCS_hue_angle(Iab)

303

304 d_r = (("reference", 1, 1), ("1", 1, 1 / 360), ("100", 100, 1 / 3.6))

305 for scale, factor_a, factor_b in d_r:

306 with domain_range_scale(scale):

307 np.testing.assert_allclose(

308 sUCS_hue_angle(Iab * factor_a),

309 hue * factor_b,

310 atol=TOLERANCE_ABSOLUTE_TESTS,

311 )

312

313 @ignore_numpy_errors

314 def test_nan_sUCS_hue_angle(self) -> None:

315 """Test :func:`colour.models.sucs.sUCS_hue_angle` definition nan support."""

316

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

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

319 sUCS_hue_angle(cases)

320

321

322 class TestsUCS_Iab_to_sUCS_ICh:

323 """

324 Define :func:`colour.models.sucs.sUCS_Iab_to_sUCS_ICh` definition unit tests

325 methods.

326 """

327

328 def test_sUCS_Iab_to_sUCS_ICh(self) -> None:

329 """Test :func:`colour.models.sucs.sUCS_Iab_to_sUCS_ICh` definition."""

330

331 np.testing.assert_allclose(

332 sUCS_Iab_to_sUCS_ICh(np.array([42.62923653, 36.97646831, 14.12301358])),

333 np.array([42.62923653, 40.42051106, 20.90415607]),

334 atol=TOLERANCE_ABSOLUTE_TESTS,

335 )

336

337 np.testing.assert_allclose(

338 sUCS_Iab_to_sUCS_ICh(np.array([51.93649255, -18.89245582, 15.76112395])),

339 np.array([51.93649255, 29.43783150, 140.16328107]),

340 atol=TOLERANCE_ABSOLUTE_TESTS,

341 )

342

343 np.testing.assert_allclose(

344 sUCS_Iab_to_sUCS_ICh(np.array([29.79456846, -6.83806757, -25.33884097])),

345 np.array([29.79456846, 30.80097976, 254.89763185]),

346 atol=TOLERANCE_ABSOLUTE_TESTS,

347 )

348

349 def test_n_dimensional_sUCS_Iab_to_sUCS_ICh(self) -> None:

350 """

351 Test :func:`colour.models.sucs.sUCS_Iab_to_sUCS_ICh` definition

352 n-dimensional support.

353 """

354

355 Iab = np.array([42.62923653, 36.97646831, 14.12301358])

356 ICh = sUCS_Iab_to_sUCS_ICh(Iab)

357

358 Iab = np.tile(Iab, (6, 1))

359 ICh = np.tile(ICh, (6, 1))

360 np.testing.assert_allclose(

361 sUCS_Iab_to_sUCS_ICh(Iab), ICh, atol=TOLERANCE_ABSOLUTE_TESTS

362 )

363

364 Iab = np.reshape(Iab, (2, 3, 3))

365 ICh = np.reshape(ICh, (2, 3, 3))

366 np.testing.assert_allclose(

367 sUCS_Iab_to_sUCS_ICh(Iab), ICh, atol=TOLERANCE_ABSOLUTE_TESTS

368 )

369

370 def test_domain_range_scale_sUCS_Iab_to_sUCS_ICh(self) -> None:

371 """

372 Test :func:`colour.models.sucs.sUCS_Iab_to_sUCS_ICh` definition domain

373 and range scale support.

374 """

375

376 Iab = np.array([42.62923653, 36.97646831, 14.12301358])

377 ICh = sUCS_Iab_to_sUCS_ICh(Iab)

378

379 d_r = (

380 ("reference", 1, 1),

381 ("1", 0.01, np.array([0.01, 0.01, 1 / 360])),

382 ("100", 1, np.array([1, 1, 100 / 360])),

383 )

384 for scale, factor_a, factor_b in d_r:

385 with domain_range_scale(scale):

386 np.testing.assert_allclose(

387 sUCS_Iab_to_sUCS_ICh(Iab * factor_a),

388 ICh * factor_b,

389 atol=TOLERANCE_ABSOLUTE_TESTS,

390 )

391

392 @ignore_numpy_errors

393 def test_nan_sUCS_Iab_to_sUCS_ICh(self) -> None:

394 """

395 Test :func:`colour.models.sucs.sUCS_Iab_to_sUCS_ICh` definition nan support.

396 """

397

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

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

400 sUCS_Iab_to_sUCS_ICh(cases)

401

402

403 class TestsUCS_ICh_to_sUCS_Iab:

404 """

405 Define :func:`colour.models.sucs.sUCS_ICh_to_sUCS_Iab` definition unit tests

406 methods.

407 """

408

409 def test_sUCS_ICh_to_sUCS_Iab(self) -> None:

410 """Test :func:`colour.models.sucs.sUCS_ICh_to_sUCS_Iab` definition."""

411

412 np.testing.assert_allclose(

413 sUCS_ICh_to_sUCS_Iab(np.array([42.62923653, 40.42051106, 20.90415607])),

414 np.array([42.62923653, 36.97646831, 14.12301358]),

415 atol=TOLERANCE_ABSOLUTE_TESTS,

416 )

417

418 np.testing.assert_allclose(

419 sUCS_ICh_to_sUCS_Iab(np.array([51.93649255, 29.43783150, 140.16328107])),

420 np.array([51.93649255, -18.89245582, 15.76112395]),

421 atol=TOLERANCE_ABSOLUTE_TESTS,

422 )

423

424 np.testing.assert_allclose(

425 sUCS_ICh_to_sUCS_Iab(np.array([29.79456846, 30.80097976, 254.89763185])),

426 np.array([29.79456846, -6.83806757, -25.33884097]),

427 atol=TOLERANCE_ABSOLUTE_TESTS,

428 )

429

430 def test_n_dimensional_sUCS_ICh_to_sUCS_Iab(self) -> None:

431 """

432 Test :func:`colour.models.sucs.sUCS_ICh_to_sUCS_Iab` definition

433 n-dimensional support.

434 """

435

436 ICh = np.array([42.62923653, 40.42051106, 20.90415607])

437 Iab = sUCS_ICh_to_sUCS_Iab(ICh)

438

439 ICh = np.tile(ICh, (6, 1))

440 Iab = np.tile(Iab, (6, 1))

441 np.testing.assert_allclose(

442 sUCS_ICh_to_sUCS_Iab(ICh), Iab, atol=TOLERANCE_ABSOLUTE_TESTS

443 )

444

445 ICh = np.reshape(ICh, (2, 3, 3))

446 Iab = np.reshape(Iab, (2, 3, 3))

447 np.testing.assert_allclose(

448 sUCS_ICh_to_sUCS_Iab(ICh), Iab, atol=TOLERANCE_ABSOLUTE_TESTS

449 )

450

451 def test_domain_range_scale_sUCS_ICh_to_sUCS_Iab(self) -> None:

452 """

453 Test :func:`colour.models.sucs.sUCS_ICh_to_sUCS_Iab` definition domain

454 and range scale support.

455 """

456

457 ICh = np.array([42.62923653, 40.42051106, 20.90415607])

458 Iab = sUCS_ICh_to_sUCS_Iab(ICh)

459

460 d_r = (

461 ("reference", 1, 1),

462 ("1", np.array([0.01, 0.01, 1 / 360]), 0.01),

463 ("100", np.array([1, 1, 100 / 360]), 1),

464 )

465 for scale, factor_a, factor_b in d_r:

466 with domain_range_scale(scale):

467 np.testing.assert_allclose(

468 sUCS_ICh_to_sUCS_Iab(ICh * factor_a),

469 Iab * factor_b,

470 atol=TOLERANCE_ABSOLUTE_TESTS,

471 )

472

473 @ignore_numpy_errors

474 def test_nan_sUCS_ICh_to_sUCS_Iab(self) -> None:

475 """

476 Test :func:`colour.models.sucs.sUCS_ICh_to_sUCS_Iab` definition nan support.

477 """

478

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

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

481 sUCS_ICh_to_sUCS_Iab(cases)