Coverage for appearance/tests/test_atd95.py: 100%

1"""Define the unit tests for the :mod:`colour.appearance.atd95` module."""

2

3 from __future__ import annotations

4

5 from itertools import product

6

7 import numpy as np

8

9 from colour.appearance import XYZ_to_ATD95

10 from colour.constants import TOLERANCE_ABSOLUTE_TESTS

11 from colour.utilities import as_float_array, 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_ATD95",

22]

23

24

25 class TestXYZ_to_ATD95:

26 """

27 Define :func:`colour.appearance.atd95.XYZ_to_ATD95` definition unit

28 tests methods.

29 """

30

31 def test_XYZ_to_ATD95(self) -> None:

32 """

33 Test :func:`colour.appearance.atd95.XYZ_to_ATD95` definition.

34

35 Notes

36 -----

37 - The test values have been generated from data of the following file

38 by *Fairchild (2013)*:

39 http://rit-mcsl.org/fairchild//files/AppModEx.xls

40 """

41

42 XYZ = np.array([19.01, 20.00, 21.78])

43 XYZ_0 = np.array([95.05, 100.00, 108.88])

44 Y_02 = 318.31

45 K_1 = 0

46 K_2 = 50

47 sigma = 300

48 np.testing.assert_allclose(

49 XYZ_to_ATD95(XYZ, XYZ_0, Y_02, K_1, K_2, sigma),

50 np.array(

51 [

52 1.91,

53 1.206,

54 0.1814,

55 0.1788,

56 0.0287,

57 0.0108,

58 0.0192,

59 0.0205,

60 0.0108,

61 ]

62 ),

63 atol=0.01,

64 )

65

66 XYZ = np.array([57.06, 43.06, 31.96])

67 Y_02 = 31.83

68 np.testing.assert_allclose(

69 XYZ_to_ATD95(XYZ, XYZ_0, Y_02, K_1, K_2, sigma),

70 np.array(

71 [

72 63.96,

73 1.371,

74 0.2142,

75 0.2031,

76 0.068,

77 0.0005,

78 0.0224,

79 0.0308,

80 0.0005,

81 ]

82 ),

83 atol=0.01,

84 )

85

86 XYZ = np.array([3.53, 6.56, 2.14])

87 XYZ_0 = np.array([109.85, 100.00, 35.58])

88 Y_02 = 318.31

89 np.testing.assert_allclose(

90 XYZ_to_ATD95(XYZ, XYZ_0, Y_02, K_1, K_2, sigma),

91 np.array(

92 [

93 -0.31,

94 0.436,

95 0.1075,

96 0.1068,

97 -0.011,

98 0.0044,

99 0.0106,

100 -0.0014,

101 0.0044,

102 ]

103 ),

104 atol=0.01,

105 )

106

107 XYZ = np.array([19.01, 20.00, 21.78])

108 Y_02 = 31.83

109 np.testing.assert_allclose(

110 XYZ_to_ATD95(XYZ, XYZ_0, Y_02, K_1, K_2, sigma),

111 np.array(

112 [

113 0.79,

114 1.091,

115 0.1466,

116 0.146,

117 0.0007,

118 0.013,

119 0.0152,

120 0.0102,

121 0.013,

122 ]

123 ),

124 atol=0.01,

125 )

126

127 def test_n_dimensional_XYZ_to_ATD95(self) -> None:

128 """

129 Test :func:`colour.appearance.atd95.XYZ_to_ATD95` definition

130 n-dimensional support.

131 """

132

133 XYZ = np.array([19.01, 20.00, 21.78])

134 XYZ_0 = np.array([95.05, 100.00, 108.88])

135 Y_02 = 318.31

136 K_1 = 0

137 K_2 = 50

138 sigma = 300

139 specification = XYZ_to_ATD95(XYZ, XYZ_0, Y_02, K_1, K_2, sigma)

140

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

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

143 np.testing.assert_allclose(

144 XYZ_to_ATD95(XYZ, XYZ_0, Y_02, K_1, K_2, sigma),

145 specification,

146 atol=TOLERANCE_ABSOLUTE_TESTS,

147 )

148

149 XYZ_0 = np.tile(XYZ_0, (6, 1))

150 np.testing.assert_allclose(

151 XYZ_to_ATD95(XYZ, XYZ_0, Y_02, K_1, K_2, sigma),

152 specification,

153 atol=TOLERANCE_ABSOLUTE_TESTS,

154 )

155

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

157 XYZ_0 = np.reshape(XYZ_0, (2, 3, 3))

158 specification = np.reshape(specification, (2, 3, 9))

159 np.testing.assert_allclose(

160 XYZ_to_ATD95(XYZ, XYZ_0, Y_02, K_1, K_2, sigma),

161 specification,

162 atol=TOLERANCE_ABSOLUTE_TESTS,

163 )

164

165 @ignore_numpy_errors

166 def test_domain_range_scale_XYZ_to_ATD95(self) -> None:

167 """

168 Test :func:`colour.appearance.atd95.XYZ_to_ATD95` definition domain

169 and range scale support.

170 """

171

172 XYZ = np.array([19.01, 20.00, 21.78])

173 XYZ_0 = np.array([95.05, 100.00, 108.88])

174 Y_0 = 318.31

175 k_1 = 0.0

176 k_2 = 50.0

177 specification = XYZ_to_ATD95(XYZ, XYZ_0, Y_0, k_1, k_2)

178

179 d_r = (

180 ("reference", 1, 1),

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

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

183 )

184 for scale, factor_a, factor_b in d_r:

185 with domain_range_scale(scale):

186 np.testing.assert_allclose(

187 XYZ_to_ATD95(XYZ * factor_a, XYZ_0 * factor_a, Y_0, k_1, k_2),

188 as_float_array(specification) * factor_b,

189 atol=TOLERANCE_ABSOLUTE_TESTS,

190 )

191

192 @ignore_numpy_errors

193 def test_nan_XYZ_to_ATD95(self) -> None:

194 """

195 Test :func:`colour.appearance.atd95.XYZ_to_ATD95` definition nan

196 support.

197 """

198

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

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

201 XYZ_to_ATD95(cases, cases, cases[..., 0], cases[..., 0], cases[..., 0])