Coverage for algebra/tests/test_interpolation.py: 100%

264 statements  

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

1""" 

2Define the unit tests for the :mod:`colour.algebra.interpolation` module. 

3 

4References 

5---------- 

6- :cite:`Fairman1985b` : Fairman, H. S. (1985). The calculation of weight 

7 factors for tristimulus integration. Color Research & Application, 10(4), 

8 199-203. doi:10.1002/col.5080100407 

9""" 

10 

11from __future__ import annotations 

12 

13import os 

14from itertools import product 

15 

16import numpy as np 

17import pytest 

18 

19from colour.algebra import ( 

20 CubicSplineInterpolator, 

21 KernelInterpolator, 

22 LinearInterpolator, 

23 NearestNeighbourInterpolator, 

24 NullInterpolator, 

25 PchipInterpolator, 

26 SpragueInterpolator, 

27 kernel_cardinal_spline, 

28 kernel_lanczos, 

29 kernel_linear, 

30 kernel_nearest_neighbour, 

31 kernel_sinc, 

32 lagrange_coefficients, 

33 random_triplet_generator, 

34 table_interpolation, 

35 table_interpolation_tetrahedral, 

36 table_interpolation_trilinear, 

37) 

38from colour.constants import TOLERANCE_ABSOLUTE_TESTS 

39from colour.hints import NDArrayFloat, cast 

40from colour.io import LUT3D, read_LUT 

41from colour.utilities import ignore_numpy_errors, is_scipy_installed 

42 

43__author__ = "Colour Developers" 

44__copyright__ = "Copyright 2013 Colour Developers" 

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

46__maintainer__ = "Colour Developers" 

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

48__status__ = "Production" 

49 

50__all__ = [ 

51 "DATA_POINTS_A", 

52 "DATA_POINTS_A_LINEAR_INTERPOLATED_10_SAMPLES", 

53 "DATA_POINTS_A_SPRAGUE_INTERPOLATED_10_SAMPLES", 

54 "DATA_POINTS_A_CUBIC_SPLINE_INTERPOLATED_X2_SAMPLES", 

55 "LAGRANGE_COEFFICIENTS_A", 

56 "LAGRANGE_COEFFICIENTS_B", 

57 "LUT_TABLE", 

58 "TestKernelNearestNeighbour", 

59 "TestKernelLinear", 

60 "TestKernelSinc", 

61 "TestKernelLanczos", 

62 "TestKernelCardinalSpline", 

63 "TestKernelInterpolator", 

64 "TestLinearInterpolator", 

65 "TestSpragueInterpolator", 

66 "TestCubicSplineInterpolator", 

67 "TestPchipInterpolator", 

68 "TestNullInterpolator", 

69 "TestLagrangeCoefficients", 

70 "TestTableInterpolationTrilinear", 

71 "TestTableInterpolationTetrahedral", 

72] 

73 

74DATA_POINTS_A: tuple = ( 

75 9.3700, 

76 12.3200, 

77 12.4600, 

78 9.5100, 

79 5.9200, 

80 4.3300, 

81 4.2900, 

82 3.8800, 

83 4.5100, 

84 10.9200, 

85 27.5000, 

86 49.6700, 

87 69.5900, 

88 81.7300, 

89 88.1900, 

90 86.0500, 

91) 

92 

93DATA_POINTS_A_LINEAR_INTERPOLATED_10_SAMPLES: tuple = ( 

94 9.370, 

95 9.665, 

96 9.960, 

97 10.255, 

98 10.550, 

99 10.845, 

100 11.140, 

101 11.435, 

102 11.730, 

103 12.025, 

104 12.320, 

105 12.334, 

106 12.348, 

107 12.362, 

108 12.376, 

109 12.390, 

110 12.404, 

111 12.418, 

112 12.432, 

113 12.446, 

114 12.460, 

115 12.165, 

116 11.870, 

117 11.575, 

118 11.280, 

119 10.985, 

120 10.690, 

121 10.395, 

122 10.100, 

123 9.805, 

124 9.510, 

125 9.151, 

126 8.792, 

127 8.433, 

128 8.074, 

129 7.715, 

130 7.356, 

131 6.997, 

132 6.638, 

133 6.279, 

134 5.920, 

135 5.761, 

136 5.602, 

137 5.443, 

138 5.284, 

139 5.125, 

140 4.966, 

141 4.807, 

142 4.648, 

143 4.489, 

144 4.330, 

145 4.326, 

146 4.322, 

147 4.318, 

148 4.314, 

149 4.310, 

150 4.306, 

151 4.302, 

152 4.298, 

153 4.294, 

154 4.290, 

155 4.249, 

156 4.208, 

157 4.167, 

158 4.126, 

159 4.085, 

160 4.044, 

161 4.003, 

162 3.962, 

163 3.921, 

164 3.880, 

165 3.943, 

166 4.006, 

167 4.069, 

168 4.132, 

169 4.195, 

170 4.258, 

171 4.321, 

172 4.384, 

173 4.447, 

174 4.510, 

175 5.151, 

176 5.792, 

177 6.433, 

178 7.074, 

179 7.715, 

180 8.356, 

181 8.997, 

182 9.638, 

183 10.279, 

184 10.920, 

185 12.578, 

186 14.236, 

187 15.894, 

188 17.552, 

189 19.210, 

190 20.868, 

191 22.526, 

192 24.184, 

193 25.842, 

194 27.500, 

195 29.717, 

196 31.934, 

197 34.151, 

198 36.368, 

199 38.585, 

200 40.802, 

201 43.019, 

202 45.236, 

203 47.453, 

204 49.670, 

205 51.662, 

206 53.654, 

207 55.646, 

208 57.638, 

209 59.630, 

210 61.622, 

211 63.614, 

212 65.606, 

213 67.598, 

214 69.590, 

215 70.804, 

216 72.018, 

217 73.232, 

218 74.446, 

219 75.660, 

220 76.874, 

221 78.088, 

222 79.302, 

223 80.516, 

224 81.730, 

225 82.376, 

226 83.022, 

227 83.668, 

228 84.314, 

229 84.960, 

230 85.606, 

231 86.252, 

232 86.898, 

233 87.544, 

234 88.190, 

235 87.976, 

236 87.762, 

237 87.548, 

238 87.334, 

239 87.120, 

240 86.906, 

241 86.692, 

242 86.478, 

243 86.264, 

244 86.050, 

245) 

246 

247DATA_POINTS_A_SPRAGUE_INTERPOLATED_10_SAMPLES: tuple = ( 

248 9.37000000, 

249 9.72075073, 

250 10.06936191, 

251 10.41147570, 

252 10.74302270, 

253 11.06022653, 

254 11.35960827, 

255 11.63799100, 

256 11.89250427, 

257 12.12058860, 

258 12.32000000, 

259 12.48873542, 

260 12.62489669, 

261 12.72706530, 

262 12.79433478, 

263 12.82623598, 

264 12.82266243, 

265 12.78379557, 

266 12.71003009, 

267 12.60189921, 

268 12.46000000, 

269 12.28440225, 

270 12.07404800, 

271 11.82976500, 

272 11.55443200, 

273 11.25234375, 

274 10.92857600, 

275 10.58835050, 

276 10.23640000, 

277 9.87633325, 

278 9.51000000, 

279 9.13692962, 

280 8.75620800, 

281 8.36954763, 

282 7.98097600, 

283 7.59601562, 

284 7.22086400, 

285 6.86157362, 

286 6.52323200, 

287 6.20914162, 

288 5.92000000, 

289 5.65460200, 

290 5.41449600, 

291 5.20073875, 

292 5.01294400, 

293 4.84968750, 

294 4.70891200, 

295 4.58833225, 

296 4.48584000, 

297 4.39990900, 

298 4.33000000, 

299 4.27757887, 

300 4.24595200, 

301 4.23497388, 

302 4.24099200, 

303 4.25804688, 

304 4.27907200, 

305 4.29709387, 

306 4.30643200, 

307 4.30389887, 

308 4.29000000, 

309 4.26848387, 

310 4.24043200, 

311 4.20608887, 

312 4.16603200, 

313 4.12117188, 

314 4.07275200, 

315 4.02234887, 

316 3.97187200, 

317 3.92356387, 

318 3.88000000, 

319 3.84319188, 

320 3.81318400, 

321 3.79258487, 

322 3.78691200, 

323 3.80367187, 

324 3.85144000, 

325 3.93894087, 

326 4.07412800, 

327 4.26326387, 

328 4.51000000, 

329 4.81362075, 

330 5.17028800, 

331 5.58225150, 

332 6.05776000, 

333 6.60890625, 

334 7.24947200, 

335 7.99277300, 

336 8.84950400, 

337 9.82558375, 

338 10.92000000, 

339 12.12700944, 

340 13.44892800, 

341 14.88581406, 

342 16.43283200, 

343 18.08167969, 

344 19.82201600, 

345 21.64288831, 

346 23.53416000, 

347 25.48793794, 

348 27.50000000, 

349 29.57061744, 

350 31.69964800, 

351 33.88185481, 

352 36.10777600, 

353 38.36511719, 

354 40.64014400, 

355 42.91907456, 

356 45.18947200, 

357 47.44163694, 

358 49.67000000, 

359 51.87389638, 

360 54.05273600, 

361 56.20157688, 

362 58.31198400, 

363 60.37335938, 

364 62.37427200, 

365 64.30378787, 

366 66.15280000, 

367 67.91535838, 

368 69.59000000, 

369 71.17616669, 

370 72.66283200, 

371 74.04610481, 

372 75.33171200, 

373 76.53183594, 

374 77.66195200, 

375 78.73766606, 

376 79.77155200, 

377 80.76998919, 

378 81.73000000, 

379 82.64375688, 

380 83.51935227, 

381 84.35919976, 

382 85.15567334, 

383 85.89451368, 

384 86.55823441, 

385 87.12952842, 

386 87.59467414, 

387 87.94694187, 

388 88.19000000, 

389 88.33345751, 

390 88.37111372, 

391 88.30221714, 

392 88.13600972, 

393 87.88846516, 

394 87.57902706, 

395 87.22734720, 

396 86.85002373, 

397 86.45733945, 

398 86.05000000, 

399) 

400 

401DATA_POINTS_A_CUBIC_SPLINE_INTERPOLATED_X2_SAMPLES: tuple = ( 

402 9.37000000, 

403 11.08838189, 

404 12.26359953, 

405 12.78808025, 

406 12.55425139, 

407 11.50391691, 

408 9.87473603, 

409 8.01707329, 

410 6.30369624, 

411 5.08664365, 

412 4.43550284, 

413 4.25438019, 

414 4.29206798, 

415 4.21753374, 

416 3.98875865, 

417 3.79691327, 

418 4.02534907, 

419 5.23223510, 

420 8.08816250, 

421 13.36306794, 

422 21.19519815, 

423 30.89350026, 

424 41.64531611, 

425 52.53540869, 

426 62.65180882, 

427 71.10713687, 

428 77.46889540, 

429 82.31355134, 

430 86.05208477, 

431 88.28078752, 

432 88.45998434, 

433 86.05000000, 

434) 

435 

436LAGRANGE_COEFFICIENTS_A: NDArrayFloat = np.array( 

437 [ 

438 [0.92625, 0.09750, -0.02375], 

439 [0.85500, 0.19000, -0.04500], 

440 [0.78625, 0.27750, -0.06375], 

441 [0.72000, 0.36000, -0.08000], 

442 [0.65625, 0.43750, -0.09375], 

443 [0.59500, 0.51000, -0.10500], 

444 [0.53625, 0.57750, -0.11375], 

445 [0.48000, 0.64000, -0.12000], 

446 [0.42625, 0.69750, -0.12375], 

447 [0.37500, 0.75000, -0.12500], 

448 [0.32625, 0.79750, -0.12375], 

449 [0.28000, 0.84000, -0.12000], 

450 [0.23625, 0.87750, -0.11375], 

451 [0.19500, 0.91000, -0.10500], 

452 [0.15625, 0.93750, -0.09375], 

453 [0.12000, 0.96000, -0.08000], 

454 [0.08625, 0.97750, -0.06375], 

455 [0.05500, 0.99000, -0.04500], 

456 [0.02625, 0.99750, -0.02375], 

457 ] 

458) 

459 

460LAGRANGE_COEFFICIENTS_B: NDArrayFloat = np.array( 

461 [ 

462 [-0.0154375, 0.9725625, 0.0511875, -0.0083125], 

463 [-0.0285000, 0.9405000, 0.1045000, -0.0165000], 

464 [-0.0393125, 0.9041875, 0.1595625, -0.0244375], 

465 [-0.0480000, 0.8640000, 0.2160000, -0.0320000], 

466 [-0.0546875, 0.8203125, 0.2734375, -0.0390625], 

467 [-0.0595000, 0.7735000, 0.3315000, -0.0455000], 

468 [-0.0625625, 0.7239375, 0.3898125, -0.0511875], 

469 [-0.0640000, 0.6720000, 0.4480000, -0.0560000], 

470 [-0.0639375, 0.6180625, 0.5056875, -0.0598125], 

471 [-0.0625000, 0.5625000, 0.5625000, -0.0625000], 

472 [-0.0598125, 0.5056875, 0.6180625, -0.0639375], 

473 [-0.0560000, 0.4480000, 0.6720000, -0.0640000], 

474 [-0.0511875, 0.3898125, 0.7239375, -0.0625625], 

475 [-0.0455000, 0.3315000, 0.7735000, -0.0595000], 

476 [-0.0390625, 0.2734375, 0.8203125, -0.0546875], 

477 [-0.0320000, 0.2160000, 0.8640000, -0.0480000], 

478 [-0.0244375, 0.1595625, 0.9041875, -0.0393125], 

479 [-0.0165000, 0.1045000, 0.9405000, -0.0285000], 

480 [-0.0083125, 0.0511875, 0.9725625, -0.0154375], 

481 ] 

482) 

483 

484LUT_TABLE: NDArrayFloat = cast( 

485 "LUT3D", 

486 read_LUT( 

487 os.path.join( 

488 os.path.dirname(__file__), 

489 "..", 

490 "..", 

491 "io", 

492 "luts", 

493 "tests", 

494 "resources", 

495 "iridas_cube", 

496 "Colour_Correct.cube", 

497 ) 

498 ), 

499).table 

500 

501 

502class TestKernelNearestNeighbour: 

503 """ 

504 Define :func:`colour.algebra.interpolation.kernel_nearest_neighbour` 

505 definition unit tests methods. 

506 """ 

507 

508 def test_kernel_nearest(self) -> None: 

509 """ 

510 Test :func:`colour.algebra.interpolation.kernel_nearest_neighbour` 

511 definition. 

512 """ 

513 

514 np.testing.assert_allclose( 

515 kernel_nearest_neighbour(np.linspace(-5, 5, 25)), 

516 np.array( 

517 [ 

518 0, 

519 0, 

520 0, 

521 0, 

522 0, 

523 0, 

524 0, 

525 0, 

526 0, 

527 0, 

528 0, 

529 1, 

530 1, 

531 1, 

532 0, 

533 0, 

534 0, 

535 0, 

536 0, 

537 0, 

538 0, 

539 0, 

540 0, 

541 0, 

542 0, 

543 ] 

544 ), 

545 atol=TOLERANCE_ABSOLUTE_TESTS, 

546 ) 

547 

548 

549class TestKernelLinear: 

550 """ 

551 Define :func:`colour.algebra.interpolation.kernel_linear` definition 

552 unit tests methods. 

553 """ 

554 

555 def test_kernel_linear(self) -> None: 

556 """Test :func:`colour.algebra.interpolation.kernel_linear` definition.""" 

557 

558 np.testing.assert_allclose( 

559 kernel_linear(np.linspace(-5, 5, 25)), 

560 np.array( 

561 [ 

562 0.00000000, 

563 0.00000000, 

564 0.00000000, 

565 0.00000000, 

566 0.00000000, 

567 0.00000000, 

568 0.00000000, 

569 0.00000000, 

570 0.00000000, 

571 0.00000000, 

572 0.16666667, 

573 0.58333333, 

574 1.00000000, 

575 0.58333333, 

576 0.16666667, 

577 0.00000000, 

578 0.00000000, 

579 0.00000000, 

580 0.00000000, 

581 0.00000000, 

582 0.00000000, 

583 0.00000000, 

584 0.00000000, 

585 0.00000000, 

586 0.00000000, 

587 ] 

588 ), 

589 atol=TOLERANCE_ABSOLUTE_TESTS, 

590 ) 

591 

592 

593class TestKernelSinc: 

594 """ 

595 Define :func:`colour.algebra.interpolation.kernel_sinc` definition 

596 unit tests methods. 

597 """ 

598 

599 def test_kernel_sinc(self) -> None: 

600 """Test :func:`colour.algebra.interpolation.kernel_sinc` definition.""" 

601 

602 np.testing.assert_allclose( 

603 kernel_sinc(np.linspace(-5, 5, 25)), 

604 np.array( 

605 [ 

606 0.00000000, 

607 0.00000000, 

608 0.00000000, 

609 0.00000000, 

610 0.00000000, 

611 0.02824617, 

612 0.12732395, 

613 0.03954464, 

614 -0.16539867, 

615 -0.18006326, 

616 0.19098593, 

617 0.73791298, 

618 1.00000000, 

619 0.73791298, 

620 0.19098593, 

621 -0.18006326, 

622 -0.16539867, 

623 0.03954464, 

624 0.12732395, 

625 0.02824617, 

626 0.00000000, 

627 0.00000000, 

628 0.00000000, 

629 0.00000000, 

630 0.00000000, 

631 ] 

632 ), 

633 atol=TOLERANCE_ABSOLUTE_TESTS, 

634 ) 

635 

636 np.testing.assert_allclose( 

637 kernel_sinc(np.linspace(-5, 5, 25), 1), 

638 np.array( 

639 [ 

640 0.00000000, 

641 0.00000000, 

642 0.00000000, 

643 0.00000000, 

644 0.00000000, 

645 0.00000000, 

646 0.00000000, 

647 0.00000000, 

648 0.00000000, 

649 0.00000000, 

650 0.19098593, 

651 0.73791298, 

652 1.00000000, 

653 0.73791298, 

654 0.19098593, 

655 0.00000000, 

656 0.00000000, 

657 0.00000000, 

658 0.00000000, 

659 0.00000000, 

660 0.00000000, 

661 0.00000000, 

662 0.00000000, 

663 0.00000000, 

664 0.00000000, 

665 ] 

666 ), 

667 atol=TOLERANCE_ABSOLUTE_TESTS, 

668 ) 

669 

670 

671class TestKernelLanczos: 

672 """ 

673 Define :func:`colour.algebra.interpolation.kernel_lanczos` definition 

674 unit tests methods. 

675 """ 

676 

677 def test_kernel_lanczos(self) -> None: 

678 """Test :func:`colour.algebra.interpolation.kernel_lanczos` definition.""" 

679 

680 np.testing.assert_allclose( 

681 kernel_lanczos(np.linspace(-5, 5, 25)), 

682 np.array( 

683 [ 

684 0.00000000e00, 

685 0.00000000e00, 

686 0.00000000e00, 

687 0.00000000e00, 

688 0.00000000e00, 

689 8.06009483e-04, 

690 2.43170841e-02, 

691 1.48478897e-02, 

692 -9.33267411e-02, 

693 -1.32871018e-01, 

694 1.67651704e-01, 

695 7.14720157e-01, 

696 1.00000000e00, 

697 7.14720157e-01, 

698 1.67651704e-01, 

699 -1.32871018e-01, 

700 -9.33267411e-02, 

701 1.48478897e-02, 

702 2.43170841e-02, 

703 8.06009483e-04, 

704 0.00000000e00, 

705 0.00000000e00, 

706 0.00000000e00, 

707 0.00000000e00, 

708 0.00000000e00, 

709 ] 

710 ), 

711 atol=TOLERANCE_ABSOLUTE_TESTS, 

712 ) 

713 

714 np.testing.assert_allclose( 

715 kernel_lanczos(np.linspace(-5, 5, 25), 1), 

716 np.array( 

717 [ 

718 0.00000000, 

719 0.00000000, 

720 0.00000000, 

721 0.00000000, 

722 0.00000000, 

723 0.00000000, 

724 0.00000000, 

725 0.00000000, 

726 0.00000000, 

727 0.00000000, 

728 0.03647563, 

729 0.54451556, 

730 1.00000000, 

731 0.54451556, 

732 0.03647563, 

733 0.00000000, 

734 0.00000000, 

735 0.00000000, 

736 0.00000000, 

737 0.00000000, 

738 0.00000000, 

739 0.00000000, 

740 0.00000000, 

741 0.00000000, 

742 0.00000000, 

743 ] 

744 ), 

745 atol=TOLERANCE_ABSOLUTE_TESTS, 

746 ) 

747 

748 

749class TestKernelCardinalSpline: 

750 """ 

751 Define :func:`colour.algebra.interpolation.kernel_cardinal_spline` 

752 definition unit tests methods. 

753 """ 

754 

755 def test_kernel_cardinal_spline(self) -> None: 

756 """ 

757 Test :func:`colour.algebra.interpolation.kernel_cardinal_spline` 

758 definition. 

759 """ 

760 

761 np.testing.assert_allclose( 

762 kernel_cardinal_spline(np.linspace(-5, 5, 25)), 

763 np.array( 

764 [ 

765 0.00000000, 

766 0.00000000, 

767 0.00000000, 

768 0.00000000, 

769 0.00000000, 

770 0.00000000, 

771 0.00000000, 

772 0.00000000, 

773 -0.03703704, 

774 -0.0703125, 

775 0.13194444, 

776 0.67447917, 

777 1.00000000, 

778 0.67447917, 

779 0.13194444, 

780 -0.0703125, 

781 -0.03703704, 

782 0.00000000, 

783 0.00000000, 

784 0.00000000, 

785 0.00000000, 

786 0.00000000, 

787 0.00000000, 

788 0.00000000, 

789 0.00000000, 

790 ] 

791 ), 

792 atol=TOLERANCE_ABSOLUTE_TESTS, 

793 ) 

794 

795 np.testing.assert_allclose( 

796 kernel_cardinal_spline(np.linspace(-5, 5, 25), 0, 1), 

797 np.array( 

798 [ 

799 0.00000000, 

800 0.00000000, 

801 0.00000000, 

802 0.00000000, 

803 0.00000000, 

804 0.00000000, 

805 0.00000000, 

806 0.00000000, 

807 0.00617284, 

808 0.0703125, 

809 0.26157407, 

810 0.52922454, 

811 0.66666667, 

812 0.52922454, 

813 0.26157407, 

814 0.0703125, 

815 0.00617284, 

816 0.00000000, 

817 0.00000000, 

818 0.00000000, 

819 0.00000000, 

820 0.00000000, 

821 0.00000000, 

822 0.00000000, 

823 0.00000000, 

824 ] 

825 ), 

826 atol=TOLERANCE_ABSOLUTE_TESTS, 

827 ) 

828 

829 

830class TestKernelInterpolator: 

831 """ 

832 Define :class:`colour.algebra.interpolation.KernelInterpolator` class unit 

833 tests methods. 

834 """ 

835 

836 def test_required_attributes(self) -> None: 

837 """Test the presence of required attributes.""" 

838 

839 if not is_scipy_installed(): # pragma: no cover 

840 return 

841 

842 required_attributes = ( 

843 "x", 

844 "y", 

845 "window", 

846 "kernel", 

847 "kernel_kwargs", 

848 "padding_kwargs", 

849 ) 

850 

851 for attribute in required_attributes: 

852 assert attribute in dir(KernelInterpolator) 

853 

854 def test_required_methods(self) -> None: 

855 """Test the presence of required methods.""" 

856 

857 required_methods = ("__init__", "__call__") 

858 

859 for method in required_methods: # pragma: no cover 

860 assert method in dir(KernelInterpolator) 

861 

862 def test_x(self) -> None: 

863 """ 

864 Test :attr:`colour.algebra.interpolation.KernelInterpolator.x` 

865 property. 

866 """ 

867 

868 x = y = np.linspace(0, 1, 10) 

869 kernel_interpolator = KernelInterpolator(x, y) 

870 

871 np.testing.assert_equal(kernel_interpolator.x, x) 

872 

873 def test_y(self) -> None: 

874 """ 

875 Test :attr:`colour.algebra.interpolation.KernelInterpolator.y` 

876 property. 

877 """ 

878 

879 if not is_scipy_installed(): # pragma: no cover 

880 return 

881 

882 x = y = np.linspace(0, 1, 10) 

883 kernel_interpolator = KernelInterpolator(x, y) 

884 

885 np.testing.assert_equal(kernel_interpolator.y, y) 

886 

887 def test_window(self) -> None: 

888 """ 

889 Test :attr:`colour.algebra.interpolation.KernelInterpolator.window` 

890 property. 

891 """ 

892 

893 x = y = np.linspace(0, 1, 10) 

894 kernel_interpolator = KernelInterpolator(x, y, window=3) 

895 

896 assert kernel_interpolator.window == 3 

897 

898 def test_kernel(self) -> None: 

899 """ 

900 Test :attr:`colour.algebra.interpolation.KernelInterpolator.kernel` 

901 property. 

902 """ 

903 

904 x = y = np.linspace(0, 1, 10) 

905 kernel_interpolator = KernelInterpolator(x, y, kernel=kernel_linear) 

906 

907 assert kernel_interpolator.kernel is kernel_linear 

908 

909 def test_kernel_kwargs(self) -> None: 

910 """ 

911 Test :attr:`colour.algebra.interpolation.KernelInterpolator.\ 

912kernel_kwargs` property. 

913 """ 

914 

915 x = y = np.linspace(0, 1, 10) 

916 kernel_kwargs = {"a": 1} 

917 kernel_interpolator = KernelInterpolator(x, y, kernel_kwargs=kernel_kwargs) 

918 

919 assert kernel_interpolator.kernel_kwargs == kernel_kwargs 

920 

921 def test_padding_kwargs(self) -> None: 

922 """ 

923 Test :attr:`colour.algebra.interpolation.KernelInterpolator.\ 

924padding_kwargs` property. 

925 """ 

926 

927 x = y = np.linspace(0, 1, 10) 

928 padding_kwargs = {"pad_width": (3, 3), "mode": "mean"} 

929 kernel_interpolator = KernelInterpolator(x, y, padding_kwargs=padding_kwargs) 

930 

931 assert kernel_interpolator.padding_kwargs == padding_kwargs 

932 

933 def test_raise_exception___init__(self) -> None: 

934 """ 

935 Test :meth:`colour.algebra.interpolation.KernelInterpolator.__init__` 

936 method raised exception. 

937 """ 

938 

939 pytest.raises( 

940 ValueError, 

941 KernelInterpolator, 

942 np.linspace(0, 1, 10), 

943 np.linspace(0, 1, 15), 

944 ) 

945 

946 def test__call__(self) -> None: 

947 """ 

948 Test :meth:`colour.algebra.interpolation.KernelInterpolator.__call__` 

949 method. 

950 """ 

951 

952 if not is_scipy_installed(): # pragma: no cover 

953 return 

954 

955 x = np.arange(11, 26, 1) 

956 y = np.sin(x / len(x) * np.pi * 6) / (x / len(x)) + np.pi 

957 x_i = np.linspace(11, 25, 25) 

958 

959 kernel_interpolator = KernelInterpolator(x, y) 

960 np.testing.assert_allclose( 

961 kernel_interpolator(x_i), 

962 np.array( 

963 [ 

964 4.43848790, 

965 4.26286480, 

966 3.64640076, 

967 2.77982023, 

968 2.13474499, 

969 2.08206794, 

970 2.50585862, 

971 3.24992692, 

972 3.84593162, 

973 4.06289704, 

974 3.80825633, 

975 3.21068994, 

976 2.65177161, 

977 2.32137382, 

978 2.45995375, 

979 2.88799997, 

980 3.43843598, 

981 3.79504892, 

982 3.79937086, 

983 3.47673343, 

984 2.99303182, 

985 2.59305006, 

986 2.47805594, 

987 2.82957843, 

988 3.14159265, 

989 ] 

990 ), 

991 atol=TOLERANCE_ABSOLUTE_TESTS, 

992 ) 

993 

994 kernel_interpolator = KernelInterpolator(x, y, kernel=kernel_sinc) 

995 np.testing.assert_allclose( 

996 kernel_interpolator(x_i), 

997 np.array( 

998 [ 

999 4.43848790, 

1000 4.47570010, 

1001 3.84353906, 

1002 3.05959493, 

1003 2.53514958, 

1004 2.19916874, 

1005 2.93225625, 

1006 3.32187855, 

1007 4.09458791, 

1008 4.23088094, 

1009 3.92591447, 

1010 3.53263071, 

1011 2.65177161, 

1012 2.73541557, 

1013 2.65740315, 

1014 3.17077616, 

1015 3.69624479, 

1016 3.87159620, 

1017 4.06433758, 

1018 3.56283868, 

1019 3.28312289, 

1020 2.79652091, 

1021 2.62481419, 

1022 3.22117115, 

1023 3.14159265, 

1024 ] 

1025 ), 

1026 atol=TOLERANCE_ABSOLUTE_TESTS, 

1027 ) 

1028 

1029 kernel_interpolator = KernelInterpolator(x, y, window=1) 

1030 np.testing.assert_allclose( 

1031 kernel_interpolator(x_i), 

1032 np.array( 

1033 [ 

1034 4.43848790, 

1035 4.96712277, 

1036 4.09584229, 

1037 3.23991575, 

1038 2.80418924, 

1039 2.28470276, 

1040 3.20024753, 

1041 3.41120944, 

1042 4.46416970, 

1043 4.57878168, 

1044 4.15371498, 

1045 3.92841633, 

1046 2.65177161, 

1047 3.02110187, 

1048 2.79812654, 

1049 3.44218674, 

1050 4.00032377, 

1051 4.01356870, 

1052 4.47633386, 

1053 3.70912627, 

1054 3.58365067, 

1055 3.14325415, 

1056 2.88247572, 

1057 3.37531662, 

1058 3.14159265, 

1059 ] 

1060 ), 

1061 atol=TOLERANCE_ABSOLUTE_TESTS, 

1062 ) 

1063 

1064 kernel_interpolator = KernelInterpolator(x, y, window=1, kernel_kwargs={"a": 1}) 

1065 np.testing.assert_allclose( 

1066 kernel_interpolator(x_i), 

1067 np.array( 

1068 [ 

1069 4.43848790, 

1070 3.34379320, 

1071 3.62463711, 

1072 2.34585418, 

1073 2.04767083, 

1074 2.09444849, 

1075 2.13349835, 

1076 3.10304927, 

1077 3.29553153, 

1078 3.59884738, 

1079 3.48484031, 

1080 2.72974983, 

1081 2.65177161, 

1082 2.03850468, 

1083 2.29470194, 

1084 2.76179863, 

1085 2.80189050, 

1086 3.75979450, 

1087 2.98422257, 

1088 3.48444099, 

1089 2.49208997, 

1090 2.46516442, 

1091 2.42336082, 

1092 2.25975903, 

1093 3.14159265, 

1094 ] 

1095 ), 

1096 atol=TOLERANCE_ABSOLUTE_TESTS, 

1097 ) 

1098 

1099 kernel_interpolator = KernelInterpolator( 

1100 x, y, padding_kwargs={"pad_width": (3, 3), "mode": "mean"} 

1101 ) 

1102 np.testing.assert_allclose( 

1103 kernel_interpolator(x_i), 

1104 np.array( 

1105 [ 

1106 4.4384879, 

1107 4.35723245, 

1108 3.62918155, 

1109 2.77471295, 

1110 2.13474499, 

1111 2.08206794, 

1112 2.50585862, 

1113 3.24992692, 

1114 3.84593162, 

1115 4.06289704, 

1116 3.80825633, 

1117 3.21068994, 

1118 2.65177161, 

1119 2.32137382, 

1120 2.45995375, 

1121 2.88799997, 

1122 3.43843598, 

1123 3.79504892, 

1124 3.79937086, 

1125 3.47673343, 

1126 2.99303182, 

1127 2.59771985, 

1128 2.49380017, 

1129 2.76339043, 

1130 3.14159265, 

1131 ] 

1132 ), 

1133 atol=TOLERANCE_ABSOLUTE_TESTS, 

1134 ) 

1135 

1136 x_1 = np.arange(1, 10, 1) 

1137 x_2 = x_1 * 10 

1138 x_3 = x_1 / 10 

1139 y = np.sin(x_1 / len(x_1) * np.pi * 6) / (x_1 / len(x_1)) 

1140 x_i = np.linspace(1, 9, 25) 

1141 

1142 np.testing.assert_allclose( 

1143 KernelInterpolator(x_1, y)(x_i), 

1144 KernelInterpolator(x_2, y)(x_i * 10), 

1145 atol=TOLERANCE_ABSOLUTE_TESTS, 

1146 ) 

1147 

1148 np.testing.assert_allclose( 

1149 KernelInterpolator(x_1, y)(x_i), 

1150 KernelInterpolator(x_3, y)(x_i / 10), 

1151 atol=TOLERANCE_ABSOLUTE_TESTS, 

1152 ) 

1153 

1154 def test_raise_exception___call__(self) -> None: 

1155 """ 

1156 Test :meth:`colour.algebra.interpolation.KernelInterpolator.__call__` 

1157 method raised exception. 

1158 """ 

1159 

1160 x = y = np.linspace(0, 1, 10) 

1161 kernel_interpolator = KernelInterpolator(x, y) 

1162 

1163 pytest.raises(ValueError, kernel_interpolator, -1) 

1164 

1165 pytest.raises(ValueError, kernel_interpolator, 11) 

1166 

1167 @ignore_numpy_errors 

1168 def test_nan__call__(self) -> None: 

1169 """ 

1170 Test :meth:`colour.algebra.interpolation.KernelInterpolator.__call__` 

1171 method nan support. 

1172 """ 

1173 

1174 # NOTE: As the "x" independent variable must be uniform, it cannot 

1175 # contain NaNs. 

1176 # TODO: Revisit if the interpolator can be applied on non-uniform "x" 

1177 # independent variable. 

1178 

1179 

1180class TestNearestNeighbourInterpolator: 

1181 """ 

1182 Define :class:`colour.algebra.interpolation.NearestNeighbourInterpolator` 

1183 class unit tests methods. 

1184 """ 

1185 

1186 def test_required_attributes(self) -> None: 

1187 """Test the presence of required attributes.""" 

1188 

1189 if not is_scipy_installed(): # pragma: no cover 

1190 return 

1191 

1192 required_attributes = () 

1193 

1194 for attribute in required_attributes: # pragma: no cover 

1195 assert attribute in dir(NearestNeighbourInterpolator) 

1196 

1197 def test_required_methods(self) -> None: 

1198 """Test the presence of required methods.""" 

1199 

1200 required_methods = ("__init__",) 

1201 

1202 for method in required_methods: # pragma: no cover 

1203 assert method in dir(NearestNeighbourInterpolator) 

1204 

1205 def test___init__(self) -> None: 

1206 """ 

1207 Test :meth:`colour.algebra.interpolation.KernelInterpolator.__init__` 

1208 method. 

1209 """ 

1210 

1211 x = y = np.linspace(0, 1, 10) 

1212 nearest_neighbour_interpolator = NearestNeighbourInterpolator( 

1213 x, y, kernel_kwargs={"a": 1} 

1214 ) 

1215 

1216 assert nearest_neighbour_interpolator.kernel_kwargs == {} 

1217 

1218 

1219class TestLinearInterpolator: 

1220 """ 

1221 Define :class:`colour.algebra.interpolation.LinearInterpolator` class unit 

1222 tests methods. 

1223 """ 

1224 

1225 def test_required_attributes(self) -> None: 

1226 """Test the presence of required attributes.""" 

1227 

1228 if not is_scipy_installed(): # pragma: no cover 

1229 return 

1230 

1231 required_attributes = ("x", "y") 

1232 

1233 for attribute in required_attributes: 

1234 assert attribute in dir(LinearInterpolator) 

1235 

1236 def test_required_methods(self) -> None: 

1237 """Test the presence of required methods.""" 

1238 

1239 required_methods = ("__init__", "__call__") 

1240 

1241 for method in required_methods: # pragma: no cover 

1242 assert method in dir(LinearInterpolator) 

1243 

1244 def test_raise_exception___init__(self) -> None: 

1245 """ 

1246 Test :meth:`colour.algebra.interpolation.LinearInterpolator.__init__` 

1247 method raised exception. 

1248 """ 

1249 

1250 x, y = np.linspace(0, 1, 10), np.linspace(0, 1, 15) 

1251 pytest.raises(ValueError, LinearInterpolator, x, y) 

1252 

1253 def test__call__(self) -> None: 

1254 """ 

1255 Test :meth:`colour.algebra.interpolation.LinearInterpolator.__call__` 

1256 method. 

1257 """ 

1258 

1259 if not is_scipy_installed(): # pragma: no cover 

1260 return 

1261 

1262 interval = 0.1 

1263 x = np.arange(len(DATA_POINTS_A)) 

1264 linear_interpolator = LinearInterpolator(x, DATA_POINTS_A) 

1265 

1266 for i, value in enumerate( 

1267 np.arange(0, len(DATA_POINTS_A) - 1 + interval, interval) 

1268 ): 

1269 np.testing.assert_allclose( 

1270 DATA_POINTS_A_LINEAR_INTERPOLATED_10_SAMPLES[i], 

1271 linear_interpolator(value), 

1272 atol=TOLERANCE_ABSOLUTE_TESTS, 

1273 ) 

1274 

1275 np.testing.assert_allclose( 

1276 linear_interpolator( 

1277 np.arange(0, len(DATA_POINTS_A) - 1 + interval, interval) 

1278 ), 

1279 DATA_POINTS_A_LINEAR_INTERPOLATED_10_SAMPLES, 

1280 atol=TOLERANCE_ABSOLUTE_TESTS, 

1281 ) 

1282 

1283 def test_raise_exception___call__(self) -> None: 

1284 """ 

1285 Test :meth:`colour.algebra.interpolation.LinearInterpolator.__call__` 

1286 method raised exception. 

1287 """ 

1288 

1289 x = y = np.linspace(0, 1, 10) 

1290 linear_interpolator = LinearInterpolator(x, y) 

1291 

1292 pytest.raises(ValueError, linear_interpolator, -1) 

1293 

1294 pytest.raises(ValueError, linear_interpolator, 11) 

1295 

1296 @ignore_numpy_errors 

1297 def test_nan__call__(self) -> None: 

1298 """ 

1299 Test :meth:`colour.algebra.interpolation.LinearInterpolator.__call__` 

1300 method nan support. 

1301 """ 

1302 

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

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

1305 for case in cases: 

1306 try: 

1307 linear_interpolator = LinearInterpolator(case, case) 

1308 linear_interpolator(case[0]) 

1309 except ValueError: # noqa: PERF203 

1310 pass 

1311 

1312 

1313class TestSpragueInterpolator: 

1314 """ 

1315 Define :class:`colour.algebra.interpolation.SpragueInterpolator` class 

1316 unit tests methods. 

1317 """ 

1318 

1319 def test_required_attributes(self) -> None: 

1320 """Test the presence of required attributes.""" 

1321 

1322 if not is_scipy_installed(): # pragma: no cover 

1323 return 

1324 

1325 required_attributes = ("x", "y") 

1326 

1327 for attribute in required_attributes: 

1328 assert attribute in dir(SpragueInterpolator) 

1329 

1330 def test_required_methods(self) -> None: 

1331 """Test the presence of required methods.""" 

1332 

1333 required_methods = ("__init__", "__call__") 

1334 

1335 for method in required_methods: # pragma: no cover 

1336 assert method in dir(SpragueInterpolator) 

1337 

1338 def test_raise_exception___init__(self) -> None: 

1339 """ 

1340 Test :meth:`colour.algebra.interpolation.SpragueInterpolator.__init__` 

1341 method raised exception. 

1342 """ 

1343 

1344 x, y = np.linspace(0, 1, 10), np.linspace(0, 1, 15) 

1345 pytest.raises(ValueError, SpragueInterpolator, x, y) 

1346 

1347 def test__call__(self) -> None: 

1348 """ 

1349 Test :meth:`colour.algebra.interpolation.SpragueInterpolator.__call__` 

1350 method. 

1351 """ 

1352 

1353 if not is_scipy_installed(): # pragma: no cover 

1354 return 

1355 

1356 interval = 0.1 

1357 x = np.arange(len(DATA_POINTS_A)) 

1358 sprague_interpolator = SpragueInterpolator(x, DATA_POINTS_A) 

1359 

1360 for i, value in enumerate( 

1361 np.arange(0, len(DATA_POINTS_A) - 1 + interval, interval) 

1362 ): 

1363 np.testing.assert_allclose( 

1364 DATA_POINTS_A_SPRAGUE_INTERPOLATED_10_SAMPLES[i], 

1365 sprague_interpolator(value), 

1366 atol=TOLERANCE_ABSOLUTE_TESTS, 

1367 ) 

1368 

1369 np.testing.assert_allclose( 

1370 sprague_interpolator( 

1371 np.arange(0, len(DATA_POINTS_A) - 1 + interval, interval) 

1372 ), 

1373 DATA_POINTS_A_SPRAGUE_INTERPOLATED_10_SAMPLES, 

1374 atol=TOLERANCE_ABSOLUTE_TESTS, 

1375 ) 

1376 

1377 def test_raise_exception___call__(self) -> None: 

1378 """ 

1379 Test :meth:`colour.algebra.interpolation.SpragueInterpolator.__call__` 

1380 method raised exception. 

1381 """ 

1382 

1383 x = y = np.linspace(0, 1, 10) 

1384 sprague_interpolator = SpragueInterpolator(x, y) 

1385 

1386 pytest.raises(ValueError, sprague_interpolator, -1) 

1387 

1388 pytest.raises(ValueError, sprague_interpolator, 11) 

1389 

1390 @ignore_numpy_errors 

1391 def test_nan__call__(self) -> None: 

1392 """ 

1393 Test :meth:`colour.algebra.interpolation.SpragueInterpolator.__call__` 

1394 method nan support. 

1395 """ 

1396 

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

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

1399 for case in cases: 

1400 try: 

1401 sprague_interpolator = SpragueInterpolator(case, case) 

1402 sprague_interpolator(case[0]) # pragma: no cover 

1403 except AssertionError: # noqa: PERF203 

1404 pass 

1405 

1406 

1407class TestCubicSplineInterpolator: 

1408 """ 

1409 Define :class:`colour.algebra.interpolation.CubicSplineInterpolator` class 

1410 unit tests methods. 

1411 """ 

1412 

1413 def test__call__(self) -> None: 

1414 """ 

1415 Test :meth:`colour.algebra.interpolation.CubicSplineInterpolator.\ 

1416__call__` method. 

1417 

1418 Notes 

1419 ----- 

1420 - This class is a wrapper around *scipy.interpolate.interp1d* class 

1421 and is assumed to be unit tested thoroughly. 

1422 """ 

1423 

1424 if not is_scipy_installed(): # pragma: no cover 

1425 return 

1426 

1427 np.testing.assert_allclose( 

1428 CubicSplineInterpolator( 

1429 np.linspace(0, 1, len(DATA_POINTS_A)), DATA_POINTS_A 

1430 )(np.linspace(0, 1, len(DATA_POINTS_A) * 2)), 

1431 DATA_POINTS_A_CUBIC_SPLINE_INTERPOLATED_X2_SAMPLES, 

1432 atol=TOLERANCE_ABSOLUTE_TESTS, 

1433 ) 

1434 

1435 

1436class TestPchipInterpolator: 

1437 """ 

1438 Define :class:`colour.algebra.interpolation.PchipInterpolator` class 

1439 unit tests methods. 

1440 """ 

1441 

1442 def test_required_attributes(self) -> None: 

1443 """Test the presence of required attributes.""" 

1444 

1445 if not is_scipy_installed(): # pragma: no cover 

1446 return 

1447 

1448 required_attributes = ("x", "y") 

1449 

1450 for attribute in required_attributes: 

1451 assert attribute in dir(PchipInterpolator) 

1452 

1453 def test_required_methods(self) -> None: 

1454 """Test the presence of required methods.""" 

1455 

1456 required_methods = ("__init__",) 

1457 

1458 for method in required_methods: # pragma: no cover 

1459 assert method in dir(PchipInterpolator) 

1460 

1461 def test_y(self) -> None: 

1462 """ 

1463 Test :attr:`colour.algebra.interpolation.PchipInterpolator.y` property. 

1464 """ 

1465 

1466 if not is_scipy_installed(): # pragma: no cover 

1467 return 

1468 

1469 interpolator = PchipInterpolator(np.linspace(0, 1, 10), np.linspace(0, 1, 10)) 

1470 

1471 interpolator.y = np.linspace(0, 1, 10) 

1472 

1473 assert interpolator(np.array(5)) == 5 

1474 

1475 

1476class TestNullInterpolator: 

1477 """ 

1478 Define :class:`colour.algebra.interpolation.NullInterpolator` class 

1479 unit tests methods. 

1480 """ 

1481 

1482 def test_required_attributes(self) -> None: 

1483 """Test the presence of required attributes.""" 

1484 

1485 if not is_scipy_installed(): # pragma: no cover 

1486 return 

1487 

1488 required_attributes = ("x", "y") 

1489 

1490 for attribute in required_attributes: 

1491 assert attribute in dir(NullInterpolator) 

1492 

1493 def test_required_methods(self) -> None: 

1494 """Test the presence of required methods.""" 

1495 

1496 required_methods = ("__init__", "__call__") 

1497 

1498 for method in required_methods: # pragma: no cover 

1499 assert method in dir(NullInterpolator) 

1500 

1501 def test_x(self) -> None: 

1502 """ 

1503 Test :attr:`colour.algebra.interpolation.NullInterpolator.x` 

1504 property. 

1505 """ 

1506 

1507 x = y = np.linspace(0, 1, 10) 

1508 null_interpolator = NullInterpolator(x, y) 

1509 

1510 np.testing.assert_equal(null_interpolator.x, x) 

1511 

1512 def test_y(self) -> None: 

1513 """ 

1514 Test :attr:`colour.algebra.interpolation.NullInterpolator.y` 

1515 property. 

1516 """ 

1517 

1518 if not is_scipy_installed(): # pragma: no cover 

1519 return 

1520 

1521 x = y = np.linspace(0, 1, 10) 

1522 null_interpolator = NullInterpolator(x, y) 

1523 

1524 np.testing.assert_equal(null_interpolator.y, y) 

1525 

1526 def test_absolute_tolerance(self) -> None: 

1527 """ 

1528 Test :attr:`colour.algebra.interpolation.NullInterpolator.\ 

1529absolute_tolerance` property. 

1530 """ 

1531 

1532 x = y = np.linspace(0, 1, 10) 

1533 null_interpolator = NullInterpolator(x, y, absolute_tolerance=0.1) 

1534 

1535 np.testing.assert_equal(null_interpolator.absolute_tolerance, 0.1) 

1536 

1537 def test_relative_tolerance(self) -> None: 

1538 """ 

1539 Test :attr:`colour.algebra.interpolation.NullInterpolator.\ 

1540relative_tolerance` property. 

1541 """ 

1542 

1543 x = y = np.linspace(0, 1, 10) 

1544 null_interpolator = NullInterpolator(x, y, relative_tolerance=0.1) 

1545 

1546 np.testing.assert_equal(null_interpolator.relative_tolerance, 0.1) 

1547 

1548 def test_default(self) -> None: 

1549 """ 

1550 Test :attr:`colour.algebra.interpolation.NullInterpolator.\ 

1551default` property. 

1552 """ 

1553 

1554 x = y = np.linspace(0, 1, 10) 

1555 null_interpolator = NullInterpolator(x, y, default=0) 

1556 

1557 np.testing.assert_equal(null_interpolator.default, 0) 

1558 

1559 def test_raise_exception___init__(self) -> None: 

1560 """ 

1561 Test :meth:`colour.algebra.interpolation.NullInterpolator.__init__` 

1562 method raised exception. 

1563 """ 

1564 

1565 x, y = np.linspace(0, 1, 10), np.linspace(0, 1, 15) 

1566 pytest.raises(ValueError, NullInterpolator, x, y) 

1567 

1568 def test__call__(self) -> None: 

1569 """ 

1570 Test :meth:`colour.algebra.interpolation.NullInterpolator.__call__` 

1571 method. 

1572 """ 

1573 

1574 if not is_scipy_installed(): # pragma: no cover 

1575 return 

1576 

1577 x = np.arange(len(DATA_POINTS_A)) 

1578 null_interpolator = NullInterpolator(x, DATA_POINTS_A) 

1579 np.testing.assert_allclose( 

1580 null_interpolator(np.array([0.75, 2.0, 3.0, 4.75])), 

1581 np.array([np.nan, 12.46, 9.51, np.nan]), 

1582 atol=TOLERANCE_ABSOLUTE_TESTS, 

1583 ) 

1584 

1585 null_interpolator = NullInterpolator(x, DATA_POINTS_A, 0.25, 0.25) 

1586 np.testing.assert_allclose( 

1587 null_interpolator(np.array([0.75, 2.0, 3.0, 4.75])), 

1588 np.array([12.32, 12.46, 9.51, 4.33]), 

1589 atol=TOLERANCE_ABSOLUTE_TESTS, 

1590 ) 

1591 

1592 def test_raise_exception___call__(self) -> None: 

1593 """ 

1594 Test :meth:`colour.algebra.interpolation.NullInterpolator.__call__` 

1595 method raised exception. 

1596 """ 

1597 

1598 x = y = np.linspace(0, 1, 10) 

1599 null_interpolator = NullInterpolator(x, y) 

1600 

1601 pytest.raises(ValueError, null_interpolator, -1) 

1602 

1603 pytest.raises(ValueError, null_interpolator, 11) 

1604 

1605 @ignore_numpy_errors 

1606 def test_nan__call__(self) -> None: 

1607 """ 

1608 Test :meth:`colour.algebra.interpolation.NullInterpolator.__call__` 

1609 method nan support. 

1610 """ 

1611 

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

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

1614 for case in cases: 

1615 try: 

1616 null_interpolator = NullInterpolator(case, case) 

1617 null_interpolator(case[0]) 

1618 except ValueError: # noqa: PERF203 

1619 pass 

1620 

1621 

1622class TestLagrangeCoefficients: 

1623 """ 

1624 Define :func:`colour.algebra.interpolation.lagrange_coefficients` 

1625 definition unit tests methods. 

1626 """ 

1627 

1628 def test_lagrange_coefficients(self) -> None: 

1629 """ 

1630 Test :func:`colour.algebra.interpolation.lagrange_coefficients` 

1631 definition. 

1632 

1633 Notes 

1634 ----- 

1635 - :attr:`LAGRANGE_COEFFICIENTS_A` and :attr:`LAGRANGE_COEFFICIENTS_B` 

1636 attributes data is matching :cite:`Fairman1985b`. 

1637 

1638 References 

1639 ---------- 

1640 :cite:`Fairman1985b` 

1641 """ 

1642 

1643 lc = [lagrange_coefficients(i, 3) for i in np.linspace(0.05, 0.95, 19)] 

1644 np.testing.assert_allclose( 

1645 lc, LAGRANGE_COEFFICIENTS_A, atol=TOLERANCE_ABSOLUTE_TESTS 

1646 ) 

1647 

1648 lc = [lagrange_coefficients(i, 4) for i in np.linspace(1.05, 1.95, 19)] 

1649 np.testing.assert_allclose( 

1650 lc, LAGRANGE_COEFFICIENTS_B, atol=TOLERANCE_ABSOLUTE_TESTS 

1651 ) 

1652 

1653 

1654class TestTableInterpolationTrilinear: 

1655 """ 

1656 Define :func:`colour.algebra.interpolation.\ 

1657table_interpolation_trilinear` definition unit tests methods. 

1658 """ 

1659 

1660 def test_interpolation_trilinear(self) -> None: 

1661 """ 

1662 Test :func:`colour.algebra.interpolation.\ 

1663table_interpolation_trilinear` definition. 

1664 """ 

1665 

1666 prng = np.random.RandomState(4) 

1667 

1668 V_xyz = random_triplet_generator(16, random_state=prng) 

1669 

1670 np.testing.assert_allclose( 

1671 table_interpolation_trilinear(V_xyz, LUT_TABLE), 

1672 np.array( 

1673 [ 

1674 [1.07937594, -0.02773926, 0.55498254], 

1675 [0.53983424, 0.37099516, 0.13994561], 

1676 [1.13449122, -0.00305380, 0.13792909], 

1677 [0.73411897, 1.00141020, 0.59348239], 

1678 [0.74066176, 0.44679540, 0.55030394], 

1679 [0.20634750, 0.84797880, 0.55905579], 

1680 [0.92348649, 0.73112515, 0.42362820], 

1681 [0.03639248, 0.70357649, 0.52375041], 

1682 [0.29215488, 0.19697840, 0.44603879], 

1683 [0.47793470, 0.08696360, 0.70288463], 

1684 [0.88883354, 0.68680856, 0.87404642], 

1685 [0.21430977, 0.16796653, 0.19634247], 

1686 [0.82118989, 0.69239283, 0.39932389], 

1687 [1.06679072, 0.37974319, 0.49759377], 

1688 [0.17856230, 0.44755467, 0.62045271], 

1689 [0.59220355, 0.93136492, 0.30063692], 

1690 ] 

1691 ), 

1692 atol=TOLERANCE_ABSOLUTE_TESTS, 

1693 ) 

1694 

1695 

1696class TestTableInterpolationTetrahedral: 

1697 """ 

1698 Define :func:`colour.algebra.interpolation.\ 

1699table_interpolation_tetrahedral` definition unit tests methods. 

1700 """ 

1701 

1702 def test_interpolation_tetrahedral(self) -> None: 

1703 """ 

1704 Test :func:`colour.algebra.interpolation.\ 

1705table_interpolation_tetrahedral` definition. 

1706 """ 

1707 

1708 prng = np.random.RandomState(4) 

1709 

1710 V_xyz = random_triplet_generator(16, random_state=prng) 

1711 

1712 np.testing.assert_allclose( 

1713 table_interpolation_tetrahedral(V_xyz, LUT_TABLE), 

1714 np.array( 

1715 [ 

1716 [1.08039215, -0.02840092, 0.55855303], 

1717 [0.52208945, 0.35297753, 0.13599555], 

1718 [1.14373467, -0.00422138, 0.13413290], 

1719 [0.71384967, 0.98420883, 0.57982724], 

1720 [0.76771576, 0.46280975, 0.55106736], 

1721 [0.20861663, 0.85077712, 0.57102264], 

1722 [0.90398698, 0.72351675, 0.41151955], 

1723 [0.03749453, 0.70226823, 0.52614254], 

1724 [0.29626758, 0.21645072, 0.47615873], 

1725 [0.46729624, 0.07494851, 0.68892548], 

1726 [0.85907681, 0.67744258, 0.84410486], 

1727 [0.24335535, 0.20896545, 0.21996717], 

1728 [0.79244027, 0.66930773, 0.39213595], 

1729 [1.08383608, 0.37985897, 0.49011919], 

1730 [0.14683649, 0.43624903, 0.58706947], 

1731 [0.61272658, 0.92799297, 0.29650424], 

1732 ] 

1733 ), 

1734 atol=TOLERANCE_ABSOLUTE_TESTS, 

1735 ) 

1736 

1737 

1738class TestTableInterpolation: 

1739 """ 

1740 Define :func:`colour.algebra.interpolation.table_interpolation` 

1741 wrapper definition unit tests methods. 

1742 """ 

1743 

1744 def test_table_interpolation(self) -> None: 

1745 """ 

1746 Test :func:`colour.algebra.interpolation.table_interpolation` 

1747 wrapper definition. 

1748 """ 

1749 

1750 prng = np.random.RandomState(4) 

1751 V_xyz = prng.random_sample((10, 3)) 

1752 

1753 # Test with "Trilinear" method 

1754 np.testing.assert_allclose( 

1755 table_interpolation(V_xyz, LUT_TABLE, method="Trilinear"), 

1756 table_interpolation_trilinear(V_xyz, LUT_TABLE), 

1757 atol=TOLERANCE_ABSOLUTE_TESTS, 

1758 ) 

1759 

1760 # Test with "Tetrahedral" method 

1761 np.testing.assert_allclose( 

1762 table_interpolation(V_xyz, LUT_TABLE, method="Tetrahedral"), 

1763 table_interpolation_tetrahedral(V_xyz, LUT_TABLE), 

1764 atol=TOLERANCE_ABSOLUTE_TESTS, 

1765 )