Coverage for temperature/mccamy1992.py: 53%

1"""

2 McCamy (1992) Correlated Colour Temperature

3===========================================

4

5 Define the *McCamy (1992)* correlated colour temperature :math:`T_{cp}`

6 computation objects.

7

8- :func:`colour.temperature.xy_to_CCT_McCamy1992`: Compute correlated

9 colour temperature :math:`T_{cp}` from specified *CIE xy* chromaticity

10 coordinates using the *McCamy (1992)* method.

11- :func:`colour.temperature.CCT_to_xy_McCamy1992`: Compute *CIE xy*

12 chromaticity coordinates from specified correlated colour temperature

13 :math:`T_{cp}` using the *McCamy (1992)* method.

14

15 References

16----------

17- :cite:`Wikipedia2001` : Wikipedia. (2001). Approximation. Retrieved June

18 28, 2014, from http://en.wikipedia.org/wiki/Color_temperature#Approximation

19"""

20

21 from __future__ import annotations

22

23 import typing

24

25 import numpy as np

26

27 from colour.algebra import sdiv, sdiv_mode

28 from colour.colorimetry import CCS_ILLUMINANTS

29

30 if typing.TYPE_CHECKING:

31 from colour.hints import ArrayLike, DTypeFloat, NDArrayFloat

32

33 from colour.utilities import as_float, as_float_array, required, tsplit, usage_warning

34

35 __author__ = "Colour Developers"

36 __copyright__ = "Copyright 2013 Colour Developers"

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

38 __maintainer__ = "Colour Developers"

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

40 __status__ = "Production"

41

42 __all__ = [

43 "xy_to_CCT_McCamy1992",

44 "CCT_to_xy_McCamy1992",

45]

46

47

48@required("SciPy")

49 def xy_to_CCT_McCamy1992(xy: ArrayLike) -> NDArrayFloat:

50 """

51 Compute the correlated colour temperature :math:`T_{cp}` from the

52 specified *CIE xy* chromaticity coordinates using the *McCamy (1992)*

53 method.

54

55 Parameters

56 ----------

57 xy

58 *CIE xy* chromaticity coordinates.

59

60 Returns

61 -------

62 :class:`numpy.ndarray`

63 Correlated colour temperature :math:`T_{cp}`.

64

65 References

66 ----------

67 :cite:`Wikipedia2001`

68

69 Examples

70 --------

71 >>> import numpy as np

72 >>> xy = np.array([0.31270, 0.32900])

73 >>> xy_to_CCT_McCamy1992(xy) # doctest: +ELLIPSIS

74 6505.0805913...

75 """

76

77 x, y = tsplit(xy)

78

79 with sdiv_mode():

80 n = sdiv(x - 0.3320, y - 0.1858)

81

82 CCT = -449 * n**3 + 3525 * n**2 - 6823.3 * n + 5520.33

83

84 return as_float(CCT)

85

86

87 def CCT_to_xy_McCamy1992(

88 CCT: ArrayLike, optimisation_kwargs: dict | None = None

89) -> NDArrayFloat:

90 """

91 Compute the *CIE xy* chromaticity coordinates from the specified

92 correlated colour temperature :math:`T_{cp}` using the *McCamy (1992)*

93 method.

94

95 Parameters

96 ----------

97 CCT

98 Correlated colour temperature :math:`T_{cp}`.

99 optimisation_kwargs

100 Parameters for :func:`scipy.optimize.minimize` definition.

101

102 Returns

103 -------

104 :class:`numpy.ndarray`

105 *CIE xy* chromaticity coordinates.

106

107 Warnings

108 --------

109 The *McCamy (1992)* method for computing *CIE xy* chromaticity coordinates

110 from the specified correlated colour temperature is not a bijective

111 function and might produce unexpected results. It is provided for

112 consistency with other correlated colour temperature computation methods

113 but should be avoided for practical applications. The current

114 implementation relies on optimisation using

115 :func:`scipy.optimize.minimize` definition and thus has reduced precision

116 and poor performance.

117

118 References

119 ----------

120 :cite:`Wikipedia2001`

121

122 Examples

123 --------

124 >>> CCT_to_xy_McCamy1992(6505.0805913074782) # doctest: +ELLIPSIS

125 array([ 0.3127..., 0.329...])

126 """

127

128 from scipy.optimize import minimize # noqa: PLC0415

129

130 usage_warning(

131 '"McCamy (1992)" method for computing "CIE xy" chromaticity '

132 "coordinates from given correlated colour temperature is not a "

133 "bijective function and might produce unexpected results. It is given "

134 "for consistency with other correlated colour temperature computation "

135 "methods but should be avoided for practical applications."

136 )

137

138 CCT = as_float_array(CCT)

139 shape = list(CCT.shape)

140 CCT = np.atleast_1d(np.reshape(CCT, (-1, 1)))

141

142 def objective_function(xy: NDArrayFloat, CCT: NDArrayFloat) -> DTypeFloat:

143 """Objective function."""

144

145 objective = np.linalg.norm(xy_to_CCT_McCamy1992(xy) - CCT)

146

147 return as_float(objective)

148

149 optimisation_settings = {

150 "method": "Nelder-Mead",

151 "options": {

152 "fatol": 1e-10,

153 },

154 }

155 if optimisation_kwargs is not None:

156 optimisation_settings.update(optimisation_kwargs)

157

158 xy = as_float_array(

159 [

160 minimize(

161 objective_function,

162 x0=CCS_ILLUMINANTS["CIE 1931 2 Degree Standard Observer"]["D65"],

163 args=(CCT_i,),

164 **optimisation_settings,

165 ).x

166 for CCT_i in CCT

167 ]

168 )

169

170 return np.reshape(xy, ([*shape, 2]))