Coverage for colorimetry/transformations.py: 63%

1"""

2 Colour Matching Functions Transformations

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

4

5 Define educational objects for transformations between colour matching

6 functions in various colour spaces and observer standards.

7

8- :func:`colour.colorimetry.RGB_2_degree_cmfs_to_XYZ_2_degree_cmfs`

9- :func:`colour.colorimetry.RGB_10_degree_cmfs_to_XYZ_10_degree_cmfs`

10- :func:`colour.colorimetry.RGB_10_degree_cmfs_to_LMS_10_degree_cmfs`

11- :func:`colour.colorimetry.LMS_2_degree_cmfs_to_XYZ_2_degree_cmfs`

12- :func:`colour.colorimetry.LMS_10_degree_cmfs_to_XYZ_10_degree_cmfs`

13

14 References

15----------

16- :cite:`CIETC1-362006a` : CIE TC 1-36. (2006). CIE 170-1:2006 Fundamental

17 Chromaticity Diagram with Physiological Axes - Part 1. Commission

18 Internationale de l'Eclairage. ISBN:978-3-901906-46-6

19- :cite:`CVRLp` : CVRL. (n.d.). CIE (2012) 10-deg XYZ

20 "physiologically-relevant" colour matching functions. Retrieved June 25,

21 2014, from http://www.cvrl.org/database/text/cienewxyz/cie2012xyz10.htm

22- :cite:`CVRLv` : CVRL. (n.d.). CIE (2012) 2-deg XYZ

23 "physiologically-relevant" colour matching functions. Retrieved June 25,

24 2014, from http://www.cvrl.org/database/text/cienewxyz/cie2012xyz2.htm

25- :cite:`Wyszecki2000be` : Wyszecki, Günther, & Stiles, W. S. (2000). The

26 CIE 1964 Standard Observer. In Color Science: Concepts and Methods,

27 Quantitative Data and Formulae (p. 141). Wiley. ISBN:978-0-471-39918-6

28- :cite:`Wyszecki2000bg` : Wyszecki, Günther, & Stiles, W. S. (2000). Table

29 1(3.3.3). In Color Science: Concepts and Methods, Quantitative Data and

30 Formulae (pp. 138-139). Wiley. ISBN:978-0-471-39918-6

31"""

32

33 from __future__ import annotations

34

35 import typing

36

37 import numpy as np

38

39 from colour.algebra import vecmul

40 from colour.colorimetry import (

41 MSDS_CMFS_LMS,

42 MSDS_CMFS_RGB,

43 SDS_LEFS_PHOTOPIC,

44 reshape_sd,

45)

46

47 if typing.TYPE_CHECKING:

48 from colour.hints import ArrayLike, NDArrayFloat

49

50 from colour.utilities import tstack

51

52 __author__ = "Colour Developers"

53 __copyright__ = "Copyright 2013 Colour Developers"

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

55 __maintainer__ = "Colour Developers"

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

57 __status__ = "Production"

58

59 __all__ = [

60 "RGB_2_degree_cmfs_to_XYZ_2_degree_cmfs",

61 "RGB_10_degree_cmfs_to_XYZ_10_degree_cmfs",

62 "RGB_10_degree_cmfs_to_LMS_10_degree_cmfs",

63 "LMS_2_degree_cmfs_to_XYZ_2_degree_cmfs",

64 "LMS_10_degree_cmfs_to_XYZ_10_degree_cmfs",

65]

66

67

68 def RGB_2_degree_cmfs_to_XYZ_2_degree_cmfs(

69 wavelength: ArrayLike,

70) -> NDArrayFloat:

71 """

72 Convert the *Wright & Guild 1931 2 Degree RGB CMFs* colour matching

73 functions to the *CIE 1931 2 Degree Standard Observer* colour matching

74 functions.

75

76 Parameters

77 ----------

78 wavelength

79 Wavelength :math:`\\lambda` in nm.

80

81 Returns

82 -------

83 :class:`numpy.ndarray`

84 *CIE 1931 2 Degree Standard Observer* spectral tristimulus values.

85

86 Notes

87 -----

88 - Data for the *CIE 1931 2 Degree Standard Observer* already exists,

89 this definition is intended for educational purpose.

90

91 References

92 ----------

93 :cite:`Wyszecki2000bg`

94

95 Examples

96 --------

97 >>> from colour.utilities import numpy_print_options

98 >>> with numpy_print_options(suppress=True):

99 ... RGB_2_degree_cmfs_to_XYZ_2_degree_cmfs(700) # doctest: +ELLIPSIS

100 array([ 0.0113577..., 0.004102 , 0. ])

101 """

102

103 cmfs = MSDS_CMFS_RGB["Wright & Guild 1931 2 Degree RGB CMFs"]

104

105 rgb_bar = cmfs[wavelength]

106

107 rgb = rgb_bar / np.sum(rgb_bar)

108

109 M1 = np.array(

110 [

111 [0.49000, 0.31000, 0.20000],

112 [0.17697, 0.81240, 0.01063],

113 [0.00000, 0.01000, 0.99000],

114 ]

115 )

116

117 M2 = np.array(

118 [

119 [0.66697, 1.13240, 1.20063],

120 [0.66697, 1.13240, 1.20063],

121 [0.66697, 1.13240, 1.20063],

122 ]

123 )

124

125 xyz = vecmul(M1, rgb) / vecmul(M2, rgb)

126

127 x, y, z = xyz[..., 0], xyz[..., 1], xyz[..., 2]

128

129 V = reshape_sd(

130 SDS_LEFS_PHOTOPIC["CIE 1924 Photopic Standard Observer"],

131 cmfs.shape,

132 copy=False,

133 )

134 L = V[wavelength]

135

136 x_bar = x / y * L

137 y_bar = L

138 z_bar = z / y * L

139

140 return tstack([x_bar, y_bar, z_bar])

141

142

143 def RGB_10_degree_cmfs_to_XYZ_10_degree_cmfs(

144 wavelength: ArrayLike,

145) -> NDArrayFloat:

146 """

147 Convert the *Stiles & Burch 1959 10 Degree RGB CMFs* colour matching

148 functions to the *CIE 1964 10 Degree Standard Observer* colour matching

149 functions.

150

151 Parameters

152 ----------

153 wavelength

154 Wavelength :math:`\\lambda` in nm.

155

156 Returns

157 -------

158 :class:`numpy.ndarray`

159 *CIE 1964 10 Degree Standard Observer* spectral tristimulus

160 values.

161

162 Notes

163 -----

164 - Data for the *CIE 1964 10 Degree Standard Observer* already

165 exists, this definition is intended for educational purpose.

166

167 References

168 ----------

169 :cite:`Wyszecki2000be`

170

171 Examples

172 --------

173 >>> from colour.utilities import numpy_print_options

174 >>> with numpy_print_options(suppress=True):

175 ... RGB_10_degree_cmfs_to_XYZ_10_degree_cmfs(700) # doctest: +ELLIPSIS

176 array([ 0.0096432..., 0.0037526..., -0.0000041...])

177 """

178

179 cmfs = MSDS_CMFS_RGB["Stiles & Burch 1959 10 Degree RGB CMFs"]

180

181 rgb_bar = cmfs[wavelength]

182

183 M = np.array(

184 [

185 [0.341080, 0.189145, 0.387529],

186 [0.139058, 0.837460, 0.073316],

187 [0.000000, 0.039553, 2.026200],

188 ]

189 )

190

191 return vecmul(M, rgb_bar)

192

193

194 def RGB_10_degree_cmfs_to_LMS_10_degree_cmfs(

195 wavelength: ArrayLike,

196) -> NDArrayFloat:

197 """

198 Convert the *Stiles & Burch 1959 10 Degree RGB CMFs* colour matching

199 functions to the *Stockman & Sharpe 10 Degree Cone Fundamentals*

200 spectral sensitivity functions.

201

202 Parameters

203 ----------

204 wavelength

205 Wavelength :math:`\\lambda` in nm.

206

207 Returns

208 -------

209 :class:`numpy.ndarray`

210 *Stockman & Sharpe 10 Degree Cone Fundamentals* spectral

211 tristimulus values.

212

213 Notes

214 -----

215 - Data for the *Stockman & Sharpe 10 Degree Cone Fundamentals*

216 already exists, this definition is intended for educational

217 purpose.

218

219 References

220 ----------

221 :cite:`CIETC1-362006a`

222

223 Examples

224 --------

225 >>> from colour.utilities import numpy_print_options

226 >>> with numpy_print_options(suppress=True):

227 ... RGB_10_degree_cmfs_to_LMS_10_degree_cmfs(700) # doctest: +ELLIPSIS

228 array([ 0.0052860..., 0.0003252..., 0. ])

229 """

230

231 cmfs = MSDS_CMFS_RGB["Stiles & Burch 1959 10 Degree RGB CMFs"]

232

233 rgb_bar = cmfs[wavelength]

234

235 M = np.array(

236 [

237 [0.1923252690, 0.749548882, 0.0675726702],

238 [0.0192290085, 0.940908496, 0.113830196],

239 [0.0000000000, 0.0105107859, 0.991427669],

240 ]

241 )

242

243 lms_bar = vecmul(M, rgb_bar)

244 lms_bar[..., -1][np.asarray(np.asarray(wavelength) > 505)] = 0

245

246 return lms_bar

247

248

249 def LMS_2_degree_cmfs_to_XYZ_2_degree_cmfs(

250 wavelength: ArrayLike,

251) -> NDArrayFloat:

252 """

253 Convert the *Stockman & Sharpe 2 Degree Cone Fundamentals* colour matching

254 functions to the *CIE 2015 2 Degree Standard Observer* colour matching

255 functions.

256

257 Parameters

258 ----------

259 wavelength

260 Wavelength :math:`\\lambda` in nm.

261

262 Returns

263 -------

264 :class:`numpy.ndarray`

265 *CIE 2015 2 Degree Standard Observer* spectral tristimulus values.

266

267 Notes

268 -----

269 - Data for the *CIE 2015 2 Degree Standard Observer* already exists,

270 this definition is intended for educational purpose.

271

272 References

273 ----------

274 :cite:`CVRLv`

275

276 Examples

277 --------

278 >>> from colour.utilities import numpy_print_options

279 >>> with numpy_print_options(suppress=True):

280 ... LMS_2_degree_cmfs_to_XYZ_2_degree_cmfs(700) # doctest: +ELLIPSIS

281 array([ 0.0109677..., 0.0041959..., 0. ])

282 """

283

284 cmfs = MSDS_CMFS_LMS["Stockman & Sharpe 2 Degree Cone Fundamentals"]

285

286 lms_bar = cmfs[wavelength]

287

288 M = np.array(

289 [

290 [1.94735469, -1.41445123, 0.36476327],

291 [0.68990272, 0.34832189, 0.00000000],

292 [0.00000000, 0.00000000, 1.93485343],

293 ]

294 )

295

296 return vecmul(M, lms_bar)

297

298

299 def LMS_10_degree_cmfs_to_XYZ_10_degree_cmfs(

300 wavelength: ArrayLike,

301) -> NDArrayFloat:

302 """

303 Convert the *Stockman & Sharpe 10 Degree Cone Fundamentals* colour matching

304 functions to the *CIE 2015 10 Degree Standard Observer* colour matching

305 functions.

306

307 Parameters

308 ----------

309 wavelength

310 Wavelength :math:`\\lambda` in nm.

311

312 Returns

313 -------

314 :class:`numpy.ndarray`

315 *CIE 2015 10 Degree Standard Observer* spectral tristimulus values.

316

317 Notes

318 -----

319 - Data for the *CIE 2015 10 Degree Standard Observer* already exists,

320 this definition is intended for educational purpose.

321

322 References

323 ----------

324 :cite:`CVRLp`

325

326 Examples

327 --------

328 >>> from colour.utilities import numpy_print_options

329 >>> with numpy_print_options(suppress=True):

330 ... LMS_10_degree_cmfs_to_XYZ_10_degree_cmfs(700) # doctest: +ELLIPSIS

331 array([ 0.0098162..., 0.0037761..., 0. ])

332 """

333

334 cmfs = MSDS_CMFS_LMS["Stockman & Sharpe 10 Degree Cone Fundamentals"]

335

336 lms_bar = cmfs[wavelength]

337

338 M = np.array(

339 [

340 [1.93986443, -1.34664359, 0.43044935],

341 [0.69283932, 0.34967567, 0.00000000],

342 [0.00000000, 0.00000000, 2.14687945],

343 ]

344 )

345

346 return vecmul(M, lms_bar)