Skip to content

Commit 8a82944

Browse files
Merge branch 'colour-science:develop' into feature/metamerism
2 parents 315c024 + 5bc353a commit 8a82944

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+546
-175
lines changed

colour/algebra/interpolation.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,31 @@
6464

6565
from __future__ import annotations
6666

67+
import sys
6768
import typing
6869
from functools import reduce
70+
from unittest.mock import MagicMock
6971

7072
import numpy as np
73+
74+
from colour.utilities.requirements import is_scipy_installed
75+
from colour.utilities.verbose import usage_warning
76+
77+
if not is_scipy_installed(): # pragma: no cover
78+
try:
79+
is_scipy_installed(raise_exception=True)
80+
except ImportError as error:
81+
usage_warning(str(error))
82+
83+
mock = MagicMock()
84+
mock.__name__ = ""
85+
86+
for module in (
87+
"scipy",
88+
"scipy.interpolate",
89+
):
90+
sys.modules[module] = mock
91+
7192
import scipy.interpolate
7293

7394
from colour.algebra import sdiv, sdiv_mode

colour/algebra/tests/test_extrapolation.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
PchipInterpolator,
1414
)
1515
from colour.constants import TOLERANCE_ABSOLUTE_TESTS
16-
from colour.utilities import ignore_numpy_errors
16+
from colour.utilities import ignore_numpy_errors, is_scipy_installed
1717

1818
__author__ = "Colour Developers"
1919
__copyright__ = "Copyright 2013 Colour Developers"
@@ -107,6 +107,9 @@ def test__call__(self) -> None:
107107
method.
108108
"""
109109

110+
if not is_scipy_installed(): # pragma: no cover
111+
return
112+
110113
extrapolator = Extrapolator(
111114
LinearInterpolator(np.array([5, 6, 7]), np.array([5, 6, 7]))
112115
)

colour/algebra/tests/test_interpolation.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
from colour.constants import TOLERANCE_ABSOLUTE_TESTS
3838
from colour.hints import NDArrayFloat, cast
3939
from colour.io import LUT3D, read_LUT
40-
from colour.utilities import ignore_numpy_errors
40+
from colour.utilities import ignore_numpy_errors, is_scipy_installed
4141

4242
__author__ = "Colour Developers"
4343
__copyright__ = "Copyright 2013 Colour Developers"
@@ -835,6 +835,9 @@ class TestKernelInterpolator:
835835
def test_required_attributes(self) -> None:
836836
"""Test the presence of required attributes."""
837837

838+
if not is_scipy_installed(): # pragma: no cover
839+
return
840+
838841
required_attributes = (
839842
"x",
840843
"y",
@@ -872,6 +875,9 @@ def test_y(self) -> None:
872875
property.
873876
"""
874877

878+
if not is_scipy_installed(): # pragma: no cover
879+
return
880+
875881
x = y = np.linspace(0, 1, 10)
876882
kernel_interpolator = KernelInterpolator(x, y)
877883

@@ -942,6 +948,9 @@ def test__call__(self) -> None:
942948
method.
943949
"""
944950

951+
if not is_scipy_installed(): # pragma: no cover
952+
return
953+
945954
x = np.arange(11, 26, 1)
946955
y = np.sin(x / len(x) * np.pi * 6) / (x / len(x)) + np.pi
947956
x_i = np.linspace(11, 25, 25)
@@ -1176,6 +1185,9 @@ class unit tests methods.
11761185
def test_required_attributes(self) -> None:
11771186
"""Test the presence of required attributes."""
11781187

1188+
if not is_scipy_installed(): # pragma: no cover
1189+
return
1190+
11791191
required_attributes = ()
11801192

11811193
for attribute in required_attributes: # pragma: no cover
@@ -1212,6 +1224,9 @@ class TestLinearInterpolator:
12121224
def test_required_attributes(self) -> None:
12131225
"""Test the presence of required attributes."""
12141226

1227+
if not is_scipy_installed(): # pragma: no cover
1228+
return
1229+
12151230
required_attributes = ("x", "y")
12161231

12171232
for attribute in required_attributes:
@@ -1240,6 +1255,9 @@ def test__call__(self) -> None:
12401255
method.
12411256
"""
12421257

1258+
if not is_scipy_installed(): # pragma: no cover
1259+
return
1260+
12431261
interval = 0.1
12441262
x = np.arange(len(DATA_POINTS_A))
12451263
linear_interpolator = LinearInterpolator(x, DATA_POINTS_A)
@@ -1300,6 +1318,9 @@ class TestSpragueInterpolator:
13001318
def test_required_attributes(self) -> None:
13011319
"""Test the presence of required attributes."""
13021320

1321+
if not is_scipy_installed(): # pragma: no cover
1322+
return
1323+
13031324
required_attributes = ("x", "y")
13041325

13051326
for attribute in required_attributes:
@@ -1328,6 +1349,9 @@ def test__call__(self) -> None:
13281349
method.
13291350
"""
13301351

1352+
if not is_scipy_installed(): # pragma: no cover
1353+
return
1354+
13311355
interval = 0.1
13321356
x = np.arange(len(DATA_POINTS_A))
13331357
sprague_interpolator = SpragueInterpolator(x, DATA_POINTS_A)
@@ -1396,6 +1420,9 @@ def test__call__(self) -> None:
13961420
and is assumed to be unit tested thoroughly.
13971421
"""
13981422

1423+
if not is_scipy_installed(): # pragma: no cover
1424+
return
1425+
13991426
np.testing.assert_allclose(
14001427
CubicSplineInterpolator(
14011428
np.linspace(0, 1, len(DATA_POINTS_A)), DATA_POINTS_A
@@ -1414,6 +1441,9 @@ class TestPchipInterpolator:
14141441
def test_required_attributes(self) -> None:
14151442
"""Test the presence of required attributes."""
14161443

1444+
if not is_scipy_installed(): # pragma: no cover
1445+
return
1446+
14171447
required_attributes = ("x", "y")
14181448

14191449
for attribute in required_attributes:
@@ -1432,6 +1462,9 @@ def test_y(self) -> None:
14321462
Test :attr:`colour.algebra.interpolation.PchipInterpolator.y` property.
14331463
"""
14341464

1465+
if not is_scipy_installed(): # pragma: no cover
1466+
return
1467+
14351468
interpolator = PchipInterpolator(np.linspace(0, 1, 10), np.linspace(0, 1, 10))
14361469

14371470
interpolator.y = np.linspace(0, 1, 10)
@@ -1448,6 +1481,9 @@ class TestNullInterpolator:
14481481
def test_required_attributes(self) -> None:
14491482
"""Test the presence of required attributes."""
14501483

1484+
if not is_scipy_installed(): # pragma: no cover
1485+
return
1486+
14511487
required_attributes = ("x", "y")
14521488

14531489
for attribute in required_attributes:
@@ -1478,6 +1514,9 @@ def test_y(self) -> None:
14781514
property.
14791515
"""
14801516

1517+
if not is_scipy_installed(): # pragma: no cover
1518+
return
1519+
14811520
x = y = np.linspace(0, 1, 10)
14821521
null_interpolator = NullInterpolator(x, y)
14831522

@@ -1531,6 +1570,9 @@ def test__call__(self) -> None:
15311570
method.
15321571
"""
15331572

1573+
if not is_scipy_installed(): # pragma: no cover
1574+
return
1575+
15341576
x = np.arange(len(DATA_POINTS_A))
15351577
null_interpolator = NullInterpolator(x, DATA_POINTS_A)
15361578
np.testing.assert_allclose(

colour/characterisation/aces_it.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
import typing
6161

6262
import numpy as np
63-
from scipy.optimize import minimize
6463

6564
from colour.adaptation import matrix_chromatic_adaptation_VonKries
6665
from colour.algebra import euclidean_distance, vecmul
@@ -114,6 +113,7 @@
114113
as_float_scalar,
115114
from_range_1,
116115
optional,
116+
required,
117117
runtime_warning,
118118
tsplit,
119119
zeros,
@@ -1000,6 +1000,7 @@ def matrix_idt(
10001000
) -> Tuple[NDArrayFloat, NDArrayFloat, NDArrayFloat, NDArrayFloat]: ...
10011001

10021002

1003+
@required("SciPy")
10031004
def matrix_idt(
10041005
sensitivities: RGB_CameraSensitivities,
10051006
illuminant: SpectralDistribution,
@@ -1107,6 +1108,8 @@ def matrix_idt(
11071108
array([ 2.3414154..., 1. , 1.5163375...])
11081109
"""
11091110

1111+
from scipy.optimize import minimize # noqa: PLC0415
1112+
11101113
training_data = optional(training_data, read_training_data_rawtoaces_v1())
11111114

11121115
cmfs, illuminant = handle_spectral_arguments(

colour/characterisation/tests/test_aces_it.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
)
4242
from colour.constants import TOLERANCE_ABSOLUTE_TESTS
4343
from colour.io import read_sds_from_csv_file
44-
from colour.utilities import domain_range_scale
44+
from colour.utilities import domain_range_scale, is_scipy_installed
4545

4646
__author__ = "Colour Developers"
4747
__copyright__ = "Copyright 2013 Colour Developers"
@@ -981,6 +981,9 @@ def test_matrix_idt(self) -> None:
981981
Test :func:`colour.characterisation.aces_it.matrix_idt` definition.
982982
"""
983983

984+
if not is_scipy_installed(): # pragma: no cover
985+
return
986+
984987
# The *RAW to ACES* v1 matrix for the same camera and optimized by
985988
# `Ceres Solver <http://ceres-solver.org>`__ is as follows:
986989
#
@@ -1196,6 +1199,9 @@ def test_camera_RGB_to_ACES2065_1(self) -> None:
11961199
definition.
11971200
"""
11981201

1202+
if not is_scipy_installed(): # pragma: no cover
1203+
return
1204+
11991205
B, b = matrix_idt(MSDS_CANON_EOS_5DMARK_II, SDS_ILLUMINANTS["D55"]) # pyright: ignore
12001206
np.testing.assert_allclose(
12011207
camera_RGB_to_ACES2065_1(np.array([0.1, 0.2, 0.3]), B, b),

colour/colorimetry/dominant.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import typing
2727

2828
import numpy as np
29-
import scipy.spatial.distance
3029

3130
from colour.algebra import euclidean_distance, sdiv, sdiv_mode
3231
from colour.colorimetry import MultiSpectralDistributions, handle_spectral_arguments
@@ -36,7 +35,7 @@
3635
from colour.hints import ArrayLike, NDArrayFloat, NDArrayInt, Tuple
3736

3837
from colour.models import XYZ_to_xy
39-
from colour.utilities import as_float_array
38+
from colour.utilities import as_float_array, required
4039

4140
__author__ = "Colour Developers"
4241
__copyright__ = "Copyright 2013 Colour Developers"
@@ -54,6 +53,7 @@
5453
]
5554

5655

56+
@required("SciPy")
5757
def closest_spectral_locus_wavelength(
5858
xy: ArrayLike, xy_n: ArrayLike, xy_s: ArrayLike, inverse: bool = False
5959
) -> Tuple[NDArrayInt, NDArrayFloat]:
@@ -100,6 +100,8 @@ def closest_spectral_locus_wavelength(
100100
[ 0.6835474... 0.3162840...]
101101
"""
102102

103+
import scipy.spatial.distance # noqa: PLC0415
104+
103105
xy = as_float_array(xy)
104106
xy_n = np.resize(xy_n, xy.shape)
105107
xy_s = as_float_array(xy_s)

0 commit comments

Comments
 (0)