Coverage for models/cie_ucs.py: 60%

50 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-16 22:49 +1300

1""" 

2CIE 1960 UCS Colourspace 

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

4 

5Define the *CIE 1960 UCS* colourspace transformations. 

6 

7- :func:`colour.XYZ_to_UCS` 

8- :func:`colour.UCS_to_XYZ` 

9- :func:`colour.UCS_to_uv` 

10- :func:`colour.uv_to_UCS` 

11- :func:`colour.UCS_uv_to_xy` 

12- :func:`colour.xy_to_UCS_uv` 

13- :func:`colour.XYZ_to_CIE1960UCS` 

14- :func:`colour.CIE1960UCS_to_XYZ` 

15 

16References 

17---------- 

18- :cite:`Wikipedia2008` : Wikipedia. (2008). CIE 1960 color space. Retrieved 

19 February 24, 2014, from http://en.wikipedia.org/wiki/CIE_1960_color_space 

20- :cite:`Wikipedia2008c` : Wikipedia. (2008). Relation to CIE XYZ. Retrieved 

21 February 24, 2014, from 

22 http://en.wikipedia.org/wiki/CIE_1960_color_space#Relation_to_CIE_XYZ 

23""" 

24 

25from __future__ import annotations 

26 

27import numpy as np 

28 

29from colour.algebra import sdiv, sdiv_mode 

30from colour.hints import ( # noqa: TC001 

31 ArrayLike, 

32 Domain1, 

33 NDArrayFloat, 

34 Range1, 

35) 

36from colour.utilities import from_range_1, to_domain_1, tsplit, tstack 

37 

38__author__ = "Colour Developers" 

39__copyright__ = "Copyright 2013 Colour Developers" 

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

41__maintainer__ = "Colour Developers" 

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

43__status__ = "Production" 

44 

45__all__ = [ 

46 "XYZ_to_UCS", 

47 "UCS_to_XYZ", 

48 "UCS_to_uv", 

49 "uv_to_UCS", 

50 "UCS_uv_to_xy", 

51 "xy_to_UCS_uv", 

52 "XYZ_to_CIE1960UCS", 

53 "CIE1960UCS_to_XYZ", 

54] 

55 

56 

57def XYZ_to_UCS(XYZ: Domain1) -> Range1: 

58 """ 

59 Convert from *CIE XYZ* tristimulus values to *CIE 1960 UCS* :math:`UVW` 

60 colourspace. 

61 

62 Parameters 

63 ---------- 

64 XYZ 

65 *CIE XYZ* tristimulus values. 

66 

67 Returns 

68 ------- 

69 :class:`numpy.ndarray` 

70 *CIE 1960 UCS* :math:`UVW` colourspace array. 

71 

72 Notes 

73 ----- 

74 +------------+-----------------------+---------------+ 

75 | **Domain** | **Scale - Reference** | **Scale - 1** | 

76 +============+=======================+===============+ 

77 | ``XYZ`` | 1 | 1 | 

78 +------------+-----------------------+---------------+ 

79 

80 +------------+-----------------------+---------------+ 

81 | **Range** | **Scale - Reference** | **Scale - 1** | 

82 +============+=======================+===============+ 

83 | ``UVW`` | 1 | 1 | 

84 +------------+-----------------------+---------------+ 

85 

86 References 

87 ---------- 

88 :cite:`Wikipedia2008c`, :cite:`Wikipedia2008` 

89 

90 Examples 

91 -------- 

92 >>> import numpy as np 

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

94 >>> XYZ_to_UCS(XYZ) # doctest: +ELLIPSIS 

95 array([ 0.1376933..., 0.1219722..., 0.1053731...]) 

96 """ 

97 

98 X, Y, Z = tsplit(to_domain_1(XYZ)) 

99 

100 UVW = tstack([2 / 3 * X, Y, 1 / 2 * (-X + 3 * Y + Z)]) 

101 

102 return from_range_1(UVW) 

103 

104 

105def UCS_to_XYZ(UVW: Domain1) -> Range1: 

106 """ 

107 Convert from *CIE 1960 UCS* :math:`UVW` colourspace to *CIE XYZ* 

108 tristimulus values. 

109 

110 Parameters 

111 ---------- 

112 UVW 

113 *CIE 1960 UCS* :math:`UVW` colourspace array. 

114 

115 Returns 

116 ------- 

117 :class:`numpy.ndarray` 

118 *CIE XYZ* tristimulus values. 

119 

120 Notes 

121 ----- 

122 +------------+-----------------------+---------------+ 

123 | **Domain** | **Scale - Reference** | **Scale - 1** | 

124 +============+=======================+===============+ 

125 | ``UVW`` | 1 | 1 | 

126 +------------+-----------------------+---------------+ 

127 

128 +------------+-----------------------+---------------+ 

129 | **Range** | **Scale - Reference** | **Scale - 1** | 

130 +============+=======================+===============+ 

131 | ``XYZ`` | 1 | 1 | 

132 +------------+-----------------------+---------------+ 

133 

134 References 

135 ---------- 

136 :cite:`Wikipedia2008c`, :cite:`Wikipedia2008` 

137 

138 Examples 

139 -------- 

140 >>> import numpy as np 

141 >>> UVW = np.array([0.13769339, 0.12197225, 0.10537310]) 

142 >>> UCS_to_XYZ(UVW) # doctest: +ELLIPSIS 

143 array([ 0.2065400..., 0.1219722..., 0.0513695...]) 

144 """ 

145 

146 U, V, W = tsplit(to_domain_1(UVW)) 

147 

148 XYZ = tstack([3 / 2 * U, V, 3 / 2 * U - (3 * V) + (2 * W)]) 

149 

150 return from_range_1(XYZ) 

151 

152 

153def UCS_to_uv(UVW: Domain1) -> NDArrayFloat: 

154 """ 

155 Convert from *CIE 1960 UCS* colourspace to *uv* chromaticity 

156 coordinates. 

157 

158 Parameters 

159 ---------- 

160 UVW 

161 *CIE 1960 UCS* :math:`UVW` colourspace array. 

162 

163 Returns 

164 ------- 

165 :class:`numpy.ndarray` 

166 *CIE UCS uv* chromaticity coordinates. 

167 

168 Notes 

169 ----- 

170 +------------+-----------------------+---------------+ 

171 | **Domain** | **Scale - Reference** | **Scale - 1** | 

172 +============+=======================+===============+ 

173 | ``UVW`` | 1 | 1 | 

174 +------------+-----------------------+---------------+ 

175 

176 References 

177 ---------- 

178 :cite:`Wikipedia2008c` 

179 

180 Examples 

181 -------- 

182 >>> import numpy as np 

183 >>> UVW = np.array([0.13769339, 0.12197225, 0.10537310]) 

184 >>> UCS_to_uv(UVW) # doctest: +ELLIPSIS 

185 array([ 0.3772021..., 0.3341350...]) 

186 """ 

187 

188 U, V, W = tsplit(to_domain_1(UVW)) 

189 

190 U_V_W = U + V + W 

191 

192 with sdiv_mode(): 

193 return tstack([sdiv(U, U_V_W), sdiv(V, U_V_W)]) 

194 

195 

196def uv_to_UCS(uv: ArrayLike, V: Domain1 = 1) -> Range1: 

197 """ 

198 Convert from *uv* chromaticity coordinates to *CIE 1960 UCS* 

199 colourspace. 

200 

201 Parameters 

202 ---------- 

203 uv 

204 *CIE UCS uv* chromaticity coordinates. 

205 V 

206 Optional :math:`V` *luminance* value used to construct the 

207 *CIE 1960 UCS* :math:`UVW` colourspace array, the default :math:`V` 

208 *luminance* is set to 1. 

209 

210 Returns 

211 ------- 

212 :class:`numpy.ndarray` 

213 *CIE 1960 UCS* :math:`UVW` colourspace array. 

214 

215 Notes 

216 ----- 

217 +------------+-----------------------+---------------+ 

218 | **Domain** | **Scale - Reference** | **Scale - 1** | 

219 +============+=======================+===============+ 

220 | ``V`` | 1 | 1 | 

221 +------------+-----------------------+---------------+ 

222 

223 +------------+-----------------------+---------------+ 

224 | **Range** | **Scale - Reference** | **Scale - 1** | 

225 +============+=======================+===============+ 

226 | ``UVW`` | 1 | 1 | 

227 +------------+-----------------------+---------------+ 

228 

229 References 

230 ---------- 

231 :cite:`Wikipedia2008c` 

232 

233 Examples 

234 -------- 

235 >>> import numpy as np 

236 >>> uv = np.array([0.37720213, 0.33413508]) 

237 >>> uv_to_UCS(uv) # doctest: +ELLIPSIS 

238 array([ 1.1288911..., 1. , 0.8639104...]) 

239 """ 

240 

241 u, v = tsplit(uv) 

242 V = to_domain_1(V) 

243 

244 with sdiv_mode(): 

245 UVW = tstack([V * sdiv(u, v), np.resize(V, u.shape), -V * sdiv(u + v - 1, v)]) 

246 

247 return from_range_1(UVW) 

248 

249 

250def UCS_uv_to_xy(uv: ArrayLike) -> NDArrayFloat: 

251 """ 

252 Convert from *CIE 1960 UCS* :math:`UVW` colourspace *uv* chromaticity 

253 coordinates to *CIE xy* chromaticity coordinates. 

254 

255 Parameters 

256 ---------- 

257 uv 

258 *CIE UCS uv* chromaticity coordinates. 

259 

260 Returns 

261 ------- 

262 :class:`numpy.ndarray` 

263 *CIE xy* chromaticity coordinates. 

264 

265 References 

266 ---------- 

267 :cite:`Wikipedia2008c` 

268 

269 Examples 

270 -------- 

271 >>> import numpy as np 

272 >>> uv = np.array([0.37720213, 0.33413508]) 

273 >>> UCS_uv_to_xy(uv) # doctest: +ELLIPSIS 

274 array([ 0.5436955..., 0.3210794...]) 

275 """ 

276 

277 u, v = tsplit(uv) 

278 

279 d = 2 * u - 8 * v + 4 

280 

281 with sdiv_mode(): 

282 return tstack([sdiv(3 * u, d), sdiv(2 * v, d)]) 

283 

284 

285def xy_to_UCS_uv(xy: ArrayLike) -> NDArrayFloat: 

286 """ 

287 Convert from *CIE xy* chromaticity coordinates to *CIE 1960 UCS* 

288 :math:`UVW` colourspace *uv* chromaticity coordinates. 

289 

290 Parameters 

291 ---------- 

292 xy 

293 *CIE xy* chromaticity coordinates. 

294 

295 Returns 

296 ------- 

297 :class:`numpy.ndarray` 

298 *CIE UCS uv* chromaticity coordinates. 

299 

300 References 

301 ---------- 

302 :cite:`Wikipedia2008c` 

303 

304 Examples 

305 -------- 

306 >>> import numpy as np 

307 >>> xy = np.array([0.54369555, 0.32107941]) 

308 >>> xy_to_UCS_uv(xy) # doctest: +ELLIPSIS 

309 array([ 0.3772021..., 0.3341350...]) 

310 """ 

311 

312 x, y = tsplit(xy) 

313 

314 d = 12 * y - 2 * x + 3 

315 

316 with sdiv_mode(): 

317 return tstack([sdiv(4 * x, d), sdiv(6 * y, d)]) 

318 

319 

320def XYZ_to_CIE1960UCS( 

321 XYZ: Domain1, 

322) -> Range1: 

323 """ 

324 Convert from *CIE XYZ* tristimulus values to *CIE 1960 UCS* :math:`uvV` 

325 colourspace. 

326 

327 This colourspace combines the *CIE 1960 UCS* :math:`UVW` colourspace 

328 :math:`uv` chromaticity coordinates with the luminance :math:`V` from 

329 the *CIE 1960 UCS* :math:`UVW` colourspace. 

330 

331 It is a convenient definition for use with the 

332 *CIE 1960 UCS Chromaticity Diagram*. 

333 

334 Parameters 

335 ---------- 

336 XYZ 

337 *CIE XYZ* tristimulus values. 

338 

339 Returns 

340 ------- 

341 :class:`numpy.ndarray` 

342 :math:`uvV` colourspace array. 

343 

344 Notes 

345 ----- 

346 +----------------+-----------------------+-----------------+ 

347 | **Domain** | **Scale - Reference** | **Scale - 1** | 

348 +================+=======================+=================+ 

349 | ``XYZ`` | 1 | 1 | 

350 +----------------+-----------------------+-----------------+ 

351 

352 +----------------+-----------------------+-----------------+ 

353 | **Range** | **Scale - Reference** | **Scale - 1** | 

354 +================+=======================+=================+ 

355 | ``uvV`` | 1 | 1 | 

356 +----------------+-----------------------+-----------------+ 

357 

358 Examples 

359 -------- 

360 >>> import numpy as np 

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

362 >>> XYZ_to_CIE1960UCS(XYZ) # doctest: +ELLIPSIS 

363 array([ 0.3772021..., 0.3341350..., 0.12197225]) 

364 """ 

365 

366 UVW = XYZ_to_UCS(XYZ) 

367 

368 _U, V, _W = tsplit(UVW) 

369 

370 u, v = tsplit(UCS_to_uv(UVW)) 

371 

372 return tstack([u, v, V]) 

373 

374 

375def CIE1960UCS_to_XYZ( 

376 uvV: Domain1, 

377) -> Range1: 

378 """ 

379 Convert from *CIE 1960 UCS* :math:`uvV` colourspace to *CIE XYZ* 

380 tristimulus values. 

381 

382 This colourspace combines the *CIE 1960 UCS* :math:`UVW` colourspace 

383 :math:`uv` chromaticity coordinates with the luminance :math:`V` from 

384 the *CIE 1960 UCS* :math:`UVW` colourspace. 

385 

386 It is a convenient definition for use with the 

387 *CIE 1960 UCS Chromaticity Diagram*. 

388 

389 Parameters 

390 ---------- 

391 uvV 

392 :math:`uvV` colourspace array. 

393 

394 Returns 

395 ------- 

396 :class:`numpy.ndarray` 

397 *CIE XYZ* tristimulus values. 

398 

399 Notes 

400 ----- 

401 +----------------+-----------------------+-----------------+ 

402 | **Domain** | **Scale - Reference** | **Scale - 1** | 

403 +================+=======================+=================+ 

404 | ``uvV`` | 1 | 1 | 

405 +----------------+-----------------------+-----------------+ 

406 

407 +----------------+-----------------------+-----------------+ 

408 | **Range** | **Scale - Reference** | **Scale - 1** | 

409 +================+=======================+=================+ 

410 | ``XYZ`` | 1 | 1 | 

411 +----------------+-----------------------+-----------------+ 

412 

413 Examples 

414 -------- 

415 >>> import numpy as np 

416 >>> uvV = np.array([0.37720213, 0.33413509, 0.12197225]) 

417 >>> CIE1960UCS_to_XYZ(uvV) # doctest: +ELLIPSIS 

418 array([ 0.2065400..., 0.1219722..., 0.0513695...]) 

419 """ 

420 

421 u, v, V = tsplit(uvV) 

422 

423 U, _V, W = tsplit(uv_to_UCS(tstack([u, v]), V)) 

424 

425 return UCS_to_XYZ(tstack([U, V, W]))