Coverage for colour/colorimetry/transformations.py: 100%
49 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
1"""
2Colour Matching Functions Transformations
3=========================================
5Define educational objects for transformations between colour matching
6functions in various colour spaces and observer standards.
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`
14References
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, Gü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, Gü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"""
33from __future__ import annotations
35import typing
37import numpy as np
39from colour.algebra import vecmul
40from colour.colorimetry import (
41 MSDS_CMFS_LMS,
42 MSDS_CMFS_RGB,
43 SDS_LEFS_PHOTOPIC,
44 reshape_sd,
45)
47if typing.TYPE_CHECKING:
48 from colour.hints import ArrayLike, NDArrayFloat
50from colour.utilities import tstack
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"
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]
68def 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.
76 Parameters
77 ----------
78 wavelength
79 Wavelength :math:`\\lambda` in nm.
81 Returns
82 -------
83 :class:`numpy.ndarray`
84 *CIE 1931 2 Degree Standard Observer* spectral tristimulus values.
86 Notes
87 -----
88 - Data for the *CIE 1931 2 Degree Standard Observer* already exists,
89 this definition is intended for educational purpose.
91 References
92 ----------
93 :cite:`Wyszecki2000bg`
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 """
103 cmfs = MSDS_CMFS_RGB["Wright & Guild 1931 2 Degree RGB CMFs"]
105 rgb_bar = cmfs[wavelength]
107 rgb = rgb_bar / np.sum(rgb_bar)
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 )
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 )
125 xyz = vecmul(M1, rgb) / vecmul(M2, rgb)
127 x, y, z = xyz[..., 0], xyz[..., 1], xyz[..., 2]
129 V = reshape_sd(
130 SDS_LEFS_PHOTOPIC["CIE 1924 Photopic Standard Observer"],
131 cmfs.shape,
132 copy=False,
133 )
134 L = V[wavelength]
136 x_bar = x / y * L
137 y_bar = L
138 z_bar = z / y * L
140 return tstack([x_bar, y_bar, z_bar])
143def 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.
151 Parameters
152 ----------
153 wavelength
154 Wavelength :math:`\\lambda` in nm.
156 Returns
157 -------
158 :class:`numpy.ndarray`
159 *CIE 1964 10 Degree Standard Observer* spectral tristimulus
160 values.
162 Notes
163 -----
164 - Data for the *CIE 1964 10 Degree Standard Observer* already
165 exists, this definition is intended for educational purpose.
167 References
168 ----------
169 :cite:`Wyszecki2000be`
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 """
179 cmfs = MSDS_CMFS_RGB["Stiles & Burch 1959 10 Degree RGB CMFs"]
181 rgb_bar = cmfs[wavelength]
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 )
191 return vecmul(M, rgb_bar)
194def 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.
202 Parameters
203 ----------
204 wavelength
205 Wavelength :math:`\\lambda` in nm.
207 Returns
208 -------
209 :class:`numpy.ndarray`
210 *Stockman & Sharpe 10 Degree Cone Fundamentals* spectral
211 tristimulus values.
213 Notes
214 -----
215 - Data for the *Stockman & Sharpe 10 Degree Cone Fundamentals*
216 already exists, this definition is intended for educational
217 purpose.
219 References
220 ----------
221 :cite:`CIETC1-362006a`
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 """
231 cmfs = MSDS_CMFS_RGB["Stiles & Burch 1959 10 Degree RGB CMFs"]
233 rgb_bar = cmfs[wavelength]
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 )
243 lms_bar = vecmul(M, rgb_bar)
244 lms_bar[..., -1][np.asarray(np.asarray(wavelength) > 505)] = 0
246 return lms_bar
249def 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.
257 Parameters
258 ----------
259 wavelength
260 Wavelength :math:`\\lambda` in nm.
262 Returns
263 -------
264 :class:`numpy.ndarray`
265 *CIE 2015 2 Degree Standard Observer* spectral tristimulus values.
267 Notes
268 -----
269 - Data for the *CIE 2015 2 Degree Standard Observer* already exists,
270 this definition is intended for educational purpose.
272 References
273 ----------
274 :cite:`CVRLv`
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 """
284 cmfs = MSDS_CMFS_LMS["Stockman & Sharpe 2 Degree Cone Fundamentals"]
286 lms_bar = cmfs[wavelength]
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 )
296 return vecmul(M, lms_bar)
299def 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.
307 Parameters
308 ----------
309 wavelength
310 Wavelength :math:`\\lambda` in nm.
312 Returns
313 -------
314 :class:`numpy.ndarray`
315 *CIE 2015 10 Degree Standard Observer* spectral tristimulus values.
317 Notes
318 -----
319 - Data for the *CIE 2015 10 Degree Standard Observer* already exists,
320 this definition is intended for educational purpose.
322 References
323 ----------
324 :cite:`CVRLp`
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 """
334 cmfs = MSDS_CMFS_LMS["Stockman & Sharpe 10 Degree Cone Fundamentals"]
336 lms_bar = cmfs[wavelength]
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 )
346 return vecmul(M, lms_bar)