Coverage for colour/colorimetry/tests/test_spectrum.py: 100%
280 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
« 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.colorimetry.spectrum` module."""
3from __future__ import annotations
5import pickle
7import numpy as np
8import pytest
10import colour
11from colour.algebra import CubicSplineInterpolator
12from colour.colorimetry.spectrum import (
13 SPECTRAL_SHAPE_DEFAULT,
14 MultiSpectralDistributions,
15 SpectralDistribution,
16 SpectralShape,
17 reshape_msds,
18 reshape_sd,
19 sds_and_msds_to_msds,
20 sds_and_msds_to_sds,
21)
22from colour.constants import TOLERANCE_ABSOLUTE_TESTS
23from colour.utilities import is_caching_enabled, is_scipy_installed, tstack
25__author__ = "Colour Developers"
26__copyright__ = "Copyright 2013 Colour Developers"
27__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
28__maintainer__ = "Colour Developers"
29__email__ = "colour-developers@colour-science.org"
30__status__ = "Production"
32__all__ = [
33 "DATA_SAMPLE",
34 "DATA_SAMPLE_NON_UNIFORM",
35 "DATA_SAMPLE_INTERPOLATED",
36 "DATA_SAMPLE_INTERPOLATED_NON_UNIFORM",
37 "DATA_SAMPLE_NORMALISED",
38 "DATA_STANDARD_OBSERVER_2_DEGREE_CIE1931",
39 "DATA_CMFS",
40 "DATA_SAMPLE_ABRIDGED",
41 "DATA_MULTI_SAMPLE_ABRIDGED",
42 "TestSpectralShape",
43 "TestSpectralDistribution",
44 "TestMultiSpectralDistributions",
45 "TestReshapeSd",
46 "TestSdsAndMdsToSds",
47 "TestSdsAndMsdsToMsds",
48]
50DATA_SAMPLE: dict = {
51 340: 0.0000,
52 360: 0.0000,
53 380: 0.0000,
54 400: 0.0641,
55 420: 0.0645,
56 440: 0.0562,
57 460: 0.0537,
58 480: 0.0559,
59 500: 0.0651,
60 520: 0.0705,
61 540: 0.0772,
62 560: 0.0870,
63 580: 0.1128,
64 600: 0.1360,
65 620: 0.1511,
66 640: 0.1688,
67 660: 0.1996,
68 680: 0.2397,
69 700: 0.2852,
70 720: 0.0000,
71 740: 0.0000,
72 760: 0.0000,
73 780: 0.0000,
74 800: 0.0000,
75 820: 0.0000,
76}
78DATA_SAMPLE_NON_UNIFORM: dict = {
79 391.898: 16.331740,
80 392.069: 16.333122,
81 405.606: 40.197224,
82 406.794: 39.923366,
83 406.891: 39.924098,
84 407.026: 39.925138,
85 416.286: 40.064293,
86 418.690: 40.009950,
87 426.700: 18.045809,
88 426.726: 18.045986,
89 432.556: 38.435883,
90 464.742: 29.534647,
91 465.025: 29.534647,
92 465.147: 29.534647,
93 466.586: 38.226470,
94 477.175: 7.487795,
95 493.205: 7.684766,
96 505.217: 7.684766,
97 513.294: 20.701285,
98 513.328: 20.704211,
99 514.349: 20.704211,
100 514.516: 20.709788,
101 515.109: 20.709788,
102 538.034: 7.684766,
103 564.807: 20.704211,
104 566.247: 20.709788,
105 569.592: 32.103387,
106 580.133: 37.548490,
107 581.198: 37.548490,
108 582.642: 40.197224,
109 588.977: 18.045986,
110 589.159: 18.045809,
111 600.113: 8.643020,
112 600.603: 8.647157,
113 600.718: 8.640394,
114 601.068: 8.640394,
115 601.322: 8.647157,
116 601.484: 8.643020,
117 657.805: 14.448826,
118 658.288: 14.448826,
119 658.761: 8.537097,
120 674.438: 38.22647,
121 678.390: 20.709788,
122 703.725: 38.435883,
123 711.318: 8.647157,
124 711.519: 8.640394,
125 711.563: 22.532398,
126 711.699: 8.647157,
127 711.990: 22.536906,
128 723.132: 16.33174,
129 723.642: 16.333122,
130 761.265: 41.342187,
131 786.089: 8.850659,
132 805.862: 8.850659,
133}
135DATA_SAMPLE_INTERPOLATED: tuple = (
136 0.000000000000000,
137 0.000230709627131,
138 0.000384144814593,
139 0.000507137093115,
140 0.000632114832536,
141 0.000778810112328,
142 0.000955965592105,
143 0.001163041382140,
144 0.001391921913876,
145 0.001628622810444,
146 0.001854997757177,
147 0.002050445372122,
148 0.002193616076555,
149 0.002264118965498,
150 0.002244228678230,
151 0.002120592268802,
152 0.001885936076555,
153 0.001540772596628,
154 0.001095107350478,
155 0.000570145756392,
156 0.000000000000000,
157 -0.000581325882457,
158 -0.001183945630981,
159 -0.001820338942229,
160 -0.002492278660287,
161 -0.003192248184715,
162 -0.003904858878589,
163 -0.004608267476544,
164 -0.005275593492823,
165 -0.005876336629317,
166 -0.006377794183612,
167 -0.006746478457031,
168 -0.006949534162679,
169 -0.006956155833489,
170 -0.006739005230263,
171 -0.006275628749720,
172 -0.005549874832536,
173 -0.004553311371393,
174 -0.003286643119019,
175 -0.001761129096236,
176 0.000000000000000,
177 0.001979832128906,
178 0.004221516875000,
179 0.006762744980469,
180 0.009617760000000,
181 0.012780285644531,
182 0.016226453125000,
183 0.019917728496094,
184 0.023803840000000,
185 0.027825705410156,
186 0.031918359375000,
187 0.036013880761719,
188 0.040044320000000,
189 0.043944626425781,
190 0.047655575625000,
191 0.051126696777344,
192 0.054319200000000,
193 0.057208903691406,
194 0.059789161875000,
195 0.062073791542969,
196 0.064100000000000,
197 0.065908998066406,
198 0.067477265625000,
199 0.068776060136719,
200 0.069791040000000,
201 0.070520520019531,
202 0.070973726875000,
203 0.071169054589844,
204 0.071132320000000,
205 0.070895018222656,
206 0.070492578125000,
207 0.069962617792969,
208 0.069343200000000,
209 0.068671087675781,
210 0.067979999375000,
211 0.067298864746094,
212 0.066650080000000,
213 0.066047763378906,
214 0.065496010625000,
215 0.064987150449219,
216 0.064500000000000,
217 0.064007805449219,
218 0.063510900625000,
219 0.063016138378906,
220 0.062528640000000,
221 0.062051989746094,
222 0.061588429375000,
223 0.061139052675781,
224 0.060704000000000,
225 0.060282652792969,
226 0.059873828125000,
227 0.059475973222656,
228 0.059087360000000,
229 0.058706279589844,
230 0.058331236875000,
231 0.057961145019531,
232 0.057595520000000,
233 0.057234675136719,
234 0.056879915625000,
235 0.056533733066406,
236 0.056200000000000,
237 0.055883811757812,
238 0.055589516250000,
239 0.055320009023437,
240 0.055076960000000,
241 0.054860961914063,
242 0.054671678750000,
243 0.054507994179687,
244 0.054368160000000,
245 0.054249944570312,
246 0.054150781250000,
247 0.054067916835938,
248 0.053998560000000,
249 0.053940029726562,
250 0.053889903750000,
251 0.053846166992187,
252 0.053807360000000,
253 0.053772727382813,
254 0.053742366250000,
255 0.053717374648438,
256 0.053700000000000,
257 0.053692483144531,
258 0.053693175625000,
259 0.053700270058594,
260 0.053712960000000,
261 0.053731311035156,
262 0.053756131875000,
263 0.053788845449219,
264 0.053831360000000,
265 0.053885940175781,
266 0.053955078125000,
267 0.054041364589844,
268 0.054147360000000,
269 0.054275465566406,
270 0.054427794375000,
271 0.054606042480469,
272 0.054811360000000,
273 0.055044222207031,
274 0.055304300625000,
275 0.055590334121094,
276 0.055900000000000,
277 0.056231407851562,
278 0.056587597500000,
279 0.056971279335937,
280 0.057383360000000,
281 0.057823168945313,
282 0.058288685000000,
283 0.058776762929688,
284 0.059283360000000,
285 0.059803762539063,
286 0.060332812500000,
287 0.060865134023438,
288 0.061395360000000,
289 0.061918358632813,
290 0.062429460000000,
291 0.062924682617188,
292 0.063400960000000,
293 0.063856367226563,
294 0.064290347500000,
295 0.064703938710938,
296 0.065100000000000,
297 0.065481647265625,
298 0.065846786250000,
299 0.066192982265625,
300 0.066519040000000,
301 0.066824853515625,
302 0.067111256250000,
303 0.067379871015625,
304 0.067632960000000,
305 0.067873274765625,
306 0.068103906250000,
307 0.068328134765625,
308 0.068549280000000,
309 0.068770551015625,
310 0.068994896250000,
311 0.069224853515625,
312 0.069462400000000,
313 0.069708802265625,
314 0.069964466250000,
315 0.070228787265625,
316 0.070500000000000,
317 0.070776270703125,
318 0.071059446250000,
319 0.071351597578125,
320 0.071653920000000,
321 0.071966845703125,
322 0.072290156250000,
323 0.072623095078125,
324 0.072964480000000,
325 0.073312815703125,
326 0.073666406250000,
327 0.074023467578125,
328 0.074382240000000,
329 0.074741100703125,
330 0.075098676250000,
331 0.075453955078125,
332 0.075806400000000,
333 0.076156060703125,
334 0.076503686250000,
335 0.076850837578125,
336 0.077200000000000,
337 0.077552701992188,
338 0.077904262500000,
339 0.078250762070313,
340 0.078590880000000,
341 0.078925561523438,
342 0.079257685000000,
343 0.079591729101562,
344 0.079933440000000,
345 0.080289498554688,
346 0.080667187500000,
347 0.081074058632813,
348 0.081517600000000,
349 0.082004903085938,
350 0.082542330000000,
351 0.083135180664063,
352 0.083787360000000,
353 0.084501045117188,
354 0.085276352500000,
355 0.086111005195313,
356 0.087000000000000,
357 0.087938453242188,
358 0.088930890000000,
359 0.089981833007812,
360 0.091092960000000,
361 0.092263452148438,
362 0.093490342500000,
363 0.094768864414062,
364 0.096092800000000,
365 0.097454828554687,
366 0.098846875000000,
367 0.100260458320312,
368 0.101687040000000,
369 0.103118372460937,
370 0.104546847500000,
371 0.105965844726563,
372 0.107370080000000,
373 0.108755953867188,
374 0.110121900000000,
375 0.111468733632812,
376 0.112800000000000,
377 0.114120657988281,
378 0.115431176875000,
379 0.116730532871094,
380 0.118017600000000,
381 0.119291174316406,
382 0.120549998125000,
383 0.121792784199219,
384 0.123018240000000,
385 0.124225091894531,
386 0.125412109375000,
387 0.126578129277344,
388 0.127722080000000,
389 0.128843005722656,
390 0.129940090625000,
391 0.131012683105469,
392 0.132060320000000,
393 0.133082750800781,
394 0.134079961875000,
395 0.135052200683594,
396 0.136000000000000,
397 0.136923531484375,
398 0.137820920000000,
399 0.138690739765625,
400 0.139532640000000,
401 0.140347216796875,
402 0.141135885000000,
403 0.141900750078125,
404 0.142644480000000,
405 0.143370177109375,
406 0.144081250000000,
407 0.144781285390625,
408 0.145473920000000,
409 0.146162712421875,
410 0.146851015000000,
411 0.147541845703125,
412 0.148237760000000,
413 0.148940722734375,
414 0.149651980000000,
415 0.150371931015625,
416 0.151100000000000,
417 0.151834687363281,
418 0.152574745625000,
419 0.153319862089844,
420 0.154070560000000,
421 0.154828088378906,
422 0.155594311875000,
423 0.156371600605469,
424 0.157162720000000,
425 0.157970720644531,
426 0.158798828125000,
427 0.159650332871094,
428 0.160528480000000,
429 0.161436359160156,
430 0.162376794375000,
431 0.163352233886719,
432 0.164364640000000,
433 0.165415378925781,
434 0.166505110625000,
435 0.167633678652344,
436 0.168800000000000,
437 0.170002988242187,
438 0.171244585000000,
439 0.172526722382812,
440 0.173850400000000,
441 0.175215795898437,
442 0.176622377500000,
443 0.178069012539063,
444 0.179554080000000,
445 0.181075581054688,
446 0.182631250000000,
447 0.184218665195313,
448 0.185835360000000,
449 0.187478933710938,
450 0.189147162500000,
451 0.190838110351563,
452 0.192550240000000,
453 0.194282523867188,
454 0.196034555000000,
455 0.197806658007813,
456 0.199600000000000,
457 0.201405046894531,
458 0.203174116875000,
459 0.204868198964844,
460 0.206468000000000,
461 0.207971350097656,
462 0.209390608125000,
463 0.210750067167969,
464 0.212083360000000,
465 0.213430864550781,
466 0.214837109375000,
467 0.216348179121094,
468 0.218009120000000,
469 0.219861345253906,
470 0.221940040625000,
471 0.224271569824219,
472 0.226870880000000,
473 0.229738907207031,
474 0.232859981875000,
475 0.236199234277344,
476 0.239700000000000,
477 0.243337282929688,
478 0.247262056250000,
479 0.251598942851562,
480 0.256394240000000,
481 0.261625952148438,
482 0.267213823750000,
483 0.273029372070313,
484 0.278905920000000,
485 0.284648628867188,
486 0.290044531250000,
487 0.294872563789062,
488 0.298913600000000,
489 0.301960483085938,
490 0.303828058750000,
491 0.304363208007813,
492 0.303454880000000,
493 0.301044124804688,
494 0.297134126250000,
495 0.291800234726562,
496 0.285200000000000,
497 0.277470396855469,
498 0.268408756875000,
499 0.257826504003906,
500 0.245651040000000,
501 0.231911267089844,
502 0.216723110625000,
503 0.200275041738281,
504 0.182813600000000,
505 0.164628916074219,
506 0.146040234375000,
507 0.127381435722656,
508 0.108986560000000,
509 0.091175328808594,
510 0.074238668125000,
511 0.058424230957031,
512 0.043921920000000,
513 0.030849410292969,
514 0.019237671875000,
515 0.009016492441406,
516 0.000000000000000,
517 -0.008014721386719,
518 -0.014901410625000,
519 -0.020510217441406,
520 -0.024767360000000,
521 -0.027665856933594,
522 -0.029256259375000,
523 -0.029637382988281,
524 -0.028947040000000,
525 -0.027352771230469,
526 -0.025042578125000,
527 -0.022215654785156,
528 -0.019073120000000,
529 -0.015808749277344,
530 -0.012599706875000,
531 -0.009597277832031,
532 -0.006917600000000,
533 -0.004632396074219,
534 -0.002759705625000,
535 -0.001254617128906,
536 0.000000000000000,
537 0.001146203203125,
538 0.002165737500000,
539 0.003010363984375,
540 0.003650560000000,
541 0.004073291015625,
542 0.004279782500000,
543 0.004283291796875,
544 0.004106880000000,
545 0.003781183828125,
546 0.003342187500000,
547 0.002828994609375,
548 0.002281600000000,
549 0.001738661640625,
550 0.001235272500000,
551 0.000800732421875,
552 0.000456320000000,
553 0.000213064453125,
554 0.000069517500000,
555 0.000009525234375,
556 0.000000000000000,
557 0.000000000000000,
558 0.000000000000000,
559 0.000000000000000,
560 0.000000000000000,
561 0.000000000000000,
562 0.000000000000000,
563 0.000000000000000,
564 0.000000000000000,
565 0.000000000000000,
566 0.000000000000000,
567 0.000000000000000,
568 0.000000000000000,
569 0.000000000000000,
570 0.000000000000000,
571 0.000000000000000,
572 0.000000000000000,
573 0.000000000000000,
574 0.000000000000000,
575 0.000000000000000,
576 0.000000000000000,
577 0.000000000000000,
578 0.000000000000000,
579 0.000000000000000,
580 0.000000000000000,
581 0.000000000000000,
582 0.000000000000000,
583 0.000000000000000,
584 0.000000000000000,
585 0.000000000000000,
586 0.000000000000000,
587 0.000000000000000,
588 0.000000000000000,
589 0.000000000000000,
590 0.000000000000000,
591 0.000000000000000,
592 0.000000000000000,
593 0.000000000000000,
594 0.000000000000000,
595 0.000000000000000,
596 0.000000000000000,
597 0.000000000000000,
598 0.000000000000000,
599 0.000000000000000,
600 0.000000000000000,
601 0.000000000000000,
602 0.000000000000000,
603 0.000000000000000,
604 0.000000000000000,
605 0.000000000000000,
606 0.000000000000000,
607 0.000000000000000,
608 0.000000000000000,
609 0.000000000000000,
610 0.000000000000000,
611 0.000000000000000,
612 0.000000000000000,
613 0.000000000000000,
614 0.000000000000000,
615 0.000000000000000,
616 0.000000000000000,
617)
619DATA_SAMPLE_INTERPOLATED_NON_UNIFORM: tuple = (
620 16.33174000,
621 16.64993716,
622 17.64548368,
623 19.20219560,
624 21.20388894,
625 23.53437976,
626 26.07748407,
627 28.71701792,
628 31.33679734,
629 33.82063837,
630 36.05235704,
631 37.91576938,
632 39.29469143,
633 40.07293922,
634 40.14077612,
635 39.92419302,
636 39.89684762,
637 39.81049683,
638 39.69333189,
639 39.57332622,
640 39.47845324,
641 39.43668638,
642 39.47599905,
643 39.62436468,
644 39.90975669,
645 40.33304002,
646 40.50491197,
647 39.74501724,
648 37.67902112,
649 34.62018880,
650 30.97314049,
651 27.14249640,
652 23.53287675,
653 20.54890177,
654 18.59519166,
655 18.08081760,
656 19.38373812,
657 22.23096797,
658 26.16305357,
659 30.72054135,
660 35.44397775,
661 39.87706471,
662 43.74602436,
663 47.05613715,
664 49.83624442,
665 52.11518748,
666 53.92180764,
667 55.28494623,
668 56.23344457,
669 56.79614397,
670 57.00188576,
671 56.87951125,
672 56.45786176,
673 55.76577861,
674 54.83210312,
675 53.68567662,
676 52.35534040,
677 50.86993581,
678 49.25830415,
679 47.54928674,
680 45.77172491,
681 43.95445997,
682 42.12633325,
683 40.31618605,
684 38.55285970,
685 36.86519552,
686 35.28203483,
687 33.83221894,
688 32.54458918,
689 31.44798686,
690 30.57125331,
691 29.94322984,
692 29.59275777,
693 29.54381964,
694 32.79286157,
695 40.36558235,
696 45.21160576,
697 47.09673165,
698 46.46577457,
699 43.76354913,
700 39.43486990,
701 33.92455146,
702 27.67740839,
703 21.13825529,
704 14.75190672,
705 8.96317728,
706 4.18354245,
707 0.49841631,
708 -2.19120584,
709 -3.98642200,
710 -4.98833019,
711 -5.29802840,
712 -5.01661465,
713 -4.24518693,
714 -3.08484325,
715 -1.63668162,
716 -0.00180003,
717 1.71870349,
718 3.42373096,
719 5.01218436,
720 6.38296569,
721 7.43497695,
722 8.07693863,
723 8.32474693,
724 8.26027419,
725 7.96635835,
726 7.52583734,
727 7.02154908,
728 6.53633153,
729 6.15302259,
730 5.95446022,
731 6.02348233,
732 6.44292687,
733 7.29563177,
734 8.65167043,
735 10.43511482,
736 12.47696318,
737 14.60671211,
738 16.65385820,
739 18.44789806,
740 19.81832829,
741 20.59464547,
742 20.70989576,
743 20.71490257,
744 20.63782267,
745 20.42824992,
746 20.09863019,
747 19.66155390,
748 19.12961147,
749 18.51539332,
750 17.83148987,
751 17.09049153,
752 16.30498873,
753 15.48757188,
754 14.65083142,
755 13.80735774,
756 12.96974128,
757 12.15057246,
758 11.36244169,
759 10.61793939,
760 9.92965598,
761 9.31018188,
762 8.77210752,
763 8.32802330,
764 7.99051965,
765 7.77218699,
766 7.68561574,
767 7.74083122,
768 7.93173795,
769 8.24599287,
770 8.67123920,
771 9.19512022,
772 9.80527915,
773 10.48935925,
774 11.23500376,
775 12.02985593,
776 12.86155901,
777 13.71775624,
778 14.58609087,
779 15.45420615,
780 16.30974532,
781 17.14035164,
782 17.93366833,
783 18.67733867,
784 19.35900588,
785 19.96631322,
786 20.48690393,
787 20.90842126,
788 21.21850846,
789 21.40480878,
790 21.45496545,
791 21.35662174,
792 21.09742087,
793 20.66514352,
794 20.43751858,
795 21.91097080,
796 25.20288294,
797 29.29167835,
798 33.13704964,
799 36.09348577,
800 38.20199674,
801 39.57231714,
802 40.31418157,
803 40.53732465,
804 40.35148096,
805 39.86638512,
806 39.19177172,
807 38.43737537,
808 37.71293067,
809 37.32215353,
810 38.85348208,
811 40.28480326,
812 38.66906876,
813 34.70409378,
814 29.52631184,
815 24.27215647,
816 20.07806121,
817 18.08045957,
818 17.97606450,
819 17.51718098,
820 16.71767084,
821 15.66588470,
822 14.45017318,
823 13.15888689,
824 11.88037645,
825 10.70299247,
826 9.71508557,
827 9.00500637,
828 8.66110548,
829 8.63646961,
830 8.61886171,
831 8.49018794,
832 8.26908563,
833 7.96116808,
834 7.57204861,
835 7.10734052,
836 6.57265713,
837 5.97361172,
838 5.31581763,
839 4.60488814,
840 3.84643656,
841 3.04607621,
842 2.20942040,
843 1.34208241,
844 0.44967558,
845 -0.46218681,
846 -1.38789144,
847 -2.32182500,
848 -3.25837419,
849 -4.19192570,
850 -5.11686623,
851 -6.02758247,
852 -6.91846110,
853 -7.78388883,
854 -8.61825235,
855 -9.41593835,
856 -10.17133352,
857 -10.87882456,
858 -11.53279815,
859 -12.12764100,
860 -12.65773980,
861 -13.11748123,
862 -13.50125200,
863 -13.80343879,
864 -14.01842830,
865 -14.14060723,
866 -14.16436225,
867 -14.08408008,
868 -13.89414739,
869 -13.58895089,
870 -13.16287727,
871 -12.61031321,
872 -11.92564542,
873 -11.10326059,
874 -10.13754541,
875 -9.02288657,
876 -7.75367076,
877 -6.32428468,
878 -4.72911503,
879 -2.96254849,
880 -1.01897176,
881 1.10722847,
882 3.42166550,
883 5.92995265,
884 8.63770321,
885 11.55053050,
886 14.66926935,
887 6.86179709,
888 -5.47290466,
889 -13.83246355,
890 -18.66023243,
891 -20.39956416,
892 -19.49381157,
893 -16.38632753,
894 -11.52046487,
895 -5.33957647,
896 1.71298484,
897 9.19386620,
898 16.65971477,
899 23.66717768,
900 29.77290209,
901 34.53353516,
902 37.50572402,
903 38.25154792,
904 36.50596565,
905 32.20857414,
906 25.31081084,
907 15.77278173,
908 3.77074445,
909 -10.29313973,
910 -26.00608936,
911 -42.95532304,
912 -60.72805933,
913 -78.91151682,
914 -97.09291408,
915 -114.85946968,
916 -131.79840221,
917 -147.49693024,
918 -161.54227235,
919 -173.52164712,
920 -183.02227312,
921 -189.63136892,
922 -192.93615311,
923 -192.52384426,
924 -187.98166096,
925 -178.89682177,
926 -164.85654527,
927 -145.44805004,
928 -120.25855466,
929 -88.87527770,
930 -50.88543775,
931 -5.87625337,
932 46.56007116,
933 104.43504592,
934 159.52668786,
935 202.61238918,
936 224.46954207,
937 215.87553872,
938 167.60777130,
939 70.44363202,
940 5.46110638,
941 141.75857149,
942 230.42498382,
943 276.55540391,
944 287.68451731,
945 271.34700958,
946 235.07756626,
947 186.41087289,
948 132.88161504,
949 82.02447824,
950 41.37414805,
951 18.46531002,
952 16.85424129,
953 19.09321438,
954 21.24241296,
955 23.30206825,
956 25.27241149,
957 27.15367391,
958 28.94608674,
959 30.64988121,
960 32.26528857,
961 33.79254002,
962 35.23186682,
963 36.58350019,
964 37.84767137,
965 39.02461158,
966 40.11455206,
967 41.11772404,
968 42.03435875,
969 42.86468742,
970 43.60894129,
971 44.26735159,
972 44.84014956,
973 45.32756641,
974 45.72983339,
975 46.04718172,
976 46.27984264,
977 46.42804739,
978 46.49202718,
979 46.47201326,
980 46.36823686,
981 46.18092921,
982 45.91032154,
983 45.55664508,
984 45.12013106,
985 44.60101073,
986 43.99951530,
987 43.31587601,
988 42.55032410,
989 41.70309079,
990 40.77461777,
991 39.76848476,
992 38.69068156,
993 37.54725968,
994 36.34427059,
995 35.08776577,
996 33.78379673,
997 32.43841493,
998 31.05767187,
999 29.64761904,
1000 28.21430791,
1001 26.76378998,
1002 25.30211674,
1003 23.83533966,
1004 22.36951024,
1005 20.91067996,
1006 19.46490031,
1007 18.03822277,
1008 16.63669883,
1009 15.26637998,
1010 13.93331770,
1011 12.64356348,
1012 11.40316880,
1013 10.21818516,
1014 9.09466403,
1015 8.03865691,
1016 7.05621528,
1017 6.15339062,
1018 5.33623443,
1019 4.61079818,
1020 3.98313337,
1021 3.45929148,
1022 3.04532400,
1023 2.74728241,
1024 2.57121821,
1025 2.52318286,
1026 2.60922788,
1027 2.83540473,
1028 3.20776490,
1029 3.73235989,
1030 4.41524117,
1031 5.26246024,
1032 6.28006857,
1033 7.47411766,
1034 8.85065900,
1035)
1037DATA_SAMPLE_NORMALISED: tuple = (
1038 0.000000000000000,
1039 0.000000000000000,
1040 0.000000000000000,
1041 22.475455820476860,
1042 22.615708274894811,
1043 19.705469845722302,
1044 18.828892005610097,
1045 19.600280504908834,
1046 22.826086956521742,
1047 24.719495091164092,
1048 27.068723702664798,
1049 30.504908835904626,
1050 39.551192145862551,
1051 47.685834502103788,
1052 52.980364656381497,
1053 59.186535764375883,
1054 69.985974754558200,
1055 84.046283309957929,
1056 100.000000000000000,
1057 0.000000000000000,
1058 0.000000000000000,
1059 0.000000000000000,
1060 0.000000000000000,
1061 0.000000000000000,
1062 0.000000000000000,
1063)
1065DATA_STANDARD_OBSERVER_2_DEGREE_CIE1931: dict = {
1066 380: (0.001368, 0.000039, 0.006450),
1067 385: (0.002236, 0.000064, 0.010550),
1068 390: (0.004243, 0.000120, 0.020050),
1069 395: (0.007650, 0.000217, 0.036210),
1070 400: (0.014310, 0.000396, 0.067850),
1071 405: (0.023190, 0.000640, 0.110200),
1072 410: (0.043510, 0.001210, 0.207400),
1073 415: (0.077630, 0.002180, 0.371300),
1074 420: (0.134380, 0.004000, 0.645600),
1075 425: (0.214770, 0.007300, 1.039050),
1076 430: (0.283900, 0.011600, 1.385600),
1077 435: (0.328500, 0.016840, 1.622960),
1078 440: (0.348280, 0.023000, 1.747060),
1079 445: (0.348060, 0.029800, 1.782600),
1080 450: (0.336200, 0.038000, 1.772110),
1081 455: (0.318700, 0.048000, 1.744100),
1082 460: (0.290800, 0.060000, 1.669200),
1083 465: (0.251100, 0.073900, 1.528100),
1084 470: (0.195360, 0.090980, 1.287640),
1085 475: (0.142100, 0.112600, 1.041900),
1086 480: (0.095640, 0.139020, 0.812950),
1087 485: (0.057950, 0.169300, 0.616200),
1088 490: (0.032010, 0.208020, 0.465180),
1089 495: (0.014700, 0.258600, 0.353300),
1090 500: (0.004900, 0.323000, 0.272000),
1091 505: (0.002400, 0.407300, 0.212300),
1092 510: (0.009300, 0.503000, 0.158200),
1093 515: (0.029100, 0.608200, 0.111700),
1094 520: (0.063270, 0.710000, 0.078250),
1095 525: (0.109600, 0.793200, 0.057250),
1096 530: (0.165500, 0.862000, 0.042160),
1097 535: (0.225750, 0.914850, 0.029840),
1098 540: (0.290400, 0.954000, 0.020300),
1099 545: (0.359700, 0.980300, 0.013400),
1100 550: (0.433450, 0.994950, 0.008750),
1101 555: (0.512050, 1.000000, 0.005750),
1102 560: (0.594500, 0.995000, 0.003900),
1103 565: (0.678400, 0.978600, 0.002750),
1104 570: (0.762100, 0.952000, 0.002100),
1105 575: (0.842500, 0.915400, 0.001800),
1106 580: (0.916300, 0.870000, 0.001650),
1107 585: (0.978600, 0.816300, 0.001400),
1108 590: (1.026300, 0.757000, 0.001100),
1109 595: (1.056700, 0.694900, 0.001000),
1110 600: (1.062200, 0.631000, 0.000800),
1111 605: (1.045600, 0.566800, 0.000600),
1112 610: (1.002600, 0.503000, 0.000340),
1113 615: (0.938400, 0.441200, 0.000240),
1114 620: (0.854450, 0.381000, 0.000190),
1115 625: (0.751400, 0.321000, 0.000100),
1116 630: (0.642400, 0.265000, 0.000050),
1117 635: (0.541900, 0.217000, 0.000030),
1118 640: (0.447900, 0.175000, 0.000020),
1119 645: (0.360800, 0.138200, 0.000010),
1120 650: (0.283500, 0.107000, 0.000000),
1121 655: (0.218700, 0.081600, 0.000000),
1122 660: (0.164900, 0.061000, 0.000000),
1123 665: (0.121200, 0.044580, 0.000000),
1124 670: (0.087400, 0.032000, 0.000000),
1125 675: (0.063600, 0.023200, 0.000000),
1126 680: (0.046770, 0.017000, 0.000000),
1127 685: (0.032900, 0.011920, 0.000000),
1128 690: (0.022700, 0.008210, 0.000000),
1129 695: (0.015840, 0.005723, 0.000000),
1130 700: (0.011359, 0.004102, 0.000000),
1131 705: (0.008111, 0.002929, 0.000000),
1132 710: (0.005790, 0.002091, 0.000000),
1133 715: (0.004109, 0.001484, 0.000000),
1134 720: (0.002899, 0.001047, 0.000000),
1135 725: (0.002049, 0.000740, 0.000000),
1136 730: (0.001440, 0.000520, 0.000000),
1137 735: (0.001000, 0.000361, 0.000000),
1138 740: (0.000690, 0.000249, 0.000000),
1139 745: (0.000476, 0.000172, 0.000000),
1140 750: (0.000332, 0.000120, 0.000000),
1141 755: (0.000235, 0.000085, 0.000000),
1142 760: (0.000166, 0.000060, 0.000000),
1143 765: (0.000117, 0.000042, 0.000000),
1144 770: (0.000083, 0.000030, 0.000000),
1145 775: (0.000059, 0.000021, 0.000000),
1146 780: (0.000042, 0.000015, 0.000000),
1147}
1149DATA_CMFS: dict = {
1150 380: np.array([0.001368, 3.90e-05, 0.006450]),
1151 385: np.array([0.002236, 6.40e-05, 0.010550]),
1152 390: np.array([0.004243, 0.000120, 0.020050]),
1153 395: np.array([0.007650, 0.000217, 0.036210]),
1154 400: np.array([0.014310, 0.000396, 0.067850]),
1155 405: np.array([0.023190, 0.000640, 0.110200]),
1156 410: np.array([0.043510, 0.001210, 0.207400]),
1157 415: np.array([0.077630, 0.002180, 0.371300]),
1158 420: np.array([0.134380, 0.004000, 0.645600]),
1159 425: np.array([0.214770, 0.007300, 1.039050]),
1160 430: np.array([0.283900, 0.011600, 1.385600]),
1161 435: np.array([0.328500, 0.016840, 1.622960]),
1162 440: np.array([0.348280, 0.023000, 1.747060]),
1163 445: np.array([0.348060, 0.029800, 1.782600]),
1164 450: np.array([0.336200, 0.038000, 1.772110]),
1165 455: np.array([0.318700, 0.048000, 1.744100]),
1166 460: np.array([0.290800, 0.060000, 1.669200]),
1167 465: np.array([0.251100, 0.073900, 1.528100]),
1168 470: np.array([0.195360, 0.090980, 1.287640]),
1169 475: np.array([0.142100, 0.112600, 1.041900]),
1170 480: np.array([0.095640, 0.139020, 0.812950]),
1171 485: np.array([0.057950, 0.169300, 0.616200]),
1172 490: np.array([0.032010, 0.208020, 0.465180]),
1173 495: np.array([0.014700, 0.258600, 0.353300]),
1174 500: np.array([0.004900, 0.323000, 0.272000]),
1175 505: np.array([0.002400, 0.407300, 0.212300]),
1176 510: np.array([0.009300, 0.503000, 0.158200]),
1177 515: np.array([0.029100, 0.608200, 0.111700]),
1178 520: np.array([0.063270, 0.710000, 0.078250]),
1179 525: np.array([0.109600, 0.793200, 0.057250]),
1180 530: np.array([0.165500, 0.862000, 0.042160]),
1181 535: np.array([0.225750, 0.914850, 0.029840]),
1182 540: np.array([0.290400, 0.954000, 0.020300]),
1183 545: np.array([0.359700, 0.980300, 0.013400]),
1184 550: np.array([0.433450, 0.994950, 0.008750]),
1185 555: np.array([0.512050, 1.000000, 0.005750]),
1186 560: np.array([0.594500, 0.995000, 0.003900]),
1187 565: np.array([0.678400, 0.978600, 0.002750]),
1188 570: np.array([0.762100, 0.952000, 0.002100]),
1189 575: np.array([0.842500, 0.915400, 0.001800]),
1190 580: np.array([0.916300, 0.870000, 0.001650]),
1191 585: np.array([0.978600, 0.816300, 0.001400]),
1192 590: np.array([1.026300, 0.757000, 0.001100]),
1193 595: np.array([1.056700, 0.694900, 0.001000]),
1194 600: np.array([1.062200, 0.631000, 0.000800]),
1195 605: np.array([1.045600, 0.566800, 0.000600]),
1196 610: np.array([1.002600, 0.503000, 0.000340]),
1197 615: np.array([0.938400, 0.441200, 0.000240]),
1198 620: np.array([0.854450, 0.381000, 0.000190]),
1199 625: np.array([0.751400, 0.321000, 0.000100]),
1200 630: np.array([0.642400, 0.265000, 5.00e-05]),
1201 635: np.array([0.541900, 0.217000, 3.00e-05]),
1202 640: np.array([0.447900, 0.175000, 2.00e-05]),
1203 645: np.array([0.360800, 0.138200, 1.00e-05]),
1204 650: np.array([0.283500, 0.107000, 0.000000]),
1205 655: np.array([0.218700, 0.081600, 0.000000]),
1206 660: np.array([0.164900, 0.061000, 0.000000]),
1207 665: np.array([0.121200, 0.044580, 0.000000]),
1208 670: np.array([0.087400, 0.032000, 0.000000]),
1209 675: np.array([0.063600, 0.023200, 0.000000]),
1210 680: np.array([0.046770, 0.017000, 0.000000]),
1211 685: np.array([0.032900, 0.011920, 0.000000]),
1212 690: np.array([0.022700, 0.008210, 0.000000]),
1213 695: np.array([0.015840, 0.005723, 0.000000]),
1214 700: np.array([0.011359, 0.004102, 0.000000]),
1215 705: np.array([0.008111, 0.002929, 0.000000]),
1216 710: np.array([0.005790, 0.002091, 0.000000]),
1217 715: np.array([0.004109, 0.001484, 0.000000]),
1218 720: np.array([0.002899, 0.001047, 0.000000]),
1219 725: np.array([0.002049, 0.000740, 0.000000]),
1220 730: np.array([0.001440, 0.000520, 0.000000]),
1221 735: np.array([0.001000, 0.000361, 0.000000]),
1222 740: np.array([0.000690, 0.000249, 0.000000]),
1223 745: np.array([0.000476, 0.000172, 0.000000]),
1224 750: np.array([0.000332, 0.000120, 0.000000]),
1225 755: np.array([0.000235, 8.50e-05, 0.000000]),
1226 760: np.array([0.000166, 6.00e-05, 0.000000]),
1227 765: np.array([0.000117, 4.20e-05, 0.000000]),
1228 770: np.array([8.30e-05, 3.00e-05, 0.000000]),
1229 775: np.array([5.90e-05, 2.10e-05, 0.000000]),
1230 780: np.array([4.20e-05, 1.50e-05, 0.000000]),
1231}
1233DATA_SAMPLE_ABRIDGED: dict = {
1234 500: 0.0651,
1235 520: 0.0705,
1236 540: 0.0772,
1237 560: 0.0870,
1238 580: 0.1128,
1239 600: 0.1360,
1240}
1242DATA_MULTI_SAMPLE_ABRIDGED: dict = {
1243 500: (0.004900, 0.323000, 0.272000),
1244 510: (0.009300, 0.503000, 0.158200),
1245 520: (0.063270, 0.710000, 0.078250),
1246 530: (0.165500, 0.862000, 0.042160),
1247 540: (0.290400, 0.954000, 0.020300),
1248 550: (0.433450, 0.994950, 0.008750),
1249 560: (0.594500, 0.995000, 0.003900),
1250}
1253class TestSpectralShape:
1254 """
1255 Define :class:`colour.colorimetry.spectrum.SpectralShape` class unit tests
1256 methods.
1257 """
1259 def test_required_attributes(self) -> None:
1260 """Test the presence of required attributes."""
1262 required_attributes = (
1263 "start",
1264 "end",
1265 "interval",
1266 "boundaries",
1267 "wavelengths",
1268 )
1270 for attribute in required_attributes:
1271 assert attribute in dir(SpectralShape)
1273 def test_required_methods(self) -> None:
1274 """Test the presence of required methods."""
1276 required_methods = (
1277 "__init__",
1278 "__str__",
1279 "__repr__",
1280 "__hash__",
1281 "__iter__",
1282 "__contains__",
1283 "__len__",
1284 "__eq__",
1285 "__ne__",
1286 "range",
1287 )
1289 for method in required_methods:
1290 assert method in dir(SpectralShape)
1292 def test_pickling(self) -> None:
1293 """
1294 Test whether the :class:`colour.colorimetry.spectrum.SpectralShape`
1295 class can be pickled.
1296 """
1298 shape = SpectralShape(360, 830, 1)
1299 data = pickle.dumps(shape)
1300 data = pickle.loads(data) # noqa: S301
1301 assert shape == data
1303 def test_start(self) -> None:
1304 """
1305 Test :attr:`colour.colorimetry.spectrum.SpectralShape.start`
1306 attribute.
1307 """
1309 assert SpectralShape(360, 830, 1).start == 360
1311 pytest.raises(AssertionError, lambda: SpectralShape(360, 360, 1))
1313 pytest.raises(AssertionError, lambda: SpectralShape(360, 0, 1))
1315 def test_end(self) -> None:
1316 """Test :attr:`colour.colorimetry.spectrum.SpectralShape.end` property."""
1318 assert SpectralShape(360, 830, 1).end == 830
1320 pytest.raises(AssertionError, lambda: SpectralShape(830, 830, 1))
1322 pytest.raises(AssertionError, lambda: SpectralShape(830, 0, 1))
1324 def test_interval(self) -> None:
1325 """
1326 Test :attr:`colour.colorimetry.spectrum.SpectralShape.interval`
1327 property.
1328 """
1330 assert SpectralShape(360, 830, 1).interval == 1
1332 def test_boundaries(self) -> None:
1333 """
1334 Test :attr:`colour.colorimetry.spectrum.SpectralShape.boundaries`
1335 property.
1336 """
1338 shape = SpectralShape(400, 700, 1)
1339 shape.boundaries = (360, 830)
1341 assert shape.start == 360
1342 assert shape.end == 830
1344 def test_wavelengths(self) -> None:
1345 """
1346 Test :attr:`colour.colorimetry.spectrum.SpectralShape.wavelengths`
1347 property.
1348 """
1350 np.testing.assert_array_equal(
1351 SpectralShape(0, 10, 0.1).wavelengths,
1352 np.arange(0, 10 + 0.1, 0.1),
1353 )
1355 def test__hash__(self) -> None:
1356 """
1357 Test :meth:`colour.colorimetry.spectrum.SpectralShape.__hash__`
1358 method.
1359 """
1361 assert isinstance(hash(SpectralShape(0, 10, 0.1)), int)
1363 def test__iter__(self) -> None:
1364 """
1365 Test :meth:`colour.colorimetry.spectrum.SpectralShape.__iter__`
1366 method.
1367 """
1369 np.testing.assert_array_equal(
1370 list(SpectralShape(0, 10, 0.1)),
1371 np.arange(0, 10 + 0.1, 0.1),
1372 )
1374 def test__contains__(self) -> None:
1375 """
1376 Test :meth:`colour.colorimetry.spectrum.SpectralShape.__contains__`
1377 method.
1378 """
1380 assert 360.1 in SpectralShape(360, 830, 0.1)
1382 assert 360.11 not in SpectralShape(360, 830, 0.1)
1384 assert np.array([0.5, 0.6]) in SpectralShape(0, 10, 0.1)
1386 assert np.array([0.5, 0.61]) not in SpectralShape(0, 10, 0.1)
1388 def test__len__(self) -> None:
1389 """
1390 Test :meth:`colour.colorimetry.spectrum.SpectralShape.__len__`
1391 method.
1392 """
1394 assert len(SpectralShape(0, 10, 0.1)) == 101
1396 def test__eq__(self) -> None:
1397 """
1398 Test :meth:`colour.colorimetry.spectrum.SpectralShape.__eq__`
1399 method.
1400 """
1402 assert SpectralShape(0, 10, 0.1) == SpectralShape(0, 10, 0.1)
1403 assert SpectralShape(0, 10, 0.1) != ()
1405 def test__ne__(self) -> None:
1406 """
1407 Test :meth:`colour.colorimetry.spectrum.SpectralShape.__ne__`
1408 method.
1409 """
1411 assert SpectralShape(0, 10, 0.1) != SpectralShape(1, 10, 0.1)
1413 def test_range(self) -> None:
1414 """Test :func:`colour.colorimetry.spectrum.SpectralShape.range` method."""
1416 np.testing.assert_array_equal(
1417 list(SpectralShape(0, 10, 0.1)),
1418 np.arange(0, 10 + 0.1, 0.1),
1419 )
1422class TestSpectralDistribution:
1423 """
1424 Define :class:`colour.colorimetry.spectrum.SpectralDistribution`
1425 class unit tests methods.
1426 """
1428 def setup_method(self) -> None:
1429 """Initialise the common tests attributes."""
1431 self._sd = SpectralDistribution(DATA_SAMPLE, name="Sample")
1433 self._non_uniform_sd = SpectralDistribution(
1434 DATA_SAMPLE_NON_UNIFORM,
1435 name="Non Uniform Sample",
1436 display_name="Display Non Uniform Sample",
1437 )
1439 self._phi = (1 + np.sqrt(5)) / 2
1441 def test_required_attributes(self) -> None:
1442 """Test the presence of required attributes."""
1444 required_attributes = (
1445 "display_name",
1446 "wavelengths",
1447 "values",
1448 "shape",
1449 )
1451 for attribute in required_attributes:
1452 assert attribute in dir(SpectralDistribution)
1454 def test_required_methods(self) -> None:
1455 """Test the presence of required methods."""
1457 required_methods = (
1458 "__init__",
1459 "interpolate",
1460 "extrapolate",
1461 "align",
1462 "trim",
1463 "normalise",
1464 )
1466 for method in required_methods:
1467 assert method in dir(SpectralDistribution)
1469 def test_pickling(self) -> None:
1470 """
1471 Test whether the :class:`colour.colorimetry.spectrum.\
1472SpectralDistribution` class can be pickled.
1473 """
1475 data = pickle.dumps(self._sd)
1476 data = pickle.loads(data) # noqa: S301
1477 assert self._sd == data
1479 def test_display_name(self) -> None:
1480 """
1481 Test :attr:`colour.colorimetry.spectrum.SpectralDistribution.display_name`
1482 property.
1483 """
1485 assert self._sd.display_name == "Sample"
1486 assert self._non_uniform_sd.display_name == "Display Non Uniform Sample"
1488 def test_wavelengths(self) -> None:
1489 """
1490 Test :attr:`colour.colorimetry.spectrum.SpectralDistribution.wavelengths`
1491 property.
1492 """
1494 np.testing.assert_array_equal(self._sd.wavelengths, self._sd.domain)
1496 sd = self._sd.copy()
1497 sd.wavelengths = sd.wavelengths + 10
1498 np.testing.assert_array_equal(sd.wavelengths, sd.domain)
1500 def test_values(self) -> None:
1501 """
1502 Test :attr:`colour.colorimetry.spectrum.SpectralDistribution.values`
1503 property.
1504 """
1506 np.testing.assert_array_equal(self._sd.values, self._sd.range)
1508 sd = self._sd.copy()
1509 sd.values = sd.values + 10
1510 np.testing.assert_array_equal(sd.values, sd.range)
1512 def test_shape(self) -> None:
1513 """
1514 Test :attr:`colour.colorimetry.spectrum.SpectralDistribution.shape`
1515 property.
1516 """
1518 assert self._sd.shape == SpectralShape(340, 820, 20)
1520 def test__init__(self) -> None:
1521 """
1522 Test :meth:`colour.colorimetry.spectrum.SpectralDistribution.__init__`
1523 method.
1524 """
1526 np.testing.assert_allclose(
1527 SpectralDistribution(DATA_SAMPLE).wavelengths,
1528 SpectralDistribution(
1529 DATA_SAMPLE.values(),
1530 SpectralShape(340, 820, 20),
1531 ).wavelengths,
1532 atol=TOLERANCE_ABSOLUTE_TESTS,
1533 )
1535 def test_interpolate(self) -> None:
1536 """
1537 Test :func:`colour.colorimetry.spectrum.\
1538SpectralDistribution.interpolate` method.
1539 """
1541 if not is_scipy_installed(): # pragma: no cover
1542 return
1544 shape = SpectralShape(self._sd.shape.start, self._sd.shape.end, 1)
1545 sd = reshape_sd(self._sd, shape, "Interpolate")
1546 np.testing.assert_allclose(
1547 sd.values, DATA_SAMPLE_INTERPOLATED, atol=TOLERANCE_ABSOLUTE_TESTS
1548 )
1549 assert sd.shape == shape
1551 shape = SpectralShape(
1552 self._non_uniform_sd.shape.start,
1553 self._non_uniform_sd.shape.end,
1554 1,
1555 )
1556 sd = reshape_sd(
1557 self._non_uniform_sd,
1558 shape,
1559 "Interpolate",
1560 )
1561 np.testing.assert_allclose(
1562 sd.values,
1563 DATA_SAMPLE_INTERPOLATED_NON_UNIFORM,
1564 atol=TOLERANCE_ABSOLUTE_TESTS,
1565 )
1566 assert sd.shape == SpectralShape(
1567 self._non_uniform_sd.shape.start,
1568 self._non_uniform_sd.shape.end,
1569 1,
1570 )
1572 def test_extrapolate(self) -> None:
1573 """
1574 Test :func:`colour.colorimetry.spectrum.\
1575SpectralDistribution.extrapolate` method.
1576 """
1578 if not is_scipy_installed(): # pragma: no cover
1579 return
1581 data = dict(zip(range(25, 35), [0] * 5 + [1] * 5, strict=True))
1582 sd = SpectralDistribution(data)
1583 sd.extrapolate(SpectralShape(10, 50, 5))
1585 np.testing.assert_allclose(sd[10], 0, atol=TOLERANCE_ABSOLUTE_TESTS)
1586 np.testing.assert_allclose(sd[50], 1, atol=TOLERANCE_ABSOLUTE_TESTS)
1588 sd = SpectralDistribution(np.linspace(0, 1, 10), np.linspace(25, 35, 10))
1589 shape = SpectralShape(10, 50, 10)
1590 sd.extrapolate(
1591 shape,
1592 extrapolator_kwargs={
1593 "method": "Linear",
1594 "left": None,
1595 "right": None,
1596 },
1597 )
1599 np.testing.assert_allclose(
1600 sd[10], -1.5000000000000004, atol=TOLERANCE_ABSOLUTE_TESTS
1601 )
1602 np.testing.assert_allclose(
1603 sd[50], 2.4999999999999964, atol=TOLERANCE_ABSOLUTE_TESTS
1604 )
1606 def test_align(self) -> None:
1607 """
1608 Test :func:`colour.colorimetry.spectrum.\
1609SpectralDistribution.align` method.
1610 """
1612 shape = SpectralShape(100, 900, 5)
1613 assert self._sd.copy().align(shape).shape == shape
1615 shape = SpectralShape(600, 650, 1)
1616 assert self._sd.copy().align(shape).shape == shape
1618 def test_trim(self) -> None:
1619 """
1620 Test :func:`colour.colorimetry.spectrum.\
1621SpectralDistribution.trim` method.
1622 """
1624 shape = SpectralShape(400, 700, 20)
1625 assert self._sd.copy().trim(shape).shape == shape
1627 shape = SpectralShape(200, 900, 1)
1628 assert self._sd.copy().trim(shape).shape == self._sd.shape
1630 def test_normalise(self) -> None:
1631 """
1632 Test :func:`colour.colorimetry.spectrum.\
1633SpectralDistribution.normalise` method.
1634 """
1636 np.testing.assert_allclose(
1637 self._sd.copy().normalise(100).values,
1638 DATA_SAMPLE_NORMALISED,
1639 atol=TOLERANCE_ABSOLUTE_TESTS,
1640 )
1642 def test_callback_on_domain_changed(self) -> None:
1643 """
1644 Test :class:`colour.colorimetry.spectrum.\
1645SpectralDistribution` *on_domain_changed* callback.
1646 """
1648 sd = self._sd.copy()
1649 assert sd.shape == SpectralShape(340, 820, 20)
1650 sd[840] = 0
1651 assert sd.shape == SpectralShape(340, 840, 20)
1654class TestMultiSpectralDistributions:
1655 """
1656 Define :class:`colour.colorimetry.spectrum.MultiSpectralDistributions`
1657 class unit tests methods.
1658 """
1660 def setup_method(self) -> None:
1661 """Initialise the common tests attributes."""
1663 self._labels = ("x_bar", "y_bar", "z_bar")
1664 self._display_labels = (
1665 "Display x_bar",
1666 "Display y_bar",
1667 "Display z_bar",
1668 )
1670 self._msds = MultiSpectralDistributions(
1671 DATA_STANDARD_OBSERVER_2_DEGREE_CIE1931,
1672 name="Observer",
1673 labels=self._labels,
1674 )
1676 sd = SpectralDistribution(DATA_SAMPLE)
1677 domain = sd.domain
1678 range_ = tstack([sd.values, sd.values, sd.values])
1679 self._sample_msds = MultiSpectralDistributions(
1680 range_,
1681 domain,
1682 name="Sample Observer",
1683 labels=self._labels,
1684 )
1686 sd = SpectralDistribution(DATA_SAMPLE_NON_UNIFORM)
1687 domain = sd.domain
1688 range_ = tstack([sd.values, sd.values, sd.values])
1689 self._non_uniform_sample_msds = MultiSpectralDistributions(
1690 range_,
1691 domain,
1692 name="Non Uniform Sample Observer",
1693 display_name="Display Non Uniform Sample Observer",
1694 labels=self._labels,
1695 display_labels=("Display x_bar", "Display y_bar", "Display z_bar"),
1696 )
1698 self._phi = (1 + np.sqrt(5)) / 2
1700 def test_required_attributes(self) -> None:
1701 """Test the presence of required attributes."""
1703 required_attributes = (
1704 "display_name",
1705 "display_labels",
1706 "wavelengths",
1707 "values",
1708 "shape",
1709 )
1711 for attribute in required_attributes:
1712 assert attribute in dir(MultiSpectralDistributions)
1714 def test_required_methods(self) -> None:
1715 """Test the presence of required methods."""
1717 required_methods = (
1718 "__init__",
1719 "interpolate",
1720 "extrapolate",
1721 "align",
1722 "trim",
1723 "normalise",
1724 "to_sds",
1725 )
1727 for method in required_methods:
1728 assert method in dir(MultiSpectralDistributions)
1730 def test_pickling(self) -> None:
1731 """
1732 Test whether the :class:`colour.colorimetry.spectrum.\
1733MultiSpectralDistributions` class can be pickled.
1734 """
1736 data = pickle.dumps(self._msds)
1737 data = pickle.loads(data) # noqa: S301
1738 assert self._msds == data
1740 def test_display_name(self) -> None:
1741 """
1742 Test :attr:`colour.colorimetry.spectrum.MultiSpectralDistributions.display_name`
1743 property.
1744 """
1746 assert self._sample_msds.display_name == "Sample Observer"
1747 assert (
1748 self._non_uniform_sample_msds.display_name
1749 == "Display Non Uniform Sample Observer"
1750 )
1752 def test_wavelengths(self) -> None:
1753 """
1754 Test :attr:`colour.colorimetry.spectrum.MultiSpectralDistributions.wavelengths`
1755 property.
1756 """
1758 np.testing.assert_array_equal(self._msds.wavelengths, self._msds.domain)
1760 msds = self._msds.copy()
1761 msds.wavelengths = msds.wavelengths + 10
1762 np.testing.assert_array_equal(msds.wavelengths, msds.domain)
1764 def test_values(self) -> None:
1765 """
1766 Test :attr:`colour.colorimetry.spectrum.MultiSpectralDistributions.values`
1767 property.
1768 """
1770 np.testing.assert_array_equal(self._msds.values, self._msds.range)
1772 msds = self._msds.copy()
1773 msds.values = msds.values + 10
1774 np.testing.assert_array_equal(msds.values, msds.range)
1776 def test_display_labels(self) -> None:
1777 """
1778 Test :attr:`colour.colorimetry.spectrum.MultiSpectralDistributions.\
1779display_labels` property.
1780 """
1782 assert tuple(self._sample_msds.display_labels) == self._labels
1783 assert tuple(self._non_uniform_sample_msds.display_labels) == (
1784 "Display x_bar",
1785 "Display y_bar",
1786 "Display z_bar",
1787 )
1789 def test_shape(self) -> None:
1790 """
1791 Test :attr:`colour.colorimetry.spectrum.MultiSpectralDistributions.shape`
1792 property.
1793 """
1795 assert self._msds.shape == SpectralShape(380, 780, 5)
1797 def test__init__(self) -> None:
1798 """
1799 Test :func:`colour.colorimetry.spectrum.\
1800MultiSpectralDistributions.__init__` method.
1801 """
1803 np.testing.assert_allclose(
1804 MultiSpectralDistributions(DATA_CMFS).wavelengths,
1805 MultiSpectralDistributions(
1806 DATA_CMFS.values(),
1807 SpectralShape(380, 780, 5),
1808 ).wavelengths,
1809 atol=TOLERANCE_ABSOLUTE_TESTS,
1810 )
1812 def test_interpolate(self) -> None:
1813 """
1814 Test :func:`colour.colorimetry.spectrum.\
1815MultiSpectralDistributions.interpolate` method.
1816 """
1818 if not is_scipy_installed(): # pragma: no cover
1819 return
1821 shape = SpectralShape(
1822 self._sample_msds.shape.start, self._sample_msds.shape.end, 1
1823 )
1824 msds = reshape_msds(self._sample_msds, shape, "Interpolate")
1825 for signal in msds.signals.values():
1826 np.testing.assert_allclose(
1827 signal.values, # pyright: ignore
1828 DATA_SAMPLE_INTERPOLATED,
1829 atol=TOLERANCE_ABSOLUTE_TESTS,
1830 )
1831 assert msds.shape == shape
1833 shape = SpectralShape(
1834 self._non_uniform_sample_msds.shape.start,
1835 self._non_uniform_sample_msds.shape.end,
1836 1,
1837 )
1838 msds = reshape_msds(
1839 self._non_uniform_sample_msds,
1840 shape,
1841 "Interpolate",
1842 )
1843 for signal in msds.signals.values():
1844 np.testing.assert_allclose(
1845 signal.values, # pyright: ignore
1846 DATA_SAMPLE_INTERPOLATED_NON_UNIFORM,
1847 atol=TOLERANCE_ABSOLUTE_TESTS,
1848 )
1849 assert msds.shape == SpectralShape(
1850 self._non_uniform_sample_msds.shape.start,
1851 self._non_uniform_sample_msds.shape.end,
1852 1,
1853 )
1855 def test_extrapolate(self) -> None:
1856 """
1857 Test :func:`colour.colorimetry.spectrum.\
1858MultiSpectralDistributions.extrapolate` method.
1859 """
1861 if not is_scipy_installed(): # pragma: no cover
1862 return
1864 data = dict(zip(range(25, 35), tstack([[0] * 5 + [1] * 5] * 3), strict=True))
1865 msds = MultiSpectralDistributions(data)
1866 msds.extrapolate(SpectralShape(10, 50, 5))
1868 np.testing.assert_allclose(
1869 msds[10], np.array([0.0, 0.0, 0.0]), atol=TOLERANCE_ABSOLUTE_TESTS
1870 )
1871 np.testing.assert_allclose(
1872 msds[50], np.array([1.0, 1.0, 1.0]), atol=TOLERANCE_ABSOLUTE_TESTS
1873 )
1875 msds = MultiSpectralDistributions(
1876 tstack([np.linspace(0, 1, 10)] * 3), np.linspace(25, 35, 10)
1877 )
1878 msds.extrapolate(
1879 SpectralShape(10, 50, 10),
1880 extrapolator_kwargs={
1881 "method": "Linear",
1882 "left": None,
1883 "right": None,
1884 },
1885 )
1886 np.testing.assert_allclose(
1887 msds[10],
1888 np.array([-1.5, -1.5, -1.5]),
1889 atol=TOLERANCE_ABSOLUTE_TESTS,
1890 )
1891 np.testing.assert_allclose(
1892 msds[50], np.array([2.5, 2.5, 2.5]), atol=TOLERANCE_ABSOLUTE_TESTS
1893 )
1895 def test_align(self) -> None:
1896 """
1897 Test :func:`colour.colorimetry.spectrum.\
1898MultiSpectralDistributions.align` method.
1899 """
1901 msds = self._sample_msds.copy()
1903 shape = SpectralShape(100, 900, 5)
1904 assert msds.align(shape).shape == shape
1906 shape = SpectralShape(600, 650, 1)
1907 assert msds.align(shape).shape == shape
1909 def test_trim(self) -> None:
1910 """
1911 Test :func:`colour.colorimetry.spectrum.\
1912MultiSpectralDistributions.trim` method.
1913 """
1915 shape = SpectralShape(400, 700, 5)
1916 assert self._msds.copy().trim(shape).shape == shape
1918 shape = SpectralShape(200, 900, 1)
1919 assert self._msds.copy().trim(shape).shape == self._msds.shape
1921 def test_normalise(self) -> None:
1922 """
1923 Test :func:`colour.colorimetry.spectrum.
1924 MultiSpectralDistributions.normalise` method.
1925 """
1927 np.testing.assert_allclose(
1928 self._sample_msds.copy().normalise(100).values,
1929 tstack([DATA_SAMPLE_NORMALISED] * 3),
1930 atol=TOLERANCE_ABSOLUTE_TESTS,
1931 )
1933 def test_to_sds(self) -> None:
1934 """
1935 Test :func:`colour.colorimetry.spectrum.\
1936MultiSpectralDistributions.to_sds` method.
1937 """
1939 if not is_scipy_installed(): # pragma: no cover
1940 return
1942 sds = self._non_uniform_sample_msds.to_sds()
1943 assert len(sds) == 3
1945 for i, sd in enumerate(sds):
1946 assert sd.name == self._labels[i]
1947 assert sd.display_name == self._display_labels[i]
1949 def test_callback_on_domain_changed(self) -> None:
1950 """
1951 Test underlying :class:`colour.colorimetry.spectrum.\
1952SpectralDistribution` *on_domain_changed* callback when used with
1953 :class:`colour.colorimetry.spectrum.MultiSpectralDistributions` class.
1954 """
1956 msds = self._msds.copy()
1957 assert msds.shape == SpectralShape(380, 780, 5)
1958 msds[785] = 0
1959 assert msds.shape == SpectralShape(380, 785, 5)
1962class TestReshapeSd:
1963 """
1964 Define :func:`colour.colorimetry.spectrum.reshape_sd` definition unit
1965 tests methods.
1966 """
1968 def test_reshape_sd(self) -> None:
1969 """Test :func:`colour.colorimetry.spectrum.reshape_sd` definition."""
1971 if not is_scipy_installed(): # pragma: no cover
1972 return
1974 sd = SpectralDistribution(DATA_SAMPLE_ABRIDGED)
1975 sd_reshaped = reshape_sd(sd)
1976 assert sd_reshaped == sd.copy().align(SPECTRAL_SHAPE_DEFAULT)
1977 assert reshape_sd(sd) == sd_reshaped
1979 shape = colour.SpectralShape(100, 900, 1)
1980 extrapolator_kwargs = {
1981 "method": "Constant",
1982 "left": 0.05,
1983 "right": 0.15,
1984 }
1985 sd_reshaped = reshape_sd(
1986 sd,
1987 shape,
1988 method="Extrapolate",
1989 extrapolator_kwargs=extrapolator_kwargs,
1990 )
1991 assert sd_reshaped == sd.copy().extrapolate(
1992 shape, extrapolator_kwargs=extrapolator_kwargs
1993 )
1995 shape = colour.SpectralShape(400, 700, 1)
1996 interpolator_kwargs = {"fill_value": 0}
1997 sd_reshaped = reshape_sd(
1998 sd,
1999 shape,
2000 method="Interpolate",
2001 interpolator=CubicSplineInterpolator,
2002 interpolator_kwargs=interpolator_kwargs,
2003 )
2004 assert sd_reshaped == sd.copy().interpolate(
2005 shape,
2006 interpolator=CubicSplineInterpolator,
2007 interpolator_kwargs=interpolator_kwargs,
2008 )
2010 sd = SpectralDistribution(DATA_SAMPLE)
2011 shape = colour.SpectralShape(500, 600, 1)
2012 sd_reshaped = reshape_sd(sd, shape, method="Trim")
2013 assert sd_reshaped == sd.copy().trim(shape)
2015 if is_caching_enabled():
2016 assert reshape_sd(sd, shape, method="Trim", copy=False) is sd_reshaped
2019class TestSdsAndMdsToSds:
2020 """
2021 Define :func:`colour.colorimetry.spectrum.sds_and_msds_to_sds` definition
2022 unit tests methods.
2023 """
2025 def test_sds_and_msds_to_sds(self) -> None:
2026 """
2027 Test :func:`colour.colorimetry.spectrum.sds_and_msds_to_sds`
2028 definition.
2029 """
2031 sd_1 = SpectralDistribution(DATA_SAMPLE_ABRIDGED)
2032 sd_2 = SpectralDistribution(DATA_SAMPLE_ABRIDGED)
2033 multi_sds_1 = MultiSpectralDistributions(DATA_MULTI_SAMPLE_ABRIDGED)
2034 multi_sds_2 = MultiSpectralDistributions(DATA_MULTI_SAMPLE_ABRIDGED)
2036 assert sds_and_msds_to_sds(sd_1) == [sd_1]
2037 assert (
2038 len(
2039 sds_and_msds_to_sds(
2040 [
2041 sd_1,
2042 sd_2,
2043 multi_sds_1,
2044 multi_sds_2,
2045 ]
2046 )
2047 )
2048 == 8
2049 )
2051 assert len(sds_and_msds_to_sds(multi_sds_1)) == 3
2054class TestSdsAndMsdsToMsds:
2055 """
2056 Define :func:`colour.colorimetry.spectrum.sds_and_msds_to_msds`
2057 definition unit tests methods.
2058 """
2060 def test_sds_and_msds_to_msds(self) -> None:
2061 """
2062 Test :func:`colour.colorimetry.spectrum.sds_and_msds_to_msds`
2063 definition.
2064 """
2066 sd_1 = SpectralDistribution(DATA_SAMPLE_ABRIDGED)
2067 sd_2 = SpectralDistribution(DATA_SAMPLE_ABRIDGED)
2068 multi_sds_1 = MultiSpectralDistributions(DATA_MULTI_SAMPLE_ABRIDGED)
2069 multi_sds_2 = MultiSpectralDistributions(DATA_MULTI_SAMPLE_ABRIDGED)
2071 assert len(sds_and_msds_to_msds(sd_1)) == 6
2073 assert sds_and_msds_to_msds(multi_sds_1) == multi_sds_1
2075 multi_sds_0 = sds_and_msds_to_msds([multi_sds_1])
2076 np.testing.assert_array_equal(multi_sds_0.range, multi_sds_1.range)
2077 assert sds_and_msds_to_msds([multi_sds_1]) == multi_sds_1
2079 shape = SpectralShape(500, 560, 10)
2080 assert (
2081 sds_and_msds_to_msds([sd_1, sd_2, multi_sds_1, multi_sds_2]).shape == shape
2082 )
2084 np.testing.assert_allclose(
2085 sds_and_msds_to_msds([sd_1, sd_2, multi_sds_1, multi_sds_2]).wavelengths,
2086 shape.wavelengths,
2087 atol=TOLERANCE_ABSOLUTE_TESTS,
2088 )
2090 np.testing.assert_allclose(
2091 sds_and_msds_to_msds([sd_1, sd_2, multi_sds_1, multi_sds_2]).values,
2092 tstack(
2093 [sd_1.align(shape).values, sd_2.align(shape).values]
2094 + [sd.values for sd in sds_and_msds_to_sds(multi_sds_1.align(shape))]
2095 + [sd.values for sd in sds_and_msds_to_sds(multi_sds_2.align(shape))]
2096 ),
2097 atol=TOLERANCE_ABSOLUTE_TESTS,
2098 )