def test_spectral_to_XYZ(self): """ Tests :func:`colour.colorimetry.tristimulus.spectral_to_XYZ` definition. """ cmfs = CMFS.get('CIE 1931 2 Degree Standard Observer') np.testing.assert_almost_equal( spectral_to_XYZ( RELATIVE_SPD_DATA.zeros(cmfs.shape), cmfs, ILLUMINANTS_RELATIVE_SPDS.get('A').clone().zeros(cmfs.shape)), np.array([14.46371626, 10.85832347, 2.04664796]), decimal=7) cmfs = CMFS.get('CIE 1964 10 Degree Standard Observer') np.testing.assert_almost_equal( spectral_to_XYZ( RELATIVE_SPD_DATA.zeros(cmfs.shape), cmfs, ILLUMINANTS_RELATIVE_SPDS.get('C').clone().zeros(cmfs.shape)), np.array([10.7704252, 9.44870313, 6.62742289]), decimal=7) np.testing.assert_almost_equal( spectral_to_XYZ( RELATIVE_SPD_DATA.zeros(cmfs.shape), cmfs, ILLUMINANTS_RELATIVE_SPDS.get('F2').clone().zeros(cmfs.shape)), np.array([11.57830745, 9.98744967, 3.95396539]), decimal=7)
def test_colour_quality_scale(self): """ Tests :func:`colour.quality.cqs.colour_quality_scale` definition. """ self.assertAlmostEqual(colour_quality_scale( ILLUMINANTS_RELATIVE_SPDS.get('F1')), 75.342060410089019, places=7) self.assertAlmostEqual(colour_quality_scale( ILLUMINANTS_RELATIVE_SPDS.get('F2')), 64.686058037115245, places=7) self.assertAlmostEqual(colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('Neodimium Incandescent')), 87.659381222366406, places=7) self.assertAlmostEqual(colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('F32T8/TL841 (Triphosphor)')), 83.179667074336621, places=7) self.assertAlmostEqual(colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('H38HT-100 (Mercury)')), 22.869936010810584, places=7) self.assertAlmostEqual(colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('Luxeon WW 2880')), 84.883777827678131, places=7)
def get_illuminant(illuminant): """ Returns the illuminant with given name. Parameters ---------- illuminant : unicode Illuminant name. Returns ------- SpectralPowerDistribution Illuminant. Raises ------ KeyError If the given illuminant is not found in the factory illuminants. """ illuminant, name = ILLUMINANTS_RELATIVE_SPDS.get(illuminant), illuminant if illuminant is None: raise KeyError( '"{0}" not found in factory illuminants: "{1}".'.format( name, ', '.join(sorted(ILLUMINANTS_RELATIVE_SPDS.keys())))) return illuminant
def get_illuminant(illuminant): """ Returns the illuminant with given name. Parameters ---------- illuminant : unicode Illuminant name. Returns ------- SpectralPowerDistribution Illuminant. Raises ------ KeyError If the given illuminant is not found in the factory illuminants. """ illuminant, name = ILLUMINANTS_RELATIVE_SPDS.get(illuminant), illuminant if illuminant is None: raise KeyError('"{0}" not found in factory illuminants: "{1}".'.format( name, ', '.join(sorted(ILLUMINANTS_RELATIVE_SPDS.keys())))) return illuminant
def test_colour_quality_scale(self): """ Tests :func:`colour.quality.cqs.colour_quality_scale` definition. """ self.assertAlmostEqual(colour_quality_scale( ILLUMINANTS_RELATIVE_SPDS.get('F1')), 75.334361226715345, places=7) self.assertAlmostEqual(colour_quality_scale( ILLUMINANTS_RELATIVE_SPDS.get('F2')), 64.678111793396397, places=7) self.assertAlmostEqual(colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('Neodimium Incandescent')), 87.655549804699419, places=7) self.assertAlmostEqual(colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('F32T8/TL841 (Triphosphor)')), 83.175799064274571, places=7) self.assertAlmostEqual(colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('H38HT-100 (Mercury)')), 22.847928690340929, places=7) self.assertAlmostEqual(colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('Luxeon WW 2880')), 84.880575409680162, places=7)
def test_spectral_to_XYZ_integration(self): """ Tests :func:`colour.colorimetry.tristimulus.\ spectral_to_XYZ_integration` definition. """ cmfs = CMFS.get('CIE 1931 2 Degree Standard Observer') np.testing.assert_almost_equal( spectral_to_XYZ_integration( SAMPLE_SPD, cmfs, ILLUMINANTS_RELATIVE_SPDS.get('A')), np.array([14.46365624, 10.85827910, 2.04662343]), decimal=7) cmfs = CMFS.get('CIE 1964 10 Degree Standard Observer') np.testing.assert_almost_equal( spectral_to_XYZ_integration( SAMPLE_SPD, cmfs, ILLUMINANTS_RELATIVE_SPDS.get('C')), np.array([10.77031004, 9.44863775, 6.62745989]), decimal=7) np.testing.assert_almost_equal( spectral_to_XYZ_integration( SAMPLE_SPD, cmfs, ILLUMINANTS_RELATIVE_SPDS.get('F2')), np.array([11.57834054, 9.98738373, 3.95462625]), decimal=7)
def test_luminous_efficacy(self): """ Tests :func:`colour.colorimetry.photometry.luminous_efficacy` definition. """ self.assertAlmostEqual( luminous_efficacy( ILLUMINANTS_RELATIVE_SPDS.get('F2').clone().normalise()), 336.83937176, places=7) self.assertAlmostEqual( luminous_efficacy(LIGHT_SOURCES_RELATIVE_SPDS.get( 'Neodimium Incandescent')), 136.21708032, places=7) self.assertAlmostEqual( luminous_efficacy(LIGHT_SOURCES_RELATIVE_SPDS.get( 'F32T8/TL841 (Triphosphor)')), 348.88267549, places=7) spd = zeros_spd() spd[555] = 1 self.assertAlmostEqual( luminous_efficacy(spd), 683.00000000, places=7)
def test_colour_rendering_index(self): """ Tests :func:`colour.quality.cri.colour_rendering_index` definition. """ self.assertAlmostEqual(colour_rendering_index( ILLUMINANTS_RELATIVE_SPDS.get('F2')), 64.1507331494, places=7) self.assertAlmostEqual(colour_rendering_index( ILLUMINANTS_RELATIVE_SPDS.get('A')), 99.9978916846, places=7) self.assertAlmostEqual(colour_rendering_index( SpectralPowerDistribution('Sample', SAMPLE_SPD_DATA)), 70.805836753503698, places=7)
def test_colour_rendering_index(self): """ Tests :func:`colour.quality.cri.colour_rendering_index` definition. """ self.assertAlmostEqual(colour_rendering_index( ILLUMINANTS_RELATIVE_SPDS.get('F2')), 64.149547892010048, places=7) self.assertAlmostEqual(colour_rendering_index( ILLUMINANTS_RELATIVE_SPDS.get('A')), 99.996736287811871, places=7) self.assertAlmostEqual(colour_rendering_index( SpectralPowerDistribution('Sample', SAMPLE_SPD_DATA)), 70.802983235772103, places=7)
def test_colour_rendering_index(self): """ Tests :func:`colour.quality.cri.colour_rendering_index` definition. """ self.assertAlmostEqual( colour_rendering_index(ILLUMINANTS_RELATIVE_SPDS.get('F2')), 64.149547892010048, places=7) self.assertAlmostEqual( colour_rendering_index(ILLUMINANTS_RELATIVE_SPDS.get('A')), 99.996736287811871, places=7) self.assertAlmostEqual( colour_rendering_index(SpectralPowerDistribution( 'Sample', SAMPLE_SPD_DATA)), 70.802983235772103, places=7)
def test_colour_rendering_index(self): """ Tests :func:`colour.quality.cri.colour_rendering_index` definition. """ self.assertAlmostEqual( colour_rendering_index(ILLUMINANTS_RELATIVE_SPDS.get('F2')), 64.1507331494, places=7) self.assertAlmostEqual( colour_rendering_index(ILLUMINANTS_RELATIVE_SPDS.get('A')), 99.9978916846, places=7) self.assertAlmostEqual( colour_rendering_index(SpectralPowerDistribution( 'Sample', SAMPLE_SPD_DATA)), 70.805836753503698, places=7)
def test_colour_quality_scale(self): """ Tests :func:`colour.quality.cqs.colour_quality_scale` definition. """ self.assertAlmostEqual( colour_quality_scale( ILLUMINANTS_RELATIVE_SPDS.get('F1')), 75.334361226715345, places=7) self.assertAlmostEqual( colour_quality_scale( ILLUMINANTS_RELATIVE_SPDS.get('F2')), 64.678111793396397, places=7) self.assertAlmostEqual( colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('Neodimium Incandescent')), 87.655549804699419, places=7) self.assertAlmostEqual( colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('F32T8/TL841 (Triphosphor)')), 83.175799064274571, places=7) self.assertAlmostEqual( colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('H38HT-100 (Mercury)')), 22.847928690340929, places=7) self.assertAlmostEqual( colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('Luxeon WW 2880')), 84.880575409680162, places=7)
def test_colour_quality_scale(self): """ Tests :func:`colour.quality.cqs.colour_quality_scale` definition. """ self.assertAlmostEqual( colour_quality_scale( ILLUMINANTS_RELATIVE_SPDS.get('F1')), 75.342060410089019, places=7) self.assertAlmostEqual( colour_quality_scale( ILLUMINANTS_RELATIVE_SPDS.get('F2')), 64.686058037115245, places=7) self.assertAlmostEqual( colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('Neodimium Incandescent')), 87.659381222366406, places=7) self.assertAlmostEqual( colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('F32T8/TL841 (Triphosphor)')), 83.179667074336621, places=7) self.assertAlmostEqual( colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('H38HT-100 (Mercury)')), 22.869936010810584, places=7) self.assertAlmostEqual( colour_quality_scale( LIGHT_SOURCES_RELATIVE_SPDS.get('Luxeon WW 2880')), 84.883777827678131, places=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_luminous_flux(self): """ Tests :func:`colour.colorimetry.photometry.luminous_flux` definition. """ self.assertAlmostEqual(luminous_flux( ILLUMINANTS_RELATIVE_SPDS.get('F2').clone().normalise()), 28588.73612977, places=7) self.assertAlmostEqual(luminous_flux( LIGHT_SOURCES_RELATIVE_SPDS.get('Neodimium Incandescent')), 23807.65552737, places=7) self.assertAlmostEqual(luminous_flux( LIGHT_SOURCES_RELATIVE_SPDS.get('F32T8/TL841 (Triphosphor)')), 13090.06759053, places=7)
def test_luminous_efficiency(self): """ Tests :func:`colour.colorimetry.photometry.luminous_efficiency` definition. """ self.assertAlmostEqual(luminous_efficiency( ILLUMINANTS_RELATIVE_SPDS.get('F2').clone().normalise()), 0.49317624, places=7) self.assertAlmostEqual(luminous_efficiency( LIGHT_SOURCES_RELATIVE_SPDS.get('Neodimium Incandescent')), 0.19943936, places=7) self.assertAlmostEqual(luminous_efficiency( LIGHT_SOURCES_RELATIVE_SPDS.get('F32T8/TL841 (Triphosphor)')), 0.51080919, places=7)
def test_luminous_flux(self): """ Tests :func:`colour.colorimetry.photometry.luminous_flux` definition. """ self.assertAlmostEqual( luminous_flux( ILLUMINANTS_RELATIVE_SPDS.get('F2').clone().normalise()), 28588.736129772711, places=7) self.assertAlmostEqual( luminous_flux(LIGHT_SOURCES_RELATIVE_SPDS.get( 'Neodimium Incandescent')), 23807.655527367198, places=7) self.assertAlmostEqual( luminous_flux(LIGHT_SOURCES_RELATIVE_SPDS.get( 'F32T8/TL841 (Triphosphor)')), 13090.067590531509, places=7)
def test_luminous_efficacy(self): """ Tests :func:`colour.colorimetry.photometry.luminous_efficacy` definition. """ self.assertAlmostEqual( luminous_efficacy( ILLUMINANTS_RELATIVE_SPDS.get('F2').clone().normalise()), 0.493176239758, places=7) self.assertAlmostEqual( luminous_efficacy(LIGHT_SOURCES_RELATIVE_SPDS.get( 'Neodimium Incandescent')), 0.199439356245, places=7) self.assertAlmostEqual( luminous_efficacy(LIGHT_SOURCES_RELATIVE_SPDS.get( 'F32T8/TL841 (Triphosphor)')), 0.510809188121, places=7)
def test_luminous_efficacy(self): """ Tests :func:`colour.colorimetry.photometry.luminous_efficacy` definition. """ self.assertAlmostEqual(luminous_efficacy( ILLUMINANTS_RELATIVE_SPDS.get('F2').clone().normalise()), 336.83937176, places=7) self.assertAlmostEqual(luminous_efficacy( LIGHT_SOURCES_RELATIVE_SPDS.get('Neodimium Incandescent')), 136.21708032, places=7) self.assertAlmostEqual(luminous_efficacy( LIGHT_SOURCES_RELATIVE_SPDS.get('F32T8/TL841 (Triphosphor)')), 348.88267549, places=7) spd = zeros_spd() spd[555] = 1 self.assertAlmostEqual(luminous_efficacy(spd), 683.00000000, places=7)
def multi_spd_plot(spds, cmfs='CIE 1931 2 Degree Standard Observer', use_spds_colours=False, normalise_spds_colours=False, **kwargs): """ Plots given spectral power distributions. Parameters ---------- spds : list, optional Spectral power distributions to plot. cmfs : unicode, optional Standard observer colour matching functions used for spectrum creation. use_spds_colours : bool, optional Use spectral power distributions colours. normalise_spds_colours : bool Should spectral power distributions colours normalised. \*\*kwargs : \*\* Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> from colour import SpectralPowerDistribution >>> data1 = {400: 0.0641, 420: 0.0645, 440: 0.0562} >>> data2 = {400: 0.134, 420: 0.789, 440: 1.289} >>> spd1 = SpectralPowerDistribution('Custom1', data1) >>> spd2 = SpectralPowerDistribution('Custom2', data2) >>> multi_spd_plot([spd1, spd2]) # doctest: +SKIP True """ cmfs, name = get_cmfs(cmfs), cmfs if use_spds_colours: illuminant = ILLUMINANTS_RELATIVE_SPDS.get('D65') x_limit_min, x_limit_max, y_limit_min, y_limit_max = [], [], [], [] for spd in spds: wavelengths, values = tuple(zip(*[(key, value) for key, value in spd])) shape = spd.shape x_limit_min.append(shape.start) x_limit_max.append(shape.end) y_limit_min.append(min(values)) y_limit_max.append(max(values)) matplotlib.pyplot.rc("axes", color_cycle=["r", "g", "b", "y"]) if use_spds_colours: XYZ = spectral_to_XYZ(spd, cmfs, illuminant) / 100 if normalise_spds_colours: XYZ = normalise(XYZ, clip=False) RGB = np.clip(XYZ_to_sRGB(XYZ), 0, 1) pylab.plot(wavelengths, values, color=RGB, label=spd.name, linewidth=2) else: pylab.plot(wavelengths, values, label=spd.name, linewidth=2) settings = { 'x_label': u'Wavelength λ (nm)', 'y_label': 'Spectral Power Distribution', 'x_tighten': True, 'legend': True, 'legend_location': 'upper left', 'x_ticker': True, 'y_ticker': True, 'limits': [ min(x_limit_min), max(x_limit_max), min(y_limit_min), max(y_limit_max) ] } settings.update(kwargs) bounding_box(**settings) aspect(**settings) return display(**settings)
def multi_spd_plot(spds, cmfs='CIE 1931 2 Degree Standard Observer', use_spds_colours=False, normalise_spds_colours=False, **kwargs): """ Plots given spectral power distributions. Parameters ---------- spds : list Spectral power distributions to plot. cmfs : unicode, optional Standard observer colour matching functions used for spectrum creation. use_spds_colours : bool, optional Use spectral power distributions colours. normalise_spds_colours : bool Should spectral power distributions colours normalised. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> from colour import SpectralPowerDistribution >>> data1 = {400: 0.0641, 420: 0.0645, 440: 0.0562} >>> data2 = {400: 0.134, 420: 0.789, 440: 1.289} >>> spd1 = SpectralPowerDistribution('Custom1', data1) >>> spd2 = SpectralPowerDistribution('Custom2', data2) >>> multi_spd_plot([spd1, spd2]) # doctest: +SKIP """ canvas(**kwargs) cmfs = get_cmfs(cmfs) if use_spds_colours: illuminant = ILLUMINANTS_RELATIVE_SPDS.get('D65') x_limit_min, x_limit_max, y_limit_min, y_limit_max = [], [], [], [] for spd in spds: wavelengths, values = tuple(zip(*spd.items)) shape = spd.shape x_limit_min.append(shape.start) x_limit_max.append(shape.end) y_limit_min.append(min(values)) y_limit_max.append(max(values)) if use_spds_colours: XYZ = spectral_to_XYZ(spd, cmfs, illuminant) / 100 if normalise_spds_colours: XYZ = normalise_maximum(XYZ, clip=False) RGB = np.clip(XYZ_to_sRGB(XYZ), 0, 1) pylab.plot(wavelengths, values, color=RGB, label=spd.title, linewidth=2) else: pylab.plot(wavelengths, values, label=spd.title, linewidth=2) settings = { 'x_label': 'Wavelength $\\lambda$ (nm)', 'y_label': 'Spectral Power Distribution', 'x_tighten': True, 'legend': True, 'legend_location': 'upper left', 'limits': (min(x_limit_min), max(x_limit_max), min(y_limit_min), max(y_limit_max)) } settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def spectral_to_aces_relative_exposure_values( spd, illuminant=ILLUMINANTS_RELATIVE_SPDS.get('D60')): """ Converts given spectral power distribution to *ACES2065-1* colourspace relative exposure values. Parameters ---------- spd : SpectralPowerDistribution Spectral power distribution. illuminant : SpectralPowerDistribution, optional *Illuminant* spectral power distribution. Returns ------- ndarray, (3,) *ACES2065-1* colourspace relative exposure values array. Notes ----- - Output *ACES2065-1* colourspace relative exposure values array is in range [0, 1]. See Also -------- :func:`colour.colorimetry.tristimulus.spectral_to_XYZ` References ---------- Examples -------- >>> from colour import COLOURCHECKERS_SPDS >>> spd = COLOURCHECKERS_SPDS['ColorChecker N Ohta']['dark skin'] >>> spectral_to_aces_relative_exposure_values(spd) # doctest: +ELLIPSIS array([ 0.1187697..., 0.0870866..., 0.0589442...]) """ shape = ACES_RICD.shape if spd.shape != ACES_RICD.shape: spd = spd.clone().align(shape) if illuminant.shape != ACES_RICD.shape: illuminant = illuminant.clone().align(shape) spd = spd.values illuminant = illuminant.values r_bar, g_bar, b_bar = (ACES_RICD.r_bar.values, ACES_RICD.g_bar.values, ACES_RICD.b_bar.values) def k(x, y): """ Computes the :math:`K_r`, :math:`K_g` or :math:`K_b` scale factors. """ return 1 / np.sum(x * y) k_r = k(illuminant, r_bar) k_g = k(illuminant, g_bar) k_b = k(illuminant, b_bar) E_r = k_r * np.sum(illuminant * spd * r_bar) E_g = k_g * np.sum(illuminant * spd * g_bar) E_b = k_b * np.sum(illuminant * spd * b_bar) E_rgb = np.array([E_r, E_g, E_b]) # Accounting for flare. E_rgb += FLARE_PERCENTAGE E_rgb *= S_FLARE_FACTOR return E_rgb
def multi_spd_plot(spds, cmfs='CIE 1931 2 Degree Standard Observer', use_spds_colours=False, normalise_spds_colours=False, **kwargs): """ Plots given spectral power distributions. Parameters ---------- spds : list Spectral power distributions to plot. cmfs : unicode, optional Standard observer colour matching functions used for spectrum creation. use_spds_colours : bool, optional Use spectral power distributions colours. normalise_spds_colours : bool Should spectral power distributions colours normalised. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> from colour import SpectralPowerDistribution >>> data1 = {400: 0.0641, 420: 0.0645, 440: 0.0562} >>> data2 = {400: 0.134, 420: 0.789, 440: 1.289} >>> spd1 = SpectralPowerDistribution('Custom1', data1) >>> spd2 = SpectralPowerDistribution('Custom2', data2) >>> multi_spd_plot([spd1, spd2]) # doctest: +SKIP True """ canvas(**kwargs) cmfs = get_cmfs(cmfs) if use_spds_colours: illuminant = ILLUMINANTS_RELATIVE_SPDS.get('D65') x_limit_min, x_limit_max, y_limit_min, y_limit_max = [], [], [], [] for spd in spds: wavelengths, values = tuple(zip(*spd.items)) shape = spd.shape x_limit_min.append(shape.start) x_limit_max.append(shape.end) y_limit_min.append(min(values)) y_limit_max.append(max(values)) if use_spds_colours: XYZ = spectral_to_XYZ(spd, cmfs, illuminant) / 100 if normalise_spds_colours: XYZ = normalise(XYZ, clip=False) RGB = np.clip(XYZ_to_sRGB(XYZ), 0, 1) pylab.plot(wavelengths, values, color=RGB, label=spd.title, linewidth=2) else: pylab.plot(wavelengths, values, label=spd.title, linewidth=2) settings = { 'x_label': 'Wavelength $\\lambda$ (nm)', 'y_label': 'Spectral Power Distribution', 'x_tighten': True, 'legend': True, 'legend_location': 'upper left', 'limits': (min(x_limit_min), max(x_limit_max), min(y_limit_min), max(y_limit_max))} settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def spectral_to_aces_relative_exposure_values( spd, illuminant=ILLUMINANTS_RELATIVE_SPDS.get('D60')): """ Converts given spectral power distribution to *ACES RGB* colourspace relative exposure values. Parameters ---------- spd : SpectralPowerDistribution Spectral power distribution. illuminant : SpectralPowerDistribution, optional *Illuminant* spectral power distribution. Returns ------- ndarray, (3,) *ACES RGB* colourspace relative exposure values matrix. Notes ----- - Output *ACES RGB* colourspace relative exposure values matrix is in domain [0, 1]. See Also -------- :func:`colour.colorimetry.tristimulus.spectral_to_XYZ` References ---------- Examples -------- >>> from colour import COLOURCHECKERS_SPDS >>> spd = COLOURCHECKERS_SPDS['ColorChecker N Ohta']['dark skin'] >>> spectral_to_aces_relative_exposure_values(spd) # doctest: +ELLIPSIS array([ 0.1187697..., 0.0870866..., 0.0589442...]) """ shape = ACES_RICD.shape if spd.shape != ACES_RICD.shape: spd = spd.clone().align(shape) if illuminant.shape != ACES_RICD.shape: illuminant = illuminant.clone().align(shape) spd = spd.values illuminant = illuminant.values r_bar, g_bar, b_bar = (ACES_RICD.r_bar.values, ACES_RICD.g_bar.values, ACES_RICD.b_bar.values) k = lambda x, y: 1 / np.sum(x * y) k_r = k(illuminant, r_bar) k_g = k(illuminant, g_bar) k_b = k(illuminant, b_bar) E_r = k_r * np.sum(illuminant * spd * r_bar) E_g = k_g * np.sum(illuminant * spd * g_bar) E_b = k_b * np.sum(illuminant * spd * b_bar) E_rgb = np.array([E_r, E_g, E_b]) # Accounting for flare. E_rgb += FLARE_PERCENTAGE E_rgb *= S_FLARE_FACTOR return E_rgb