def test_multi_sds_to_XYZ_integration(self): """ Tests :func:`colour.colorimetry.tristimulus.\ multi_sds_to_XYZ_integration` definition. """ cmfs = CMFS['CIE 1931 2 Degree Standard Observer'] np.testing.assert_almost_equal( multi_sds_to_XYZ_integration(MSDS, cmfs, ILLUMINANTS_SDS['D65']), XYZ_D65_INTEGRATION_MSDS, decimal=7) np.testing.assert_almost_equal( multi_sds_to_XYZ_integration( MSDS_ARRAY, cmfs, ILLUMINANTS_SDS['D65'], shape=SpectralShape(400, 700, 60)), XYZ_D65_ARRAY_INTEGRATION, decimal=7) np.testing.assert_almost_equal( multi_sds_to_XYZ_integration( MSDS_ARRAY, cmfs, ILLUMINANTS_SDS['D65'], 1, shape=SpectralShape(400, 700, 60)), XYZ_D65_ARRAY_K1_INTEGRATION, decimal=7)
def test_msds_to_XYZ_integration(self): """ Test :func:`colour.colorimetry.tristimulus_values.\ msds_to_XYZ_integration` definition. """ cmfs = MSDS_CMFS["CIE 1931 2 Degree Standard Observer"] np.testing.assert_almost_equal( msds_to_XYZ_integration(MSDS_TWO, cmfs, SDS_ILLUMINANTS["D65"]), TVS_D65_INTEGRATION_MSDS, decimal=7, ) np.testing.assert_almost_equal( msds_to_XYZ_integration( DATA_TWO, cmfs, SDS_ILLUMINANTS["D65"], shape=SpectralShape(400, 700, 60), ), TVS_D65_ARRAY_INTEGRATION, decimal=7, ) np.testing.assert_almost_equal( msds_to_XYZ_integration( DATA_TWO, cmfs, SDS_ILLUMINANTS["D65"], 1, shape=SpectralShape(400, 700, 60), ), TVS_D65_ARRAY_K1_INTEGRATION, decimal=7, )
def test_sd_to_XYZ_ASTME30815_mi_1nm(self): """ Tests :func:`colour.colorimetry.tristimulus.sd_to_XYZ_ASTME30815` definition for 1 nm measurement intervals. """ np.testing.assert_almost_equal( sd_to_XYZ_ASTME30815(self._sd.copy().align(self._cmfs.shape), self._cmfs, self._A), np.array([14.46372680, 10.85832950, 2.04663200]), decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_ASTME30815(self._sd.copy().align(self._cmfs.shape), self._cmfs, self._A, use_practice_range=False), np.array([14.46366018, 10.85827949, 2.04662258]), decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_ASTME30815( self._sd.copy().align(SpectralShape(400, 700, 1)), self._cmfs, self._A), np.array([14.54173397, 10.88628632, 2.04965822]), decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_ASTME30815(self._sd.copy().align( SpectralShape(400, 700, 1)), self._cmfs, self._A, use_practice_range=False), np.array([14.54203076, 10.88636754, 2.04964877]), decimal=7)
def test_spectral_to_XYZ_tristimulus_weighting_factors_ASTME30815(self): """ Tests :func:`colour.colorimetry.tristimulus.\ spectral_to_XYZ_tristimulus_weighting_factors_ASTME30815` definition. """ cmfs = CMFS.get('CIE 1931 2 Degree Standard Observer') np.testing.assert_almost_equal( spectral_to_XYZ_tristimulus_weighting_factors_ASTME30815( SAMPLE_SPD, cmfs, ILLUMINANTS_RELATIVE_SPDS.get('A')), np.array([14.46366344, 10.85828513, 2.04663792]), decimal=7) cmfs = CMFS.get('CIE 1964 10 Degree Standard Observer') np.testing.assert_almost_equal( spectral_to_XYZ_tristimulus_weighting_factors_ASTME30815( SAMPLE_SPD, cmfs, ILLUMINANTS_RELATIVE_SPDS.get('C')), np.array([10.77033881, 9.44864632, 6.62758924]), decimal=7) np.testing.assert_almost_equal( spectral_to_XYZ_tristimulus_weighting_factors_ASTME30815( SAMPLE_SPD, cmfs, ILLUMINANTS_RELATIVE_SPDS.get('F2')), np.array([11.57837130, 9.98734511, 3.95499522]), decimal=7) np.testing.assert_almost_equal( spectral_to_XYZ_tristimulus_weighting_factors_ASTME30815( SAMPLE_SPD.clone().trim_wavelengths( SpectralShape(400, 700, 5)), cmfs, ILLUMINANTS_RELATIVE_SPDS.get('A')), np.array([14.38180830, 10.74512906, 2.01579131]), decimal=7) np.testing.assert_almost_equal( spectral_to_XYZ_tristimulus_weighting_factors_ASTME30815( SAMPLE_SPD.clone().interpolate( SpectralShape(400, 700, 10)), cmfs, ILLUMINANTS_RELATIVE_SPDS.get('A')), np.array([14.38284399, 10.74577954, 2.01553721]), decimal=7) np.testing.assert_almost_equal( spectral_to_XYZ_tristimulus_weighting_factors_ASTME30815( SAMPLE_SPD.clone().interpolate( SpectralShape(400, 700, 20)), cmfs, ILLUMINANTS_RELATIVE_SPDS.get('A')), np.array([14.38356848, 10.74613294, 2.01526418]), decimal=7)
def test_sd_to_XYZ_ASTME308_mi_10nm(self): """ Test :func:`colour.colorimetry.tristimulus_values.sd_to_XYZ_ASTME308` definition for 10 nm measurement intervals. """ np.testing.assert_almost_equal( sd_to_XYZ_ASTME308( reshape_sd(self._sd, SpectralShape(360, 830, 10)), self._cmfs, self._A, ), np.array([14.47779980, 10.86358645, 2.04751388]), decimal=7, ) np.testing.assert_almost_equal( sd_to_XYZ_ASTME308( reshape_sd(self._sd, SpectralShape(360, 830, 10)), self._cmfs, self._A, use_practice_range=False, ), np.array([14.47773312, 10.86353641, 2.04750445]), decimal=7, ) np.testing.assert_almost_equal( sd_to_XYZ_ASTME308( reshape_sd(self._sd, SpectralShape(400, 700, 10)), self._cmfs, self._A, ), np.array([14.54137532, 10.88641727, 2.04931318]), decimal=7, ) np.testing.assert_almost_equal( sd_to_XYZ_ASTME308( reshape_sd(self._sd, SpectralShape(400, 700, 10)), self._cmfs, self._A, use_practice_range=False, ), np.array([14.54167211, 10.88649849, 2.04930374]), decimal=7, ) np.testing.assert_almost_equal( sd_to_XYZ_ASTME308( reshape_sd(self._sd, SpectralShape(400, 700, 10)), self._cmfs, self._A, k=1, ), np.array([1568.94283333, 1174.59084705, 221.11080639]), decimal=7, )
def test_sd_to_XYZ_tristimulus_weighting_factors_ASTME308(self): """ Tests :func:`colour.colorimetry.tristimulus.\ sd_to_XYZ_tristimulus_weighting_factors_ASTME308` definition. """ cmfs = CMFS['CIE 1931 2 Degree Standard Observer'] np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SAMPLE_SD, cmfs, ILLUMINANTS_SDS['A']), np.array([14.46366344, 10.85828513, 2.04663792]), decimal=7) cmfs = CMFS['CIE 1964 10 Degree Standard Observer'] np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SAMPLE_SD, cmfs, ILLUMINANTS_SDS['C']), np.array([10.77033881, 9.44864632, 6.62758924]), decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SAMPLE_SD, cmfs, ILLUMINANTS_SDS['FL2']), np.array([11.57837130, 9.98734511, 3.95499522]), decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SAMPLE_SD.copy().trim(SpectralShape(400, 700, 5)), cmfs, ILLUMINANTS_SDS['A']), np.array([14.38180830, 10.74512906, 2.01579131]), decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SAMPLE_SD.copy().interpolate(SpectralShape(400, 700, 10)), cmfs, ILLUMINANTS_SDS['A']), np.array([14.38284399, 10.74577954, 2.01553721]), decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SAMPLE_SD.copy().interpolate(SpectralShape(400, 700, 20)), cmfs, ILLUMINANTS_SDS['A']), np.array([14.38356848, 10.74613294, 2.01526418]), decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SAMPLE_SD.copy().interpolate(SpectralShape(400, 700, 20)), cmfs, ILLUMINANTS_SDS['A'], k=1), np.array([1636.74286798, 1222.82981953, 229.32204062]), decimal=7)
def test_sd_to_XYZ_tristimulus_weighting_factors_ASTME308(self): """ Tests :func:`colour.colorimetry.tristimulus.\ sd_to_XYZ_tristimulus_weighting_factors_ASTME308` definition. """ cmfs = MSDS_CMFS['CIE 1931 2 Degree Standard Observer'] np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SD_SAMPLE, cmfs, SDS_ILLUMINANTS['A']), np.array([14.46341867, 10.85820227, 2.04697034]), decimal=7) cmfs = MSDS_CMFS['CIE 1964 10 Degree Standard Observer'] np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SD_SAMPLE, cmfs, SDS_ILLUMINANTS['C']), np.array([10.77005571, 9.44877491, 6.62428210]), decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SD_SAMPLE, cmfs, SDS_ILLUMINANTS['FL2']), np.array([11.57542759, 9.98605604, 3.95273304]), decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SD_SAMPLE.copy().trim(SpectralShape(400, 700, 5)), cmfs, SDS_ILLUMINANTS['A']), np.array([14.38153638, 10.74503131, 2.01613844]), decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SD_SAMPLE.copy().interpolate(SpectralShape(400, 700, 10)), cmfs, SDS_ILLUMINANTS['A']), np.array([14.38257202, 10.74568178, 2.01588427]), decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SD_SAMPLE.copy().interpolate(SpectralShape(400, 700, 20)), cmfs, SDS_ILLUMINANTS['A']), np.array([14.38329645, 10.74603515, 2.01561113]), decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_tristimulus_weighting_factors_ASTME308( SD_SAMPLE.copy().interpolate(SpectralShape(400, 700, 20)), cmfs, SDS_ILLUMINANTS['A'], k=1), np.array([1636.74881983, 1222.84626486, 229.36669308]), decimal=7)
def mesopic_luminous_efficiency_function( Lp, source='Blue Heavy', method='MOVE', photopic_lef=PHOTOPIC_LEFS['CIE 1924 Photopic Standard Observer'], scotopic_lef=SCOTOPIC_LEFS['CIE 1951 Scotopic Standard Observer']): """ Returns the mesopic luminous efficiency function :math:`V_m(\lambda)` for given photopic luminance :math:`L_p`. Parameters ---------- Lp : numeric Photopic luminance :math:`L_p`. source : unicode, optional **{'Blue Heavy', 'Red Heavy'}**, Light source colour temperature. method : unicode, optional **{'MOVE', 'LRC'}**, Method to calculate the weighting factor. photopic_lef : SpectralPowerDistribution, optional :math:`V(\lambda)` photopic luminous efficiency function. scotopic_lef : SpectralPowerDistribution, optional :math:`V^\prime(\lambda)` scotopic luminous efficiency function. Returns ------- SpectralPowerDistribution Mesopic luminous efficiency function :math:`V_m(\lambda)`. Examples -------- >>> print(mesopic_luminous_efficiency_function(0.2)) SpectralPowerDistribution(\ '0.2 Lp Mesopic Luminous Efficiency Function', (380.0, 780.0, 1.0)) """ photopic_lef_shape = photopic_lef.shape scotopic_lef_shape = scotopic_lef.shape shape = SpectralShape( max(photopic_lef_shape.start, scotopic_lef_shape.start), min(photopic_lef_shape.end, scotopic_lef_shape.end), max(photopic_lef_shape.interval, scotopic_lef_shape.interval)) wavelengths = shape.range() spd_data = dict( zip( wavelengths, mesopic_weighting_function(wavelengths, Lp, source, method, photopic_lef, scotopic_lef))) spd = SpectralPowerDistribution( '{0} Lp Mesopic Luminous Efficiency Function'.format(Lp), spd_data) return spd.normalise()
def test_sd_to_XYZ_ASTME308_mi_1nm(self): """ Test :func:`colour.colorimetry.tristimulus_values.sd_to_XYZ_ASTME308` definition for 1 nm measurement intervals. """ np.testing.assert_almost_equal( sd_to_XYZ_ASTME308(reshape_sd(self._sd, self._cmfs.shape), self._cmfs, self._A), np.array([14.46372680, 10.85832950, 2.04663200]), decimal=7, ) np.testing.assert_almost_equal( sd_to_XYZ_ASTME308( reshape_sd(self._sd, self._cmfs.shape), self._cmfs, self._A, use_practice_range=False, ), np.array([14.46366018, 10.85827949, 2.04662258]), decimal=7, ) np.testing.assert_almost_equal( sd_to_XYZ_ASTME308( reshape_sd(self._sd, SpectralShape(400, 700, 1)), self._cmfs, self._A, ), np.array([14.54173397, 10.88628632, 2.04965822]), decimal=7, ) np.testing.assert_almost_equal( sd_to_XYZ_ASTME308( reshape_sd(self._sd, SpectralShape(400, 700, 1)), self._cmfs, self._A, use_practice_range=False, ), np.array([14.54203076, 10.88636754, 2.04964877]), decimal=7, ) np.testing.assert_almost_equal( sd_to_XYZ_ASTME308( reshape_sd(self._sd, SpectralShape(400, 700, 1)), self._cmfs, self._A, k=1, ), np.array([1568.98152997, 1174.57671769, 221.14803420]), decimal=7, )
def test_raise_exception_colour_fidelity_index_CFI2017(self): """ Test :func:`colour.quality.CIE2017.colour_fidelity_index_CFI2017` definition raised exception. """ sd = reshape_sd(SDS_ILLUMINANTS["FL2"], SpectralShape(400, 700, 5)) self.assertWarns(ColourUsageWarning, colour_fidelity_index_CIE2017, sd) sd = reshape_sd(SDS_ILLUMINANTS["FL2"], SpectralShape(380, 780, 10)) self.assertRaises(ValueError, colour_fidelity_index_CIE2017, sd)
def mesopic_luminous_efficiency_function( Lp, source="Blue Heavy", method="MOVE", photopic_lef=PHOTOPIC_LEFS.get("CIE 1924 Photopic Standard Observer"), scotopic_lef=SCOTOPIC_LEFS.get("CIE 1951 Scotopic Standard Observer"), ): """ Returns the mesopic luminous efficiency function :math:`V_m(\lambda)` for given photopic luminance :math:`L_p`. Parameters ---------- Lp : numeric Photopic luminance :math:`L_p`. source : unicode, optional **{'Blue Heavy', 'Red Heavy'}**, Light source colour temperature. method : unicode, optional **{'MOVE', 'LRC'}**, Method to calculate the weighting factor. photopic_lef : SpectralPowerDistribution, optional :math:`V(\lambda)` photopic luminous efficiency function. scotopic_lef : SpectralPowerDistribution, optional :math:`V^\prime(\lambda)` scotopic luminous efficiency function. Returns ------- SpectralPowerDistribution Mesopic luminous efficiency function :math:`V_m(\lambda)`. Examples -------- >>> mesopic_luminous_efficiency_function(0.2) # doctest: +ELLIPSIS <colour.colorimetry.spectrum.SpectralPowerDistribution object at 0x...> """ photopic_lef_shape = photopic_lef.shape scotopic_lef_shape = scotopic_lef.shape shape = SpectralShape( max(photopic_lef_shape.start, scotopic_lef_shape.start), min(photopic_lef_shape.end, scotopic_lef_shape.end), max(photopic_lef_shape.steps, scotopic_lef_shape.steps), ) wavelengths = shape.range() spd_data = dict( zip(wavelengths, mesopic_weighting_function(wavelengths, Lp, source, method, photopic_lef, scotopic_lef)) ) spd = SpectralPowerDistribution("{0} Lp Mesopic Luminous Efficiency Function".format(Lp), spd_data) return spd.normalise()
def test_adjust_tristimulus_weighting_factors_ASTME30815(self): """ Tests :func:`colour.colorimetry.tristimulus.\ adjust_tristimulus_weighting_factors_ASTME30815` definition. """ np.testing.assert_almost_equal( adjust_tristimulus_weighting_factors_ASTME30815( D65_CIE_1931_2_20_TWF, SpectralShape(360, 830, 20), SpectralShape(400, 700, 20)), D65_CIE_1931_2_20_ATWF, decimal=3)
def test_XYZ_to_sd_Meng2015(self): """ Tests :func:`colour.recovery.meng2015.XYZ_to_sd_Meng2015` definition. """ cmfs = (STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer']. copy().trim(DEFAULT_SPECTRAL_SHAPE)) shape = SpectralShape(cmfs.shape.start, cmfs.shape.end, 5) cmfs_c = cmfs.copy().align(shape) XYZ = np.array([0.21781186, 0.12541048, 0.04697113]) np.testing.assert_almost_equal( sd_to_XYZ_integration(XYZ_to_sd_Meng2015(XYZ, cmfs_c), cmfs_c) / 100, XYZ, decimal=7) shape = SpectralShape(cmfs.shape.start, cmfs.shape.end, 10) cmfs_c = cmfs.copy().align(shape) np.testing.assert_almost_equal( sd_to_XYZ_integration(XYZ_to_sd_Meng2015(XYZ, cmfs_c), cmfs_c) / 100, XYZ, decimal=7) np.testing.assert_almost_equal(sd_to_XYZ_integration( XYZ_to_sd_Meng2015(XYZ, cmfs_c, ILLUMINANTS_SDS['D65']), cmfs_c, ILLUMINANTS_SDS['D65']) / 100, XYZ, decimal=7) np.testing.assert_almost_equal(sd_to_XYZ_integration( XYZ_to_sd_Meng2015( XYZ, cmfs_c, optimisation_parameters={'options': { 'ftol': 1e-10, }}), cmfs_c) / 100, XYZ, decimal=7) shape = SpectralShape(400, 700, 5) cmfs_c = cmfs.copy().align(shape) np.testing.assert_almost_equal( sd_to_XYZ_integration(XYZ_to_sd_Meng2015(XYZ, cmfs_c), cmfs_c) / 100, XYZ, decimal=7)
def test_raise_exception_colour_fidelity_index_CFI2017(self): """ Tests :func:`colour.quality.CIE2017.colour_fidelity_index_CFI2017` definition raised exception. """ if six.PY3: # pragma: no cover sd = SDS_ILLUMINANTS['FL2'].copy().align(SpectralShape( 400, 700, 5)) self.assertWarns(ColourUsageWarning, colour_fidelity_index_CIE2017, sd) sd = SDS_ILLUMINANTS['FL2'].copy().align(SpectralShape(380, 780, 10)) self.assertRaises(ValueError, colour_fidelity_index_CIE2017, sd)
def test_adjust_tristimulus_weighting_factors_ASTME308(self): """ Test :func:`colour.colorimetry.tristimulus_values.\ adjust_tristimulus_weighting_factors_ASTME308` definition. """ np.testing.assert_almost_equal( adjust_tristimulus_weighting_factors_ASTME308( TWF_D65_CIE_1931_2_20, SpectralShape(360, 830, 20), SpectralShape(400, 700, 20), ), TWF_D65_CIE_1931_2_20_A, decimal=3, )
def test_tristimulus_weighting_factors_ASTME2022(self): """ Tests :func:`colour.colorimetry.tristimulus.\ tristimulus_weighting_factors_ASTME2022` definition. Notes ----- - :attr:`TWF_A_CIE_1964_10_10`, :attr:`TWF_A_CIE_1964_10_20` and :attr:`TWF_D65_CIE_1931_2_20` attributes data is matching :cite:`ASTMInternational2015b`. References ---------- :cite:`ASTMInternational2015b` """ cmfs = MSDS_CMFS['CIE 1964 10 Degree Standard Observer'] A = sd_CIE_standard_illuminant_A(cmfs.shape) twf = tristimulus_weighting_factors_ASTME2022( cmfs, A, SpectralShape(360, 830, 10)) np.testing.assert_almost_equal(np.round(twf, 3), TWF_A_CIE_1964_10_10, decimal=3) twf = tristimulus_weighting_factors_ASTME2022( cmfs, A, SpectralShape(360, 830, 20)) np.testing.assert_almost_equal(np.round(twf, 3), TWF_A_CIE_1964_10_20, decimal=3) cmfs = MSDS_CMFS['CIE 1931 2 Degree Standard Observer'] D65 = SDS_ILLUMINANTS['D65'].copy().align( cmfs.shape, interpolator=LinearInterpolator) twf = tristimulus_weighting_factors_ASTME2022( cmfs, D65, SpectralShape(360, 830, 20)) np.testing.assert_almost_equal(np.round(twf, 3), TWF_D65_CIE_1931_2_20, decimal=3) twf = tristimulus_weighting_factors_ASTME2022(cmfs, D65, SpectralShape( 360, 830, 20), k=1) np.testing.assert_almost_equal(twf, TWF_D65_CIE_1931_2_20_K1, decimal=7)
def test_raise_exception_tristimulus_weighting_factors_ASTME2022(self): """ Test :func:`colour.colorimetry.tristimulus_values.\ tristimulus_weighting_factors_ASTME2022` definition raised exception. """ shape = SpectralShape(360, 830, 10) cmfs_1 = MSDS_CMFS["CIE 1964 10 Degree Standard Observer"] # pylint: disable=E1102 cmfs_2 = reshape_msds(cmfs_1, shape) A_1 = sd_CIE_standard_illuminant_A(cmfs_1.shape) A_2 = sd_CIE_standard_illuminant_A(cmfs_2.shape) self.assertRaises( ValueError, tristimulus_weighting_factors_ASTME2022, cmfs_1, A_2, shape, ) self.assertRaises( ValueError, tristimulus_weighting_factors_ASTME2022, cmfs_2, A_1, shape, )
def test_handle_spectral_arguments(self): """ Test :func:`colour.colorimetry.tristimulus_values.\ handle_spectral_arguments` definition. """ cmfs, illuminant = handle_spectral_arguments() # pylint: disable=E1102 self.assertEqual( cmfs, reshape_msds(MSDS_CMFS["CIE 1931 2 Degree Standard Observer"]), ) self.assertEqual(illuminant, reshape_sd(SDS_ILLUMINANTS["D65"])) shape = SpectralShape(400, 700, 20) cmfs, illuminant = handle_spectral_arguments(shape_default=shape) self.assertEqual(cmfs.shape, shape) self.assertEqual(illuminant.shape, shape) cmfs, illuminant = handle_spectral_arguments( cmfs_default="CIE 2012 2 Degree Standard Observer", illuminant_default="E", shape_default=shape, ) self.assertEqual( cmfs, reshape_msds(MSDS_CMFS["CIE 2012 2 Degree Standard Observer"], shape=shape), ) self.assertEqual(illuminant, sd_ones(shape, interpolator=LinearInterpolator) * 100)
def sd_Jakob2019( coefficients: ArrayLike, shape: SpectralShape = SPECTRAL_SHAPE_JAKOB2019 ) -> SpectralDistribution: """ Return a spectral distribution following the spectral model given by *Jakob and Hanika (2019)*. Parameters ---------- coefficients Dimensionless coefficients for *Jakob and Hanika (2019)* reflectance spectral model. shape Shape used by the spectral distribution. Returns ------- :class:`colour.SpectralDistribution` *Jakob and Hanika (2019)* spectral distribution. References ---------- :cite:`Jakob2019` Examples -------- >>> from colour.utilities import numpy_print_options >>> with numpy_print_options(suppress=True): ... sd_Jakob2019([-9e-05, 8.5e-02, -20], SpectralShape(400, 700, 20)) ... # doctest: +ELLIPSIS SpectralDistribution([[ 400. , 0.3143046...], [ 420. , 0.4133320...], [ 440. , 0.4880034...], [ 460. , 0.5279562...], [ 480. , 0.5319346...], [ 500. , 0.5 ...], [ 520. , 0.4326202...], [ 540. , 0.3373544...], [ 560. , 0.2353056...], [ 580. , 0.1507665...], [ 600. , 0.0931332...], [ 620. , 0.0577434...], [ 640. , 0.0367011...], [ 660. , 0.0240879...], [ 680. , 0.0163316...], [ 700. , 0.0114118...]], interpolator=SpragueInterpolator, interpolator_kwargs={}, extrapolator=Extrapolator, extrapolator_kwargs={...}) """ c_0, c_1, c_2 = as_float_array(coefficients) wl = shape.range() U = c_0 * wl**2 + c_1 * wl + c_2 R = 1 / 2 + U / (2 * np.sqrt(1 + U**2)) name = f"{coefficients!r} (COEFF) - Jakob (2019)" return SpectralDistribution(R, wl, name=name)
def test_XYZ_to_sd_Meng2015(self): """ Tests :func:`colour.recovery.meng2015.XYZ_to_sd_Meng2015` definition. """ cmfs = STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer'] shape = SpectralShape(cmfs.shape.start, cmfs.shape.end, 5) cmfs_c = cmfs.copy().align(shape) XYZ = np.array([0.21781186, 0.12541048, 0.04697113]) np.testing.assert_almost_equal( sd_to_XYZ_integration(XYZ_to_sd_Meng2015(XYZ), cmfs=cmfs_c) / 100, XYZ, decimal=7) shape = SpectralShape(cmfs.shape.start, cmfs.shape.end, 10) cmfs_c = cmfs.copy().align(shape) np.testing.assert_almost_equal( sd_to_XYZ_integration( XYZ_to_sd_Meng2015(XYZ, interval=10), cmfs=cmfs_c) / 100, XYZ, decimal=7) np.testing.assert_almost_equal( sd_to_XYZ_integration( XYZ_to_sd_Meng2015( XYZ, interval=10, optimisation_parameters={ 'options': { 'ftol': 1e-10, 'maxiter': 2000 } }), cmfs=cmfs_c) / 100, XYZ, decimal=7) shape = SpectralShape(400, 700, 5) cmfs_c = cmfs.copy().align(shape) np.testing.assert_almost_equal( sd_to_XYZ_integration( XYZ_to_sd_Meng2015(XYZ, cmfs=cmfs_c), cmfs=cmfs_c) / 100, XYZ, decimal=7)
def test_tristimulus_weighting_factors_ASTME202211(self): """ Tests :func:`colour.colorimetry.tristimulus.\ tristimulus_weighting_factors_ASTME202211` definition. Notes ----- :attr:`A_CIE_1964_10_10_TWF`, :attr:`A_CIE_1964_10_20_TWF` and :attr:`D65_CIE_1931_2_20_TWF` attributes data is matching [1]_. References ---------- .. [1] ASTM International. (2015). ASTM E308–15 - Standard Practice for Computing the Colors of Objects by Using the CIE System, 1–47. doi:10.1520/E0308-15 """ cmfs = CMFS.get('CIE 1964 10 Degree Standard Observer') wl = cmfs.shape.range() A = SpectralPowerDistribution( 'A (360, 830, 1)', dict(zip(wl, CIE_standard_illuminant_A_function(wl)))) twf = tristimulus_weighting_factors_ASTME202211( cmfs, A, SpectralShape(360, 830, 10)) np.testing.assert_almost_equal( np.round(twf, 3), A_CIE_1964_10_10_TWF, decimal=3) twf = tristimulus_weighting_factors_ASTME202211( cmfs, A, SpectralShape(360, 830, 20)) np.testing.assert_almost_equal( np.round(twf, 3), A_CIE_1964_10_20_TWF, decimal=3) cmfs = CMFS.get('CIE 1931 2 Degree Standard Observer') D65 = ILLUMINANTS_RELATIVE_SPDS['D65'].clone().align( cmfs.shape, interpolation_method='Linear') twf = tristimulus_weighting_factors_ASTME202211( cmfs, D65, SpectralShape(360, 830, 20)) np.testing.assert_almost_equal( np.round(twf, 3), D65_CIE_1931_2_20_TWF, decimal=3)
def test_raise_exception_sd_to_XYZ_ASTME308(self): """ Tests :func:`colour.colorimetry.tristimulus.sd_to_XYZ_ASTME308` definition raised exception. """ self.assertRaises(ValueError, sd_to_XYZ_ASTME308, self._sd.copy().align(SpectralShape(360, 820, 2)))
def test_XYZ_to_sd_Meng2015(self): """Test :func:`colour.recovery.meng2015.XYZ_to_sd_Meng2015` definition.""" XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) np.testing.assert_almost_equal( sd_to_XYZ_integration( XYZ_to_sd_Meng2015(XYZ, self._cmfs, self._sd_D65), self._cmfs, self._sd_D65, ) / 100, XYZ, decimal=7, ) np.testing.assert_almost_equal( sd_to_XYZ_integration( XYZ_to_sd_Meng2015(XYZ, self._cmfs, self._sd_E), self._cmfs, self._sd_E, ) / 100, XYZ, decimal=7, ) np.testing.assert_almost_equal( sd_to_XYZ_integration( XYZ_to_sd_Meng2015( XYZ, self._cmfs, self._sd_D65, optimisation_kwargs={ "options": { "ftol": 1e-10, } }, ), self._cmfs, self._sd_D65, ) / 100, XYZ, decimal=7, ) shape = SpectralShape(400, 700, 5) # pylint: disable=E1102 cmfs = reshape_msds(self._cmfs, shape) np.testing.assert_almost_equal( sd_to_XYZ_integration( XYZ_to_sd_Meng2015(XYZ, cmfs, self._sd_D65), cmfs, self._sd_D65 ) / 100, XYZ, decimal=7, )
def msds_constant( k: Floating, labels: Sequence, shape: SpectralShape = SPECTRAL_SHAPE_DEFAULT, **kwargs: Any, ) -> MultiSpectralDistributions: """ Return the multi-spectral distributions with given labels and given spectral shape filled with constant :math:`k` values. Parameters ---------- k Constant :math:`k` to fill the multi-spectral distributions with. labels Names to use for the :class:`colour.SpectralDistribution` class instances. shape Spectral shape used to create the multi-spectral distributions. Other Parameters ---------------- kwargs {:class:`colour.MultiSpectralDistributions`}, See the documentation of the previously listed class. Returns ------- :class:`colour.MultiSpectralDistributions` Constant :math:`k` filled multi-spectral distributions. Notes ----- - By default, the multi-spectral distributions will use the shape given by :attr:`colour.SPECTRAL_SHAPE_DEFAULT` attribute. Examples -------- >>> msds = msds_constant(100, labels=['a', 'b', 'c']) >>> msds.shape SpectralShape(360.0, 780.0, 1.0) >>> msds[400] array([ 100., 100., 100.]) >>> msds.labels # doctest: +SKIP ['a', 'b', 'c'] """ settings = {"name": f"{k} Constant"} settings.update(kwargs) wavelengths = shape.range() values = full((len(wavelengths), len(labels)), k) return MultiSpectralDistributions(values, wavelengths, labels=labels, **settings)
def sd_gaussian_fwhm( peak_wavelength: Floating, fwhm: Floating, shape: SpectralShape = SPECTRAL_SHAPE_DEFAULT, **kwargs: Any, ) -> SpectralDistribution: """ Return a gaussian spectral distribution of given spectral shape at given peak wavelength and full width at half maximum. Parameters ---------- peak_wavelength Wavelength the gaussian spectral distribution will peak at. fwhm Full width at half maximum, i.e. width of the gaussian spectral distribution measured between those points on the *y* axis which are half the maximum amplitude. shape Spectral shape used to create the spectral distribution. Other Parameters ---------------- kwargs {:class:`colour.SpectralDistribution`}, See the documentation of the previously listed class. Returns ------- :class:`colour.SpectralDistribution` Gaussian spectral distribution. Notes ----- - By default, the spectral distribution will use the shape given by :attr:`colour.SPECTRAL_SHAPE_DEFAULT` attribute. Examples -------- >>> sd = sd_gaussian_fwhm(555, 25) >>> sd.shape SpectralShape(360.0, 780.0, 1.0) >>> sd[555] 1.0 >>> sd[530] # doctest: +ELLIPSIS 0.3678794... """ settings = {"name": f"{peak_wavelength}nm - {fwhm} FWHM - Gaussian"} settings.update(kwargs) wavelengths = shape.range() values = np.exp(-(((wavelengths - peak_wavelength) / fwhm)**2)) return SpectralDistribution(values, wavelengths, **settings)
def setUp(self): """ Initialises common tests attributes. """ self._cmfs = MSDS_CMFS_STANDARD_OBSERVER[ 'CIE 1931 2 Degree Standard Observer'].copy().align( SpectralShape(360, 780, 10)) self._sd_D65 = SDS_ILLUMINANTS['D65'].copy().align(self._cmfs.shape) self._sd_E = SDS_ILLUMINANTS['E'].copy().align(self._cmfs.shape)
def test_sd_CIE_standard_illuminant_A(self): """ Tests :func:`colour.colorimetry.illuminants.\ sd_CIE_standard_illuminant_A` definition. """ np.testing.assert_almost_equal(sd_CIE_standard_illuminant_A( SpectralShape(360, 830, 5)).values, A_DATA, decimal=7)
def setUp(self): """Initialise the common tests attributes.""" # pylint: disable=E1102 self._cmfs = reshape_msds( MSDS_CMFS["CIE 1931 2 Degree Standard Observer"], SpectralShape(360, 780, 10), ) self._sd_D65 = reshape_sd(SDS_ILLUMINANTS["D65"], self._cmfs.shape) self._sd_E = reshape_sd(SDS_ILLUMINANTS["E"], self._cmfs.shape)
def matrix_anomalous_trichromacy_Machado2009(cmfs, primaries, d_LMS): """ Computes the *Machado et al. (2009)* *CVD* matrix for given *LMS* cone fundamentals colour matching functions and display primaries tri-spectral distributions with given :math:`\\Delta_{LMS}` shift amount in nanometers to simulate anomalous trichromacy. Parameters ---------- cmfs : LMS_ConeFundamentals *LMS* cone fundamentals colour matching functions. primaries : RGB_DisplayPrimaries *RGB* display primaries tri-spectral distributions. d_LMS : array_like :math:`\\Delta_{LMS}` shift amount in nanometers. Notes ----- - Input *LMS* cone fundamentals colour matching functions interval is expected to be 1 nanometer, incompatible input will be interpolated at 1 nanometer interval. - Input :math:`\\Delta_{LMS}` shift amount is in domain [0, 20]. Returns ------- ndarray Anomalous trichromacy matrix. References ---------- :cite:`Colblindorb`, :cite:`Colblindora`, :cite:`Colblindorc`, :cite:`Machado2009` Examples -------- >>> from colour.characterisation import MSDS_DISPLAY_PRIMARIES >>> from colour.colorimetry import MSDS_CMFS_LMS >>> cmfs = MSDS_CMFS_LMS['Stockman & Sharpe 2 Degree Cone Fundamentals'] >>> d_LMS = np.array([15, 0, 0]) >>> primaries = MSDS_DISPLAY_PRIMARIES['Apple Studio Display'] >>> matrix_anomalous_trichromacy_Machado2009(cmfs, primaries, d_LMS) ... # doctest: +ELLIPSIS array([[-0.2777465..., 2.6515008..., -1.3737543...], [ 0.2718936..., 0.2004786..., 0.5276276...], [ 0.0064404..., 0.2592157..., 0.7343437...]]) """ if cmfs.shape.interval != 1: cmfs = cmfs.copy().interpolate(SpectralShape(interval=1)) M_n = matrix_RGB_to_WSYBRG(cmfs, primaries) cmfs_a = msds_cmfs_anomalous_trichromacy_Machado2009(cmfs, d_LMS) M_a = matrix_RGB_to_WSYBRG(cmfs_a, primaries) return matrix_dot(np.linalg.inv(M_n), M_a)
def sd_gaussian_normal( mu: Floating, sigma: Floating, shape: SpectralShape = SPECTRAL_SHAPE_DEFAULT, **kwargs: Any, ) -> SpectralDistribution: """ Return a gaussian spectral distribution of given spectral shape at given mean wavelength :math:`\\mu` and standard deviation :math:`sigma`. Parameters ---------- mu Mean wavelength :math:`\\mu` the gaussian spectral distribution will peak at. sigma Standard deviation :math:`sigma` of the gaussian spectral distribution. shape Spectral shape used to create the spectral distribution. Other Parameters ---------------- kwargs {:class:`colour.SpectralDistribution`}, See the documentation of the previously listed class. Returns ------- :class:`colour.SpectralDistribution` Gaussian spectral distribution. Notes ----- - By default, the spectral distribution will use the shape given by :attr:`colour.SPECTRAL_SHAPE_DEFAULT` attribute. Examples -------- >>> sd = sd_gaussian_normal(555, 25) >>> sd.shape SpectralShape(360.0, 780.0, 1.0) >>> sd[555] # doctest: +ELLIPSIS 1.0000000... >>> sd[530] # doctest: +ELLIPSIS 0.6065306... """ settings = {"name": f"{mu}nm - {sigma} Sigma - Gaussian"} settings.update(kwargs) wavelengths = shape.range() values = np.exp(-((wavelengths - mu)**2) / (2 * sigma**2)) return SpectralDistribution(values, wavelengths, **settings)
def test_tristimulus_weighting_factors_ASTME202211(self): """ Tests :func:`colour.colorimetry.tristimulus.\ tristimulus_weighting_factors_ASTME202211` definition. Notes ----- :attr:`A_CIE_1964_10_10_TWF`, :attr:`A_CIE_1964_10_20_TWF` and :attr:`D65_CIE_1931_2_20_TWF` attributes data is matching :cite:`ASTMInternational2015b`. References ---------- - :cite:`ASTMInternational2015b` """ cmfs = CMFS['CIE 1964 10 Degree Standard Observer'] wl = cmfs.shape.range() A = SpectralPowerDistribution(dict( zip(wl, CIE_standard_illuminant_A_function(wl))), name='A (360, 830, 1)') twf = tristimulus_weighting_factors_ASTME202211( cmfs, A, SpectralShape(360, 830, 10)) np.testing.assert_almost_equal(np.round(twf, 3), A_CIE_1964_10_10_TWF, decimal=3) twf = tristimulus_weighting_factors_ASTME202211( cmfs, A, SpectralShape(360, 830, 20)) np.testing.assert_almost_equal(np.round(twf, 3), A_CIE_1964_10_20_TWF, decimal=3) cmfs = CMFS['CIE 1931 2 Degree Standard Observer'] D65 = ILLUMINANTS_RELATIVE_SPDS['D65'].copy().align( cmfs.shape, interpolator=LinearInterpolator) twf = tristimulus_weighting_factors_ASTME202211( cmfs, D65, SpectralShape(360, 830, 20)) np.testing.assert_almost_equal(np.round(twf, 3), D65_CIE_1931_2_20_TWF, decimal=3)
def sd_mesopic_luminous_efficiency_function( Lp, source='Blue Heavy', method='MOVE', photopic_lef=PHOTOPIC_LEFS['CIE 1924 Photopic Standard Observer'], scotopic_lef=SCOTOPIC_LEFS['CIE 1951 Scotopic Standard Observer']): """ Returns the mesopic luminous efficiency function :math:`V_m(\\lambda)` for given photopic luminance :math:`L_p`. Parameters ---------- Lp : numeric Photopic luminance :math:`L_p`. source : unicode, optional **{'Blue Heavy', 'Red Heavy'}**, Light source colour temperature. method : unicode, optional **{'MOVE', 'LRC'}**, Method to calculate the weighting factor. photopic_lef : SpectralDistribution, optional :math:`V(\\lambda)` photopic luminous efficiency function. scotopic_lef : SpectralDistribution, optional :math:`V^\\prime(\\lambda)` scotopic luminous efficiency function. Returns ------- SpectralDistribution Mesopic luminous efficiency function :math:`V_m(\\lambda)`. References ---------- :cite:`Wikipedia2005d` Examples -------- >>> from colour.utilities import numpy_print_options >>> with numpy_print_options(suppress=True): ... sd_mesopic_luminous_efficiency_function(0.2) # doctest: +ELLIPSIS SpectralDistribution([[ 380. , 0.000424 ...], [ 381. , 0.0004781...], [ 382. , 0.0005399...], [ 383. , 0.0006122...], [ 384. , 0.0006961...], [ 385. , 0.0007929...], [ 386. , 0.000907 ...], [ 387. , 0.0010389...], [ 388. , 0.0011923...], [ 389. , 0.0013703...], [ 390. , 0.0015771...], [ 391. , 0.0018167...], [ 392. , 0.0020942...], [ 393. , 0.0024160...], [ 394. , 0.0027888...], [ 395. , 0.0032196...], [ 396. , 0.0037222...], [ 397. , 0.0042957...], [ 398. , 0.0049531...], [ 399. , 0.0057143...], [ 400. , 0.0065784...], [ 401. , 0.0075658...], [ 402. , 0.0086912...], [ 403. , 0.0099638...], [ 404. , 0.0114058...], [ 405. , 0.0130401...], [ 406. , 0.0148750...], [ 407. , 0.0169310...], [ 408. , 0.0192211...], [ 409. , 0.0217511...], [ 410. , 0.0245342...], [ 411. , 0.0275773...], [ 412. , 0.0309172...], [ 413. , 0.0345149...], [ 414. , 0.0383998...], [ 415. , 0.0425744...], [ 416. , 0.0471074...], [ 417. , 0.0519322...], [ 418. , 0.0570541...], [ 419. , 0.0625466...], [ 420. , 0.0683463...], [ 421. , 0.0745255...], [ 422. , 0.0809440...], [ 423. , 0.0877344...], [ 424. , 0.0948915...], [ 425. , 0.1022731...], [ 426. , 0.109877 ...], [ 427. , 0.1178421...], [ 428. , 0.1260316...], [ 429. , 0.1343772...], [ 430. , 0.143017 ...], [ 431. , 0.1518128...], [ 432. , 0.1608328...], [ 433. , 0.1700088...], [ 434. , 0.1792726...], [ 435. , 0.1886934...], [ 436. , 0.1982041...], [ 437. , 0.2078032...], [ 438. , 0.2174184...], [ 439. , 0.2271147...], [ 440. , 0.2368196...], [ 441. , 0.2464623...], [ 442. , 0.2561153...], [ 443. , 0.2657160...], [ 444. , 0.2753387...], [ 445. , 0.2848520...], [ 446. , 0.2944648...], [ 447. , 0.3034902...], [ 448. , 0.3132347...], [ 449. , 0.3223257...], [ 450. , 0.3314513...], [ 451. , 0.3406129...], [ 452. , 0.3498117...], [ 453. , 0.3583617...], [ 454. , 0.3676377...], [ 455. , 0.3762670...], [ 456. , 0.3849392...], [ 457. , 0.3936540...], [ 458. , 0.4024077...], [ 459. , 0.4111965...], [ 460. , 0.4193298...], [ 461. , 0.4281803...], [ 462. , 0.4363804...], [ 463. , 0.4453117...], [ 464. , 0.4542949...], [ 465. , 0.4626509...], [ 466. , 0.4717570...], [ 467. , 0.4809300...], [ 468. , 0.4901776...], [ 469. , 0.4995075...], [ 470. , 0.5096145...], [ 471. , 0.5191293...], [ 472. , 0.5294259...], [ 473. , 0.5391316...], [ 474. , 0.5496217...], [ 475. , 0.5602103...], [ 476. , 0.5702197...], [ 477. , 0.5810207...], [ 478. , 0.5919093...], [ 479. , 0.6028683...], [ 480. , 0.6138806...], [ 481. , 0.6249373...], [ 482. , 0.6360619...], [ 483. , 0.6465989...], [ 484. , 0.6579538...], [ 485. , 0.6687841...], [ 486. , 0.6797939...], [ 487. , 0.6909887...], [ 488. , 0.7023827...], [ 489. , 0.7133032...], [ 490. , 0.7244513...], [ 491. , 0.7358470...], [ 492. , 0.7468118...], [ 493. , 0.7580294...], [ 494. , 0.7694964...], [ 495. , 0.7805225...], [ 496. , 0.7917805...], [ 497. , 0.8026123...], [ 498. , 0.8130793...], [ 499. , 0.8239297...], [ 500. , 0.8352251...], [ 501. , 0.8456342...], [ 502. , 0.8564818...], [ 503. , 0.8676921...], [ 504. , 0.8785021...], [ 505. , 0.8881489...], [ 506. , 0.8986405...], [ 507. , 0.9079322...], [ 508. , 0.9174255...], [ 509. , 0.9257739...], [ 510. , 0.9350656...], [ 511. , 0.9432365...], [ 512. , 0.9509063...], [ 513. , 0.9586931...], [ 514. , 0.9658413...], [ 515. , 0.9722825...], [ 516. , 0.9779924...], [ 517. , 0.9836106...], [ 518. , 0.9883465...], [ 519. , 0.9920964...], [ 520. , 0.9954436...], [ 521. , 0.9976202...], [ 522. , 0.9993457...], [ 523. , 1. ...], [ 524. , 0.9996498...], [ 525. , 0.9990487...], [ 526. , 0.9975356...], [ 527. , 0.9957615...], [ 528. , 0.9930143...], [ 529. , 0.9899559...], [ 530. , 0.9858741...], [ 531. , 0.9814453...], [ 532. , 0.9766885...], [ 533. , 0.9709363...], [ 534. , 0.9648947...], [ 535. , 0.9585832...], [ 536. , 0.952012 ...], [ 537. , 0.9444916...], [ 538. , 0.9367089...], [ 539. , 0.9293506...], [ 540. , 0.9210429...], [ 541. , 0.9124772...], [ 542. , 0.9036604...], [ 543. , 0.8945958...], [ 544. , 0.8845999...], [ 545. , 0.8750500...], [ 546. , 0.8659457...], [ 547. , 0.8559224...], [ 548. , 0.8456846...], [ 549. , 0.8352499...], [ 550. , 0.8253229...], [ 551. , 0.8152079...], [ 552. , 0.8042205...], [ 553. , 0.7944209...], [ 554. , 0.7837466...], [ 555. , 0.7735680...], [ 556. , 0.7627808...], [ 557. , 0.7522710...], [ 558. , 0.7417549...], [ 559. , 0.7312909...], [ 560. , 0.7207983...], [ 561. , 0.7101939...], [ 562. , 0.6996362...], [ 563. , 0.6890656...], [ 564. , 0.6785599...], [ 565. , 0.6680593...], [ 566. , 0.6575697...], [ 567. , 0.6471578...], [ 568. , 0.6368208...], [ 569. , 0.6264871...], [ 570. , 0.6161541...], [ 571. , 0.6058896...], [ 572. , 0.5957000...], [ 573. , 0.5855937...], [ 574. , 0.5754412...], [ 575. , 0.5653883...], [ 576. , 0.5553742...], [ 577. , 0.5454680...], [ 578. , 0.5355972...], [ 579. , 0.5258267...], [ 580. , 0.5160152...], [ 581. , 0.5062322...], [ 582. , 0.4965595...], [ 583. , 0.4868746...], [ 584. , 0.4773299...], [ 585. , 0.4678028...], [ 586. , 0.4583704...], [ 587. , 0.4489722...], [ 588. , 0.4397606...], [ 589. , 0.4306131...], [ 590. , 0.4215446...], [ 591. , 0.4125681...], [ 592. , 0.4037550...], [ 593. , 0.3950359...], [ 594. , 0.3864104...], [ 595. , 0.3778777...], [ 596. , 0.3694405...], [ 597. , 0.3611074...], [ 598. , 0.3528596...], [ 599. , 0.3447056...], [ 600. , 0.3366470...], [ 601. , 0.3286917...], [ 602. , 0.3208410...], [ 603. , 0.3130808...], [ 604. , 0.3054105...], [ 605. , 0.2978225...], [ 606. , 0.2903027...], [ 607. , 0.2828727...], [ 608. , 0.2755311...], [ 609. , 0.2682900...], [ 610. , 0.2611478...], [ 611. , 0.2541176...], [ 612. , 0.2471885...], [ 613. , 0.2403570...], [ 614. , 0.2336057...], [ 615. , 0.2269379...], [ 616. , 0.2203527...], [ 617. , 0.2138465...], [ 618. , 0.2073946...], [ 619. , 0.2009789...], [ 620. , 0.1945818...], [ 621. , 0.1881943...], [ 622. , 0.1818226...], [ 623. , 0.1754987...], [ 624. , 0.1692476...], [ 625. , 0.1630876...], [ 626. , 0.1570257...], [ 627. , 0.151071 ...], [ 628. , 0.1452469...], [ 629. , 0.1395845...], [ 630. , 0.1341087...], [ 631. , 0.1288408...], [ 632. , 0.1237666...], [ 633. , 0.1188631...], [ 634. , 0.1141075...], [ 635. , 0.1094766...], [ 636. , 0.1049613...], [ 637. , 0.1005679...], [ 638. , 0.0962924...], [ 639. , 0.0921296...], [ 640. , 0.0880778...], [ 641. , 0.0841306...], [ 642. , 0.0802887...], [ 643. , 0.0765559...], [ 644. , 0.0729367...], [ 645. , 0.0694345...], [ 646. , 0.0660491...], [ 647. , 0.0627792...], [ 648. , 0.0596278...], [ 649. , 0.0565970...], [ 650. , 0.0536896...], [ 651. , 0.0509068...], [ 652. , 0.0482444...], [ 653. , 0.0456951...], [ 654. , 0.0432510...], [ 655. , 0.0409052...], [ 656. , 0.0386537...], [ 657. , 0.0364955...], [ 658. , 0.0344285...], [ 659. , 0.0324501...], [ 660. , 0.0305579...], [ 661. , 0.0287496...], [ 662. , 0.0270233...], [ 663. , 0.0253776...], [ 664. , 0.0238113...], [ 665. , 0.0223226...], [ 666. , 0.0209086...], [ 667. , 0.0195688...], [ 668. , 0.0183056...], [ 669. , 0.0171216...], [ 670. , 0.0160192...], [ 671. , 0.0149986...], [ 672. , 0.0140537...], [ 673. , 0.0131784...], [ 674. , 0.0123662...], [ 675. , 0.0116107...], [ 676. , 0.0109098...], [ 677. , 0.0102587...], [ 678. , 0.0096476...], [ 679. , 0.0090665...], [ 680. , 0.0085053...], [ 681. , 0.0079567...], [ 682. , 0.0074229...], [ 683. , 0.0069094...], [ 684. , 0.0064213...], [ 685. , 0.0059637...], [ 686. , 0.0055377...], [ 687. , 0.0051402...], [ 688. , 0.00477 ...], [ 689. , 0.0044263...], [ 690. , 0.0041081...], [ 691. , 0.0038149...], [ 692. , 0.0035456...], [ 693. , 0.0032984...], [ 694. , 0.0030718...], [ 695. , 0.0028639...], [ 696. , 0.0026738...], [ 697. , 0.0025000...], [ 698. , 0.0023401...], [ 699. , 0.0021918...], [ 700. , 0.0020526...], [ 701. , 0.0019207...], [ 702. , 0.001796 ...], [ 703. , 0.0016784...], [ 704. , 0.0015683...], [ 705. , 0.0014657...], [ 706. , 0.0013702...], [ 707. , 0.001281 ...], [ 708. , 0.0011976...], [ 709. , 0.0011195...], [ 710. , 0.0010464...], [ 711. , 0.0009776...], [ 712. , 0.0009131...], [ 713. , 0.0008525...], [ 714. , 0.0007958...], [ 715. , 0.0007427...], [ 716. , 0.0006929...], [ 717. , 0.0006462...], [ 718. , 0.0006026...], [ 719. , 0.0005619...], [ 720. , 0.0005240...], [ 721. , 0.0004888...], [ 722. , 0.0004561...], [ 723. , 0.0004255...], [ 724. , 0.0003971...], [ 725. , 0.0003704...], [ 726. , 0.0003455...], [ 727. , 0.0003221...], [ 728. , 0.0003001...], [ 729. , 0.0002796...], [ 730. , 0.0002604...], [ 731. , 0.0002423...], [ 732. , 0.0002254...], [ 733. , 0.0002095...], [ 734. , 0.0001947...], [ 735. , 0.0001809...], [ 736. , 0.0001680...], [ 737. , 0.0001560...], [ 738. , 0.0001449...], [ 739. , 0.0001345...], [ 740. , 0.0001249...], [ 741. , 0.0001159...], [ 742. , 0.0001076...], [ 743. , 0.0000999...], [ 744. , 0.0000927...], [ 745. , 0.0000862...], [ 746. , 0.0000801...], [ 747. , 0.0000745...], [ 748. , 0.0000693...], [ 749. , 0.0000646...], [ 750. , 0.0000602...], [ 751. , 0.0000561...], [ 752. , 0.0000523...], [ 753. , 0.0000488...], [ 754. , 0.0000456...], [ 755. , 0.0000425...], [ 756. , 0.0000397...], [ 757. , 0.0000370...], [ 758. , 0.0000346...], [ 759. , 0.0000322...], [ 760. , 0.0000301...], [ 761. , 0.0000281...], [ 762. , 0.0000262...], [ 763. , 0.0000244...], [ 764. , 0.0000228...], [ 765. , 0.0000213...], [ 766. , 0.0000198...], [ 767. , 0.0000185...], [ 768. , 0.0000173...], [ 769. , 0.0000161...], [ 770. , 0.0000150...], [ 771. , 0.0000140...], [ 772. , 0.0000131...], [ 773. , 0.0000122...], [ 774. , 0.0000114...], [ 775. , 0.0000106...], [ 776. , 0.0000099...], [ 777. , 0.0000092...], [ 778. , 0.0000086...], [ 779. , 0.0000080...], [ 780. , 0.0000075...]], interpolator=SpragueInterpolator, interpolator_args={}, extrapolator=Extrapolator, extrapolator_args={...}) """ photopic_lef_shape = photopic_lef.shape scotopic_lef_shape = scotopic_lef.shape shape = SpectralShape( max(photopic_lef_shape.start, scotopic_lef_shape.start), min(photopic_lef_shape.end, scotopic_lef_shape.end), max(photopic_lef_shape.interval, scotopic_lef_shape.interval)) wavelengths = shape.range() sd_data = dict( zip( wavelengths, mesopic_weighting_function(wavelengths, Lp, source, method, photopic_lef, scotopic_lef))) sd = SpectralDistribution( sd_data, name='{0} Lp Mesopic Luminous Efficiency Function'.format(Lp)) return sd.normalise()
def mesopic_luminous_efficiency_function( Lp, source='Blue Heavy', method='MOVE', photopic_lef=PHOTOPIC_LEFS.get( 'CIE 1924 Photopic Standard Observer'), scotopic_lef=SCOTOPIC_LEFS.get( 'CIE 1951 Scotopic Standard Observer')): """ Returns the mesopic luminous efficiency function :math:`V_m(\lambda)` for given photopic luminance :math:`L_p`. Parameters ---------- Lp : numeric Photopic luminance :math:`L_p`. source : unicode, optional **{'Blue Heavy', 'Red Heavy'}**, Light source colour temperature. method : unicode, optional **{'MOVE', 'LRC'}**, Method to calculate the weighting factor. photopic_lef : SpectralPowerDistribution, optional :math:`V(\lambda)` photopic luminous efficiency function. scotopic_lef : SpectralPowerDistribution, optional :math:`V^\prime(\lambda)` scotopic luminous efficiency function. Returns ------- SpectralPowerDistribution Mesopic luminous efficiency function :math:`V_m(\lambda)`. Examples -------- >>> print(mesopic_luminous_efficiency_function(0.2)) SpectralPowerDistribution(\ '0.2 Lp Mesopic Luminous Efficiency Function', (380.0, 780.0, 1.0)) """ photopic_lef_shape = photopic_lef.shape scotopic_lef_shape = scotopic_lef.shape shape = SpectralShape( max(photopic_lef_shape.start, scotopic_lef_shape.start), min(photopic_lef_shape.end, scotopic_lef_shape.end), max(photopic_lef_shape.interval, scotopic_lef_shape.interval)) wavelengths = shape.range() spd_data = dict(zip(wavelengths, mesopic_weighting_function( wavelengths, Lp, source, method, photopic_lef, scotopic_lef))) spd = SpectralPowerDistribution( '{0} Lp Mesopic Luminous Efficiency Function'.format(Lp), spd_data) return spd.normalise()