def test_domain_range_scale_CAM16_to_XYZ(self): """ Tests :func:`colour.appearance.cam16.CAM16_to_XYZ` definition domain and range scale support. """ XYZ_i = np.array([19.01, 20.00, 21.78]) XYZ_w = np.array([95.05, 100.00, 108.88]) L_A = 318.31 Y_b = 20.0 surround = CAM16_VIEWING_CONDITIONS['Average'] specification = XYZ_to_CAM16(XYZ_i, XYZ_w, L_A, Y_b, surround) XYZ = CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround) d_r = ( ('reference', 1, 1, 1), (1, np.array([1, 1, 1 / 360, 1, 1, 1, 1 / 360]), 0.01, 0.01), (100, np.array([1, 1, 100 / 360, 1, 1, 1, 100 / 360]), 1, 1), ) for scale, factor_a, factor_b, factor_c in d_r: with domain_range_scale(scale): np.testing.assert_almost_equal(CAM16_to_XYZ( specification[:-1] * factor_a, XYZ_w * factor_b, L_A, Y_b, surround), XYZ * factor_c, decimal=7)
def test_CAM16_to_XYZ(self): """Test :func:`colour.appearance.cam16.CAM16_to_XYZ` definition.""" specification = CAM_Specification_CAM16(41.73120791, 0.10335574, 217.06795977) XYZ_w = np.array([95.05, 100.00, 108.88]) L_A = 318.31 Y_b = 20 surround = VIEWING_CONDITIONS_CAM16["Average"] np.testing.assert_almost_equal( CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround), np.array([19.01, 20.00, 21.78]), decimal=7, ) specification = CAM_Specification_CAM16(65.42828069, 49.67956420, 17.48659243) L_A = 31.83 np.testing.assert_almost_equal( CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround), np.array([57.06, 43.06, 31.96]), decimal=7, ) specification = CAM_Specification_CAM16(21.36052893, 50.99381895, 178.86724266) XYZ_w = np.array([109.85, 100, 35.58]) L_A = 318.31 np.testing.assert_almost_equal( CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround), np.array([3.53, 6.56, 2.14]), decimal=7, ) specification = CAM_Specification_CAM16(41.36326063, 52.81154022, 258.88676291) L_A = 318.31 np.testing.assert_almost_equal( CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround), np.array([19.01, 20.00, 21.78]), decimal=7, ) specification = CAM_Specification_CAM16(21.03801957, 457.78881613, 350.06445098) XYZ_w = np.array([95.05, 100.00, 108.88]) L_A = 4.074366543152521 np.testing.assert_almost_equal( CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround), np.array([61.45276998, 7.00421901, 82.2406738]), decimal=7, )
def test_domain_range_scale_CAM16_to_XYZ(self): """ Test :func:`colour.appearance.cam16.CAM16_to_XYZ` definition domain and range scale support. """ XYZ = np.array([19.01, 20.00, 21.78]) XYZ_w = np.array([95.05, 100.00, 108.88]) L_A = 318.31 Y_b = 20 surround = VIEWING_CONDITIONS_CAM16["Average"] specification = XYZ_to_CAM16(XYZ, XYZ_w, L_A, Y_b, surround) XYZ = CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround) d_r = ( ("reference", 1, 1), ( "1", np.array([ 1 / 100, 1 / 100, 1 / 360, 1 / 100, 1 / 100, 1 / 100, 1 / 400, np.nan, ]), 0.01, ), ( "100", np.array([1, 1, 100 / 360, 1, 1, 1, 100 / 400, np.nan]), 1, ), ) for scale, factor_a, factor_b in d_r: with domain_range_scale(scale): np.testing.assert_almost_equal( CAM16_to_XYZ( specification * factor_a, XYZ_w * factor_b, L_A, Y_b, surround, ), XYZ * factor_b, decimal=7, )
def _XYZ_from_data(self, data, correlates): """ Returns the *CIE XYZ* tristimulus values from given *CAM16* colour appearance model input data. Parameters ---------- data : list Fixture data. correlates : array_like Correlates used to build the input *CAM16* colour appearance model specification. Returns ------- array_like *CIE XYZ* tristimulus values """ XYZ_w = tstack([data['X_w'], data['Y_w'], data['Z_w']]) i, j, k = correlates CAM16_specification = as_namedtuple( { i: data[i], j: data[j], k: data[k] }, CAM16_Specification) XYZ = CAM16_to_XYZ( CAM16_specification, XYZ_w, data['L_A'], data['Y_b'], CAM16_InductionFactors(data['F'], data['c'], data['N_c'])) return XYZ
def test_n_dimensional_CAM16_to_XYZ(self): """ Test :func:`colour.appearance.cam16.CAM16_to_XYZ` definition n-dimensional support. """ XYZ = np.array([19.01, 20.00, 21.78]) XYZ_w = np.array([95.05, 100.00, 108.88]) L_A = 318.31 Y_b = 20 surround = VIEWING_CONDITIONS_CAM16["Average"] specification = XYZ_to_CAM16(XYZ, XYZ_w, L_A, Y_b, surround) XYZ = CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround) specification = CAM_Specification_CAM16( *np.transpose(np.tile(tsplit(specification), (6, 1))).tolist()) XYZ = np.tile(XYZ, (6, 1)) np.testing.assert_almost_equal( CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround), XYZ, decimal=7, ) XYZ_w = np.tile(XYZ_w, (6, 1)) np.testing.assert_almost_equal( CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround), XYZ, decimal=7, ) specification = CAM_Specification_CAM16( *tsplit(np.reshape(specification, (2, 3, 8))).tolist()) XYZ_w = np.reshape(XYZ_w, (2, 3, 3)) XYZ = np.reshape(XYZ, (2, 3, 3)) np.testing.assert_almost_equal( CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround), XYZ, decimal=7, )
def test_nan_CAM16_to_XYZ(self): """ Tests :func:`colour.appearance.cam16.CAM16_to_XYZ` definition nan support. """ cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan] cases = set(permutations(cases * 3, r=3)) for case in cases: J = case[0] C = case[0] h = case[0] XYZ_w = np.array(case) L_A = case[0] Y_b = case[0] surround = CAM16_InductionFactors(case[0], case[0], case[0]) CAM16_to_XYZ(CAM16_Specification(J, C, h), XYZ_w, L_A, Y_b, surround)
def test_raise_exception_CAM16_to_XYZ(self): """ Tests :func:`colour.appearance.cam16.CAM16_to_XYZ` definition raised exception. """ try: CAM16_to_XYZ( CAM16_Specification( 41.731207905126638, None, 217.06795976739301, ), np.array([95.05, 100.00, 108.88]), 318.31, 20.0, CAM16_VIEWING_CONDITIONS['Average'], ) except ValueError: pass
def UCS_Li2017_to_XYZ(Jpapbp: ArrayLike, coefficients: ArrayLike, **kwargs: Any) -> NDArray: """ Convert from one of the *Li et al. (2017)* *CAM16-LCD*, *CAM16-SCD*, or *CAM16-UCS* colourspaces :math:`J'a'b'` array to *CIE XYZ* tristimulus values. Parameters ---------- Jpapbp *Li et al. (2017)* *CAM16-LCD*, *CAM16-SCD*, or *CAM16-UCS* colourspaces :math:`J'a'b'` array. coefficients Coefficients of one of the *Li et al. (2017)* *CAM16-LCD*, *CAM16-SCD*, or *CAM16-UCS* colourspaces. Other Parameters ---------------- kwargs {:func:`colour.CAM16_to_XYZ`}, See the documentation of the previously listed definition. The default viewing conditions are that of *IEC 61966-2-1:1999*, i.e. *sRGB* 64 Lux ambient illumination, 80 :math:`cd/m^2`, adapting field luminance about 20% of a white object in the scene. Returns ------- :class:`numpy.ndarray` *CIE XYZ* tristimulus values. Warnings -------- The ``XYZ_w`` parameter for :func:`colour.XYZ_to_CAM16` definition must be given in the same domain-range scale than the ``XYZ`` parameter. Notes ----- +------------+------------------------+------------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+========================+==================+ | ``Jpapbp`` | ``Jp`` : [0, 100] | ``Jp`` : [0, 1] | | | | | | | ``ap`` : [-100, 100] | ``ap`` : [-1, 1] | | | | | | | ``bp`` : [-100, 100] | ``bp`` : [-1, 1] | +------------+------------------------+------------------+ +------------+------------------------+------------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+========================+==================+ | ``XYZ`` | [0, 1] | [0, 1] | +------------+------------------------+------------------+ Examples -------- >>> import numpy as np >>> Jpapbp = np.array([46.06586037, 41.07586491, 14.51025828]) >>> UCS_Li2017_to_XYZ( ... Jpapbp, COEFFICIENTS_UCS_LUO2006['CAM02-LCD']) ... # doctest: +ELLIPSIS array([ 0.2065400..., 0.1219722..., 0.0513695...]) >>> from colour.appearance import CAM_KWARGS_CIECAM02_sRGB >>> XYZ_w = CAM_KWARGS_CIECAM02_sRGB['XYZ_w'] >>> UCS_Li2017_to_XYZ( ... Jpapbp, COEFFICIENTS_UCS_LUO2006['CAM02-LCD'], XYZ_w=XYZ_w / 100) ... # doctest: +ELLIPSIS array([ 0.2065400..., 0.1219722..., 0.0513695...]) """ from colour.appearance import ( CAM_KWARGS_CIECAM02_sRGB, CAM_Specification_CAM16, CAM16_to_XYZ, ) domain_range_reference = get_domain_range_scale() == "reference" settings = CAM_KWARGS_CIECAM02_sRGB.copy() settings.update(**kwargs) XYZ_w = kwargs.get("XYZ_w") if XYZ_w is not None and domain_range_reference: settings["XYZ_w"] = XYZ_w * 100 J, M, h = tsplit(UCS_Li2017_to_JMh_CAM16(Jpapbp, coefficients)) specification = CAM_Specification_CAM16(J=J, M=M, h=h) XYZ = CAM16_to_XYZ(specification, **settings) if domain_range_reference: XYZ /= 100 return XYZ