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

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

2

3 from __future__ import annotations

4

5 from itertools import product

6

7 import numpy as np

8

9 from colour.constants import TOLERANCE_ABSOLUTE_TESTS

10 from colour.models import IPT_hue_angle, IPT_to_XYZ, XYZ_to_IPT

11 from colour.utilities import domain_range_scale, ignore_numpy_errors

12

13 __author__ = "Colour Developers"

14 __copyright__ = "Copyright 2013 Colour Developers"

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

16 __maintainer__ = "Colour Developers"

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

18 __status__ = "Production"

19

20 __all__ = [

21 "TestXYZ_to_IPT",

22 "TestIPT_to_XYZ",

23 "TestIPTHueAngle",

24]

25

26

27 class TestXYZ_to_IPT:

28 """Define :func:`colour.models.ipt.XYZ_to_IPT` definition unit tests methods."""

29

30 def test_XYZ_to_IPT(self) -> None:

31 """Test :func:`colour.models.ipt.XYZ_to_IPT` definition."""

32

33 np.testing.assert_allclose(

34 XYZ_to_IPT(np.array([0.20654008, 0.12197225, 0.05136952])),

35 np.array([0.38426191, 0.38487306, 0.18886838]),

36 atol=TOLERANCE_ABSOLUTE_TESTS,

37 )

38

39 np.testing.assert_allclose(

40 XYZ_to_IPT(np.array([0.14222010, 0.23042768, 0.10495772])),

41 np.array([0.49437481, -0.19251742, 0.18080304]),

42 atol=TOLERANCE_ABSOLUTE_TESTS,

43 )

44

45 np.testing.assert_allclose(

46 XYZ_to_IPT(np.array([0.07818780, 0.06157201, 0.28099326])),

47 np.array([0.35167774, -0.07525627, -0.30921279]),

48 atol=TOLERANCE_ABSOLUTE_TESTS,

49 )

50

51 def test_n_dimensional_XYZ_to_IPT(self) -> None:

52 """

53 Test :func:`colour.models.ipt.XYZ_to_IPT` definition n-dimensional

54 support.

55 """

56

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

58 IPT = XYZ_to_IPT(XYZ)

59

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

61 IPT = np.tile(IPT, (6, 1))

62 np.testing.assert_allclose(XYZ_to_IPT(XYZ), IPT, atol=TOLERANCE_ABSOLUTE_TESTS)

63

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

65 IPT = np.reshape(IPT, (2, 3, 3))

66 np.testing.assert_allclose(XYZ_to_IPT(XYZ), IPT, atol=TOLERANCE_ABSOLUTE_TESTS)

67

68 def test_domain_range_scale_XYZ_to_IPT(self) -> None:

69 """

70 Test :func:`colour.models.ipt.XYZ_to_IPT` definition domain and

71 range scale support.

72 """

73

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

75 IPT = XYZ_to_IPT(XYZ)

76

77 d_r = (("reference", 1), ("1", 1), ("100", 100))

78 for scale, factor in d_r:

79 with domain_range_scale(scale):

80 np.testing.assert_allclose(

81 XYZ_to_IPT(XYZ * factor),

82 IPT * factor,

83 atol=TOLERANCE_ABSOLUTE_TESTS,

84 )

85

86 @ignore_numpy_errors

87 def test_nan_XYZ_to_IPT(self) -> None:

88 """Test :func:`colour.models.ipt.XYZ_to_IPT` definition nan support."""

89

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

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

92 XYZ_to_IPT(cases)

93

94

95 class TestIPT_to_XYZ:

96 """

97 Define :func:`colour.models.ipt.IPT_to_XYZ` definition unit tests

98 methods.

99 """

100

101 def test_IPT_to_XYZ(self) -> None:

102 """Test :func:`colour.models.ipt.IPT_to_XYZ` definition."""

103

104 np.testing.assert_allclose(

105 IPT_to_XYZ(np.array([0.38426191, 0.38487306, 0.18886838])),

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

107 atol=TOLERANCE_ABSOLUTE_TESTS,

108 )

109

110 np.testing.assert_allclose(

111 IPT_to_XYZ(np.array([0.49437481, -0.19251742, 0.18080304])),

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

113 atol=TOLERANCE_ABSOLUTE_TESTS,

114 )

115

116 np.testing.assert_allclose(

117 IPT_to_XYZ(np.array([0.35167774, -0.07525627, -0.30921279])),

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

119 atol=TOLERANCE_ABSOLUTE_TESTS,

120 )

121

122 def test_n_dimensional_IPT_to_XYZ(self) -> None:

123 """

124 Test :func:`colour.models.ipt.IPT_to_XYZ` definition n-dimensional

125 support.

126 """

127

128 IPT = np.array([0.38426191, 0.38487306, 0.18886838])

129 XYZ = IPT_to_XYZ(IPT)

130

131 IPT = np.tile(IPT, (6, 1))

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

133 np.testing.assert_allclose(IPT_to_XYZ(IPT), XYZ, atol=TOLERANCE_ABSOLUTE_TESTS)

134

135 IPT = np.reshape(IPT, (2, 3, 3))

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

137 np.testing.assert_allclose(IPT_to_XYZ(IPT), XYZ, atol=TOLERANCE_ABSOLUTE_TESTS)

138

139 def test_domain_range_scale_IPT_to_XYZ(self) -> None:

140 """

141 Test :func:`colour.models.ipt.IPT_to_XYZ` definition domain and

142 range scale support.

143 """

144

145 IPT = np.array([0.38426191, 0.38487306, 0.18886838])

146 XYZ = IPT_to_XYZ(IPT)

147

148 d_r = (("reference", 1), ("1", 1), ("100", 100))

149 for scale, factor in d_r:

150 with domain_range_scale(scale):

151 np.testing.assert_allclose(

152 IPT_to_XYZ(IPT * factor),

153 XYZ * factor,

154 atol=TOLERANCE_ABSOLUTE_TESTS,

155 )

156

157 @ignore_numpy_errors

158 def test_nan_IPT_to_XYZ(self) -> None:

159 """Test :func:`colour.models.ipt.IPT_to_XYZ` definition nan support."""

160

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

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

163 IPT_to_XYZ(cases)

164

165

166 class TestIPTHueAngle:

167 """

168 Define :func:`colour.models.ipt.IPT_hue_angle` definition unit tests

169 methods.

170 """

171

172 def test_IPT_hue_angle(self) -> None:

173 """Test :func:`colour.models.ipt.IPT_hue_angle` definition."""

174

175 np.testing.assert_allclose(

176 IPT_hue_angle(np.array([0.38426191, 0.38487306, 0.18886838])),

177 26.138526939899490,

178 atol=TOLERANCE_ABSOLUTE_TESTS,

179 )

180

181 np.testing.assert_allclose(

182 IPT_hue_angle(np.array([0.49437481, -0.19251742, 0.18080304])),

183 136.797287973958500,

184 atol=TOLERANCE_ABSOLUTE_TESTS,

185 )

186

187 np.testing.assert_allclose(

188 IPT_hue_angle(np.array([0.35167774, -0.07525627, -0.30921279])),

189 256.321284526533300,

190 atol=TOLERANCE_ABSOLUTE_TESTS,

191 )

192

193 def test_n_dimensional_IPT_hue_angle(self) -> None:

194 """

195 Test :func:`colour.models.ipt.IPT_hue_angle` definition n-dimensional

196 support.

197 """

198

199 IPT = np.array([0.38426191, 0.38487306, 0.18886838])

200 hue = IPT_hue_angle(IPT)

201

202 IPT = np.tile(IPT, (6, 1))

203 hue = np.tile(hue, 6)

204 np.testing.assert_allclose(

205 IPT_hue_angle(IPT), hue, atol=TOLERANCE_ABSOLUTE_TESTS

206 )

207

208 IPT = np.reshape(IPT, (2, 3, 3))

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

210 np.testing.assert_allclose(

211 IPT_hue_angle(IPT), hue, atol=TOLERANCE_ABSOLUTE_TESTS

212 )

213

214 def test_domain_range_scale_IPT_hue_angle(self) -> None:

215 """

216 Test :func:`colour.models.ipt.IPT_hue_angle` definition domain and

217 range scale support.

218 """

219

220 IPT = np.array([0.38426191, 0.38487306, 0.18886838])

221 hue = IPT_hue_angle(IPT)

222

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

224 for scale, factor_a, factor_b in d_r:

225 with domain_range_scale(scale):

226 np.testing.assert_allclose(

227 IPT_hue_angle(IPT * factor_a),

228 hue * factor_b,

229 atol=TOLERANCE_ABSOLUTE_TESTS,

230 )

231

232 @ignore_numpy_errors

233 def test_nan_IPT_hue_angle(self) -> None:

234 """Test :func:`colour.models.ipt.IPT_hue_angle` definition nan support."""

235

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

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

238 IPT_hue_angle(cases)