def _CCT_to_uv_Ohno2013( CCT_D_uv, cmfs=MSDS_CMFS_STANDARD_OBSERVER['CIE 1931 2 Degree Standard Observer'] ): """ Returns the *CIE UCS* colourspace *uv* chromaticity coordinates from given correlated colour temperature :math:`T_{cp}`, :math:`\\Delta_{uv}` and colour matching functions using *Ohno (2013)* method. Parameters ---------- CCT_D_uv : ndarray Correlated colour temperature :math:`T_{cp}`, :math:`\\Delta_{uv}`. cmfs : XYZ_ColourMatchingFunctions, optional Standard observer colour matching functions. Returns ------- ndarray *CIE UCS* colourspace *uv* chromaticity coordinates. """ CCT, D_uv = tsplit(CCT_D_uv) cmfs = cmfs.copy().trim(SPECTRAL_SHAPE_DEFAULT) shape = cmfs.shape delta = 0.01 sd = sd_blackbody(CCT, shape) XYZ = sd_to_XYZ(sd, cmfs) XYZ *= 1 / np.max(XYZ) UVW = XYZ_to_UCS(XYZ) u0, v0 = UCS_to_uv(UVW) if D_uv == 0: return np.array([u0, v0]) else: sd = sd_blackbody(CCT + delta, shape) XYZ = sd_to_XYZ(sd, cmfs) XYZ *= 1 / np.max(XYZ) UVW = XYZ_to_UCS(XYZ) u1, v1 = UCS_to_uv(UVW) du = u0 - u1 dv = v0 - v1 u = u0 - D_uv * (dv / np.hypot(du, dv)) v = v0 + D_uv * (du / np.hypot(du, dv)) return np.array([u, v])
def _CCT_to_uv_Ohno2013( CCT_D_uv, cmfs=STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer']): """ Returns the *CIE UCS* colourspace *uv* chromaticity coordinates from given correlated colour temperature :math:`T_{cp}`, :math:`\\Delta_{uv}` and colour matching functions using *Ohno (2013)* method. Parameters ---------- CCT_D_uv : ndarray Correlated colour temperature :math:`T_{cp}`, :math:`\\Delta_{uv}`. cmfs : XYZ_ColourMatchingFunctions, optional Standard observer colour matching functions. Returns ------- ndarray *CIE UCS* colourspace *uv* chromaticity coordinates. """ CCT, D_uv = tsplit(CCT_D_uv) cmfs = cmfs.copy().trim(ASTME30815_PRACTISE_SHAPE) shape = cmfs.shape delta = 0.01 sd = sd_blackbody(CCT, shape) XYZ = sd_to_XYZ(sd, cmfs) XYZ *= 1 / np.max(XYZ) UVW = XYZ_to_UCS(XYZ) u0, v0 = UCS_to_uv(UVW) if D_uv == 0: return np.array([u0, v0]) else: sd = sd_blackbody(CCT + delta, shape) XYZ = sd_to_XYZ(sd, cmfs) XYZ *= 1 / np.max(XYZ) UVW = XYZ_to_UCS(XYZ) u1, v1 = UCS_to_uv(UVW) du = u0 - u1 dv = v0 - v1 u = u0 - D_uv * (dv / np.hypot(du, dv)) v = v0 + D_uv * (du / np.hypot(du, dv)) return np.array([u, v])
def _CCT_to_uv_Ohno2013( CCT_D_uv: ArrayLike, cmfs: Optional[MultiSpectralDistributions] = None) -> NDArray: """ Return the *CIE UCS* colourspace *uv* chromaticity coordinates from given correlated colour temperature :math:`T_{cp}`, :math:`\\Delta_{uv}` and colour matching functions using *Ohno (2013)* method. Parameters ---------- CCT_D_uv Correlated colour temperature :math:`T_{cp}`, :math:`\\Delta_{uv}`. cmfs Standard observer colour matching functions, default to the *CIE 1931 2 Degree Standard Observer*. Returns ------- :class:`numpy.ndarray` *CIE UCS* colourspace *uv* chromaticity coordinates. """ CCT, D_uv = tsplit(CCT_D_uv) cmfs, _illuminant = handle_spectral_arguments(cmfs) delta = 0.01 sd = sd_blackbody(CCT, cmfs.shape) XYZ = sd_to_XYZ(sd, cmfs) XYZ *= 1 / np.max(XYZ) UVW = XYZ_to_UCS(XYZ) u0, v0 = UCS_to_uv(UVW) if D_uv == 0: return np.array([u0, v0]) else: sd = sd_blackbody(CCT + delta, cmfs.shape) XYZ = sd_to_XYZ(sd, cmfs) XYZ *= 1 / np.max(XYZ) UVW = XYZ_to_UCS(XYZ) u1, v1 = UCS_to_uv(UVW) du = u0 - u1 dv = v0 - v1 u = u0 - D_uv * (dv / np.hypot(du, dv)) v = v0 + D_uv * (du / np.hypot(du, dv)) return np.array([u, v])
def test_sd_reference_illuminant(self): """ Tests :func:`colour.quality.CIE2017.sd_reference_illuminant` definition. """ for sd, shape in [ (SD_SAMPLE_5NM, SD_SAMPLE_5NM.shape), (SD_SAMPLE_1NM, SD_SAMPLE_1NM.shape), ]: CCT, _D_uv = CCT_reference_illuminant(sd) sd_reference = sd_reference_illuminant(CCT, shape) np.testing.assert_allclose(sd_reference.values, sd_blackbody(3288, shape).values, rtol=0.005)
def planckian_table( uv: ArrayLike, cmfs: MultiSpectralDistributions, start: Floating, end: Floating, count: Integer, ) -> List[PlanckianTableRow]: """ Return a planckian table from given *CIE UCS* colourspace *uv* chromaticity coordinates, colour matching functions and temperature range using *Ohno (2013)* method. Parameters ---------- uv *uv* chromaticity coordinates. cmfs Standard observer colour matching functions. start Temperature range start in kelvin degrees. end Temperature range end in kelvin degrees. count Temperatures count in the planckian table. Returns ------- :class:`list` Planckian table. Examples -------- >>> from colour import MSDS_CMFS, SPECTRAL_SHAPE_DEFAULT >>> cmfs = ( ... MSDS_CMFS['CIE 1931 2 Degree Standard Observer']. ... copy().align(SPECTRAL_SHAPE_DEFAULT) ... ) >>> uv = np.array([0.1978, 0.3122]) >>> pprint(planckian_table(uv, cmfs, 1000, 1010, 10)) ... # doctest: +SKIP [PlanckianTableRow(Ti=1000.0, ui=0.4479628..., \ vi=0.3546296..., di=0.2537355...), PlanckianTableRow(Ti=1001.1111111..., ui=0.4477030..., \ vi=0.3546521..., di=0.2534831...), PlanckianTableRow(Ti=1002.2222222..., ui=0.4474434..., \ vi=0.3546746..., di=0.2532310...), PlanckianTableRow(Ti=1003.3333333..., ui=0.4471842..., \ vi=0.3546970..., di=0.2529792...), PlanckianTableRow(Ti=1004.4444444..., ui=0.4469252..., \ vi=0.3547194..., di=0.2527277...), PlanckianTableRow(Ti=1005.5555555..., ui=0.4466666..., \ vi=0.3547417..., di=0.2524765...), PlanckianTableRow(Ti=1006.6666666..., ui=0.4464083..., \ vi=0.3547640..., di=0.2522256...), PlanckianTableRow(Ti=1007.7777777..., ui=0.4461502..., \ vi=0.3547862..., di=0.2519751...), PlanckianTableRow(Ti=1008.8888888..., ui=0.4458925..., \ vi=0.3548084..., di=0.2517248...), PlanckianTableRow(Ti=1010.0, ui=0.4456351..., \ vi=0.3548306..., di=0.2514749...)] """ ux, vx = tsplit(uv) table = [] for Ti in np.linspace(start, end, count): sd = sd_blackbody(Ti, cmfs.shape) XYZ = sd_to_XYZ(sd, cmfs) XYZ /= np.max(XYZ) UVW = XYZ_to_UCS(XYZ) ui, vi = UCS_to_uv(UVW) di = np.hypot(ux - ui, vx - vi) table.append(PlanckianTableRow(Ti, ui, vi, di)) return table
def colour_quality_scale(sd_test, additional_data=False, method='NIST CQS 9.0'): """ Returns the *Colour Quality Scale* (CQS) of given spectral distribution using given method. Parameters ---------- sd_test : SpectralDistribution Test spectral distribution. additional_data : bool, optional Whether to output additional data. method : unicode, optional **{'NIST CQS 9.0', 'NIST CQS 7.4'}**, Computation method. Returns ------- numeric or CQS_Specification Color quality scale. References ---------- :cite:`Davis2010a`, :cite:`Ohno2008a`, :cite:`Ohno2013` Examples -------- >>> from colour import ILLUMINANTS_SDS >>> sd = ILLUMINANTS_SDS['FL2'] >>> colour_quality_scale(sd) # doctest: +ELLIPSIS 64.0172835... """ method = method.lower() assert method.lower() in [ m.lower() for m in COLOUR_QUALITY_SCALE_METHODS ], ('"{0}" method is invalid, must be one of {1}!'.format( method, COLOUR_QUALITY_SCALE_METHODS)) cmfs = STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer'].copy( ).trim(DEFAULT_SPECTRAL_SHAPE) shape = cmfs.shape sd_test = sd_test.copy().align(shape) vs_sds = { sd.name: sd.copy().align(shape) for sd in VS_SDS[method].values() } with domain_range_scale('1'): XYZ = sd_to_XYZ(sd_test, cmfs) uv = UCS_to_uv(XYZ_to_UCS(XYZ)) CCT, _D_uv = uv_to_CCT_Ohno2013(uv) if CCT < 5000: sd_reference = sd_blackbody(CCT, shape) else: xy = CCT_to_xy_CIE_D(CCT) sd_reference = sd_CIE_illuminant_D_series(xy) sd_reference.align(shape) test_vs_colorimetry_data = vs_colorimetry_data(sd_test, sd_reference, vs_sds, cmfs, chromatic_adaptation=True) reference_vs_colorimetry_data = vs_colorimetry_data( sd_reference, sd_reference, vs_sds, cmfs) if method == 'nist cqs 9.0': CCT_f = 1 scaling_f = 3.2 else: XYZ_r = sd_to_XYZ(sd_reference, cmfs) XYZ_r /= XYZ_r[1] CCT_f = CCT_factor(reference_vs_colorimetry_data, XYZ_r) scaling_f = 3.104 Q_as = colour_quality_scales(test_vs_colorimetry_data, reference_vs_colorimetry_data, scaling_f, CCT_f) D_E_RMS = delta_E_RMS(Q_as, 'D_E_ab') D_Ep_RMS = delta_E_RMS(Q_as, 'D_Ep_ab') Q_a = scale_conversion(D_Ep_RMS, CCT_f, scaling_f) if method == 'nist cqs 9.0': scaling_f = 2.93 * 1.0343 else: scaling_f = 2.928 Q_f = scale_conversion(D_E_RMS, CCT_f, scaling_f) G_t = gamut_area( [vs_CQS_data.Lab for vs_CQS_data in test_vs_colorimetry_data]) G_r = gamut_area( [vs_CQS_data.Lab for vs_CQS_data in reference_vs_colorimetry_data]) Q_g = G_t / D65_GAMUT_AREA * 100 if method == 'nist cqs 9.0': Q_d = Q_p = None else: p_delta_C = np.average([ sample_data.D_C_ab if sample_data.D_C_ab > 0 else 0 for sample_data in Q_as.values() ]) Q_p = 100 - 3.6 * (D_Ep_RMS - p_delta_C) Q_d = G_t / G_r * CCT_f * 100 if additional_data: return CQS_Specification( sd_test.name, Q_a, Q_f, Q_p, Q_g, Q_d, Q_as, (test_vs_colorimetry_data, reference_vs_colorimetry_data)) else: return Q_a
def colour_quality_scale(sd_test, additional_data=False, method='NIST CQS 9.0'): """ Returns the *Colour Quality Scale* (CQS) of given spectral distribution using given method. Parameters ---------- sd_test : SpectralDistribution Test spectral distribution. additional_data : bool, optional Whether to output additional data. method : unicode, optional **{'NIST CQS 9.0', 'NIST CQS 7.4'}**, Computation method. Returns ------- numeric or CQS_Specification Color quality scale. References ---------- :cite:`Davis2010a`, :cite:`Ohno2008a`, :cite:`Ohno2013` Examples -------- >>> from colour import ILLUMINANTS_SDS >>> sd = ILLUMINANTS_SDS['FL2'] >>> colour_quality_scale(sd) # doctest: +ELLIPSIS 64.0172835... """ method = method.lower() assert method.lower() in [ m.lower() for m in COLOUR_QUALITY_SCALE_METHODS ], ('"{0}" method is invalid, must be one of {1}!'.format( method, COLOUR_QUALITY_SCALE_METHODS)) cmfs = STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer'].copy( ).trim(ASTME30815_PRACTISE_SHAPE) shape = cmfs.shape sd_test = sd_test.copy().align(shape) vs_sds = { sd.name: sd.copy().align(shape) for sd in VS_SDS[method].values() } with domain_range_scale('1'): XYZ = sd_to_XYZ(sd_test, cmfs) uv = UCS_to_uv(XYZ_to_UCS(XYZ)) CCT, _D_uv = uv_to_CCT_Ohno2013(uv) if CCT < 5000: sd_reference = sd_blackbody(CCT, shape) else: xy = CCT_to_xy_CIE_D(CCT) sd_reference = sd_CIE_illuminant_D_series(xy) sd_reference.align(shape) test_vs_colorimetry_data = vs_colorimetry_data( sd_test, sd_reference, vs_sds, cmfs, chromatic_adaptation=True) reference_vs_colorimetry_data = vs_colorimetry_data( sd_reference, sd_reference, vs_sds, cmfs) if method == 'nist cqs 9.0': CCT_f = 1 scaling_f = 3.2 else: XYZ_r = sd_to_XYZ(sd_reference, cmfs) XYZ_r /= XYZ_r[1] CCT_f = CCT_factor(reference_vs_colorimetry_data, XYZ_r) scaling_f = 3.104 Q_as = colour_quality_scales(test_vs_colorimetry_data, reference_vs_colorimetry_data, scaling_f, CCT_f) D_E_RMS = delta_E_RMS(Q_as, 'D_E_ab') D_Ep_RMS = delta_E_RMS(Q_as, 'D_Ep_ab') Q_a = scale_conversion(D_Ep_RMS, CCT_f, scaling_f) if method == 'nist cqs 9.0': scaling_f = 2.93 * 1.0343 else: scaling_f = 2.928 Q_f = scale_conversion(D_E_RMS, CCT_f, scaling_f) G_t = gamut_area( [vs_CQS_data.Lab for vs_CQS_data in test_vs_colorimetry_data]) G_r = gamut_area( [vs_CQS_data.Lab for vs_CQS_data in reference_vs_colorimetry_data]) Q_g = G_t / D65_GAMUT_AREA * 100 if method == 'nist cqs 9.0': Q_d = Q_p = None else: p_delta_C = np.average([ sample_data.D_C_ab if sample_data.D_C_ab > 0 else 0 for sample_data in Q_as.values() ]) Q_p = 100 - 3.6 * (D_Ep_RMS - p_delta_C) Q_d = G_t / G_r * CCT_f * 100 if additional_data: return CQS_Specification( sd_test.name, Q_a, Q_f, Q_p, Q_g, Q_d, Q_as, (test_vs_colorimetry_data, reference_vs_colorimetry_data)) else: return Q_a
def colour_rendering_index( sd_test: SpectralDistribution, additional_data: Boolean = False ) -> Union[Floating, ColourRendering_Specification_CRI]: """ Return the *Colour Rendering Index* (CRI) :math:`Q_a` of given spectral distribution. Parameters ---------- sd_test Test spectral distribution. additional_data Whether to output additional data. Returns ------- :class:`numpy.floating` or \ :class:`colour.quality.ColourRendering_Specification_CRI` *Colour Rendering Index* (CRI). References ---------- :cite:`Ohno2008a` Examples -------- >>> from colour import SDS_ILLUMINANTS >>> sd = SDS_ILLUMINANTS['FL2'] >>> colour_rendering_index(sd) # doctest: +ELLIPSIS 64.2337241... """ # pylint: disable=E1102 cmfs = reshape_msds( MSDS_CMFS["CIE 1931 2 Degree Standard Observer"], SPECTRAL_SHAPE_DEFAULT, ) shape = cmfs.shape sd_test = reshape_sd(sd_test, shape) tcs_sds = {sd.name: reshape_sd(sd, shape) for sd in SDS_TCS.values()} with domain_range_scale("1"): XYZ = sd_to_XYZ(sd_test, cmfs) uv = UCS_to_uv(XYZ_to_UCS(XYZ)) CCT, _D_uv = uv_to_CCT_Robertson1968(uv) if CCT < 5000: sd_reference = sd_blackbody(CCT, shape) else: xy = CCT_to_xy_CIE_D(CCT) sd_reference = sd_CIE_illuminant_D_series(xy) sd_reference.align(shape) test_tcs_colorimetry_data = tcs_colorimetry_data( sd_test, sd_reference, tcs_sds, cmfs, chromatic_adaptation=True ) reference_tcs_colorimetry_data = tcs_colorimetry_data( sd_reference, sd_reference, tcs_sds, cmfs ) Q_as = colour_rendering_indexes( test_tcs_colorimetry_data, reference_tcs_colorimetry_data ) Q_a = as_float_scalar( np.average( [v.Q_a for k, v in Q_as.items() if k in (1, 2, 3, 4, 5, 6, 7, 8)] ) ) if additional_data: return ColourRendering_Specification_CRI( sd_test.name, Q_a, Q_as, (test_tcs_colorimetry_data, reference_tcs_colorimetry_data), ) else: return Q_a
def plot_blackbody_spectral_radiance( temperature: Floating = 3500, cmfs: Union[MultiSpectralDistributions, str, Sequence[Union[ MultiSpectralDistributions, str]], ] = "CIE 1931 2 Degree Standard Observer", blackbody: str = "VY Canis Major", **kwargs: Any, ) -> Tuple[plt.Figure, plt.Axes]: """ Plot given blackbody spectral radiance. Parameters ---------- temperature Blackbody temperature. cmfs Standard observer colour matching functions used for computing the spectrum domain and colours. ``cmfs`` can be of any type or form supported by the :func:`colour.plotting.filter_cmfs` definition. blackbody Blackbody name. Other Parameters ---------------- kwargs {:func:`colour.plotting.artist`, :func:`colour.plotting.plot_single_sd`, :func:`colour.plotting.render`}, See the documentation of the previously listed definitions. Returns ------- :class:`tuple` Current figure and axes. Examples -------- >>> plot_blackbody_spectral_radiance(3500, blackbody='VY Canis Major') ... # doctest: +ELLIPSIS (<Figure size ... with 2 Axes>, <...AxesSubplot...>) .. image:: ../_static/Plotting_Plot_Blackbody_Spectral_Radiance.png :align: center :alt: plot_blackbody_spectral_radiance """ figure = plt.figure() figure.subplots_adjust(hspace=CONSTANTS_COLOUR_STYLE.geometry.short / 2) cmfs = cast(MultiSpectralDistributions, first_item(filter_cmfs(cmfs).values())) sd = sd_blackbody(temperature, cmfs.shape) axes = figure.add_subplot(211) settings: Dict[str, Any] = { "axes": axes, "title": f"{blackbody} - Spectral Radiance", "y_label": "W / (sr m$^2$) / m", } settings.update(kwargs) settings["standalone"] = False plot_single_sd(sd, cmfs.name, **settings) axes = figure.add_subplot(212) with domain_range_scale("1"): XYZ = sd_to_XYZ(sd, cmfs) RGB = normalise_maximum(XYZ_to_plotting_colourspace(XYZ)) settings = { "axes": axes, "aspect": None, "title": f"{blackbody} - Colour", "x_label": f"{temperature}K", "y_label": "", "x_ticker": False, "y_ticker": False, } settings.update(kwargs) settings["standalone"] = False figure, axes = plot_single_colour_swatch(RGB, **settings) settings = {"axes": axes, "standalone": True} settings.update(kwargs) return render(**settings)
def sd_reference_illuminant(CCT: Floating, shape: SpectralShape) -> SpectralDistribution: """ Compute the reference illuminant for a given correlated colour temperature :math:`T_{cp}` for use in *CIE 2017 Colour Fidelity Index* (CFI) computation. Parameters ---------- CCT Correlated colour temperature :math:`T_{cp}`. shape Desired shape of the returned spectral distribution. Returns ------- :class:`colour.SpectralDistribution` Reference illuminant for *CIE 2017 Colour Fidelity Index* (CFI) computation. Examples -------- >>> from colour.utilities import numpy_print_options >>> with numpy_print_options(suppress=True): ... sd_reference_illuminant( # doctest: +ELLIPSIS ... 4224.469705295263300, SpectralShape(380, 780, 20)) SpectralDistribution([[ 380. , 0.0034089...], [ 400. , 0.0044208...], [ 420. , 0.0053260...], [ 440. , 0.0062857...], [ 460. , 0.0072767...], [ 480. , 0.0080207...], [ 500. , 0.0086590...], [ 520. , 0.0092242...], [ 540. , 0.0097686...], [ 560. , 0.0101444...], [ 580. , 0.0104475...], [ 600. , 0.0107642...], [ 620. , 0.0110439...], [ 640. , 0.0112535...], [ 660. , 0.0113922...], [ 680. , 0.0115185...], [ 700. , 0.0113155...], [ 720. , 0.0108192...], [ 740. , 0.0111582...], [ 760. , 0.0101299...], [ 780. , 0.0105638...]], interpolator=SpragueInterpolator, interpolator_kwargs={}, extrapolator=Extrapolator, extrapolator_kwargs={...}) """ if CCT <= 5000: sd_planckian = sd_blackbody(CCT, shape) if CCT >= 4000: xy = CCT_to_xy_CIE_D(CCT) sd_daylight = sd_CIE_illuminant_D_series(xy).align(shape) if CCT < 4000: sd_reference = sd_planckian elif 4000 <= CCT <= 5000: # Planckian and daylight illuminant must be normalised so that the # mixture isn't biased. sd_planckian /= sd_to_XYZ(sd_planckian)[1] # type: ignore[misc] sd_daylight /= sd_to_XYZ(sd_daylight)[1] # type: ignore[misc] # Mixture: 4200K should be 80% Planckian, 20% CIE Illuminant D Series. m = (CCT - 4000) / 1000 values = linstep_function(m, sd_planckian.values, sd_daylight.values) name = (f"{as_int_scalar(CCT)}K " f"Blackbody & CIE Illuminant D Series Mixture - " f"{as_float_scalar(100 * m):.1f}%") sd_reference = SpectralDistribution(values, shape.range(), name=name) elif CCT > 5000: sd_reference = sd_daylight return sd_reference
def plot_blackbody_spectral_radiance( temperature=3500, cmfs='CIE 1931 2 Degree Standard Observer', blackbody='VY Canis Major', **kwargs): """ Plots given blackbody spectral radiance. Parameters ---------- temperature : numeric, optional Blackbody temperature. cmfs : unicode, optional Standard observer colour matching functions. blackbody : unicode, optional Blackbody name. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.plot_single_sd`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_blackbody_spectral_radiance(3500, blackbody='VY Canis Major') ... # doctest: +ELLIPSIS (<Figure size ... with 2 Axes>, \ <matplotlib.axes._subplots.AxesSubplot object at 0x...>) .. image:: ../_static/Plotting_Plot_Blackbody_Spectral_Radiance.png :align: center :alt: plot_blackbody_spectral_radiance """ figure = plt.figure() figure.subplots_adjust(hspace=COLOUR_STYLE_CONSTANTS.geometry.short / 2) cmfs = first_item(filter_cmfs(cmfs).values()) sd = sd_blackbody(temperature, cmfs.shape) axes = figure.add_subplot(211) settings = { 'axes': axes, 'title': '{0} - Spectral Radiance'.format(blackbody), 'y_label': 'W / (sr m$^2$) / m', } settings.update(kwargs) settings['standalone'] = False plot_single_sd(sd, cmfs.name, **settings) axes = figure.add_subplot(212) with domain_range_scale('1'): XYZ = sd_to_XYZ(sd, cmfs) RGB = normalise_maximum(XYZ_to_plotting_colourspace(XYZ)) settings = { 'axes': axes, 'aspect': None, 'title': '{0} - Colour'.format(blackbody), 'x_label': '{0}K'.format(temperature), 'y_label': '', 'x_ticker': False, 'y_ticker': False, } settings.update(kwargs) settings['standalone'] = False figure, axes = plot_single_colour_swatch(ColourSwatch(name='', RGB=RGB), **settings) settings = {'axes': axes, 'standalone': True} settings.update(kwargs) return render(**settings)
def CCT_to_uv_Ohno2013( CCT, D_uv=0, cmfs=STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer']): """ Returns the *CIE UCS* colourspace *uv* chromaticity coordinates from given correlated colour temperature :math:`T_{cp}`, :math:`\\Delta_{uv}` and colour matching functions using *Ohno (2013)* method. Parameters ---------- CCT : numeric Correlated colour temperature :math:`T_{cp}`. D_uv : numeric, optional :math:`\\Delta_{uv}`. cmfs : XYZ_ColourMatchingFunctions, optional Standard observer colour matching functions. Returns ------- ndarray *CIE UCS* colourspace *uv* chromaticity coordinates. References ---------- :cite:`Ohno2014a` Examples -------- >>> from colour import STANDARD_OBSERVERS_CMFS >>> cmfs = STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer'] >>> CCT = 6507.4342201047066 >>> D_uv = 0.003223690901513 >>> CCT_to_uv_Ohno2013(CCT, D_uv, cmfs) # doctest: +ELLIPSIS array([ 0.1977999..., 0.3122004...]) """ cmfs = cmfs.copy().trim(ASTME30815_PRACTISE_SHAPE) shape = cmfs.shape delta = 0.01 sd = sd_blackbody(CCT, shape) XYZ = sd_to_XYZ(sd, cmfs) XYZ *= 1 / np.max(XYZ) UVW = XYZ_to_UCS(XYZ) u0, v0 = UCS_to_uv(UVW) if D_uv == 0: return np.array([u0, v0]) else: sd = sd_blackbody(CCT + delta, shape) XYZ = sd_to_XYZ(sd, cmfs) XYZ *= 1 / np.max(XYZ) UVW = XYZ_to_UCS(XYZ) u1, v1 = UCS_to_uv(UVW) du = u0 - u1 dv = v0 - v1 u = u0 - D_uv * (dv / np.hypot(du, dv)) v = v0 + D_uv * (du / np.hypot(du, dv)) return np.array([u, v])
def planckian_table(uv, cmfs, start, end, count): """ Returns a planckian table from given *CIE UCS* colourspace *uv* chromaticity coordinates, colour matching functions and temperature range using *Ohno (2013)* method. Parameters ---------- uv : array_like *uv* chromaticity coordinates. cmfs : XYZ_ColourMatchingFunctions Standard observer colour matching functions. start : numeric Temperature range start in kelvins. end : numeric Temperature range end in kelvins. count : int Temperatures count in the planckian table. Returns ------- list Planckian table. Examples -------- >>> from colour import STANDARD_OBSERVERS_CMFS >>> from pprint import pprint >>> cmfs = STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer'] >>> uv = np.array([0.1978, 0.3122]) >>> pprint(planckian_table(uv, cmfs, 1000, 1010, 10)) ... # doctest: +ELLIPSIS [PlanckianTable_Tuvdi(Ti=1000.0, \ ui=0.4479628..., vi=0.3546296..., di=0.2537355...), PlanckianTable_Tuvdi(Ti=1001.1111111..., \ ui=0.4477030..., vi=0.3546521..., di=0.2534831...), PlanckianTable_Tuvdi(Ti=1002.2222222..., \ ui=0.4474434..., vi=0.3546746..., di=0.2532310...), PlanckianTable_Tuvdi(Ti=1003.3333333..., \ ui=0.4471842..., vi=0.3546970..., di=0.2529792...), PlanckianTable_Tuvdi(Ti=1004.4444444..., \ ui=0.4469252..., vi=0.3547194..., di=0.2527277...), PlanckianTable_Tuvdi(Ti=1005.5555555..., \ ui=0.4466666..., vi=0.3547417..., di=0.2524765...), PlanckianTable_Tuvdi(Ti=1006.6666666..., \ ui=0.4464083..., vi=0.3547640..., di=0.2522256...), PlanckianTable_Tuvdi(Ti=1007.7777777..., \ ui=0.4461502..., vi=0.3547862..., di=0.2519751...), PlanckianTable_Tuvdi(Ti=1008.8888888..., \ ui=0.4458925..., vi=0.3548084..., di=0.2517248...), PlanckianTable_Tuvdi(Ti=1010.0, \ ui=0.4456351..., vi=0.3548306..., di=0.2514749...)] """ ux, vx = uv cmfs = cmfs.copy().trim(ASTME30815_PRACTISE_SHAPE) shape = cmfs.shape table = [] for Ti in np.linspace(start, end, count): sd = sd_blackbody(Ti, shape) XYZ = sd_to_XYZ(sd, cmfs) XYZ /= np.max(XYZ) UVW = XYZ_to_UCS(XYZ) ui, vi = UCS_to_uv(UVW) di = np.hypot(ux - ui, vx - vi) table.append(PLANCKIAN_TABLE_TUVD(Ti, ui, vi, di)) return table
def plot_blackbody_spectral_radiance( temperature=3500, cmfs='CIE 1931 2 Degree Standard Observer', blackbody='VY Canis Major', **kwargs): """ Plots given blackbody spectral radiance. Parameters ---------- temperature : numeric, optional Blackbody temperature. cmfs : unicode, optional Standard observer colour matching functions. blackbody : unicode, optional Blackbody name. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.plot_single_sd`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_blackbody_spectral_radiance(3500, blackbody='VY Canis Major') ... # doctest: +SKIP .. image:: ../_static/Plotting_Plot_Blackbody_Spectral_Radiance.png :align: center :alt: plot_blackbody_spectral_radiance """ figure = plt.figure() figure.subplots_adjust(hspace=COLOUR_STYLE_CONSTANTS.geometry.short / 2) cmfs = first_item(filter_cmfs(cmfs).values()) sd = sd_blackbody(temperature, cmfs.shape) axes = figure.add_subplot(211) settings = { 'axes': axes, 'title': '{0} - Spectral Radiance'.format(blackbody), 'y_label': 'W / (sr m$^2$) / m', } settings.update(kwargs) settings['standalone'] = False plot_single_sd(sd, cmfs.name, **settings) axes = figure.add_subplot(212) with domain_range_scale('1'): XYZ = sd_to_XYZ(sd, cmfs) RGB = normalise_maximum(XYZ_to_plotting_colourspace(XYZ)) settings = { 'axes': axes, 'aspect': None, 'title': '{0} - Colour'.format(blackbody), 'x_label': '{0}K'.format(temperature), 'y_label': '', 'x_ticker': False, 'y_ticker': False, } settings.update(kwargs) settings['standalone'] = False figure, axes = plot_single_colour_swatch( ColourSwatch(name='', RGB=RGB), **settings) settings = {'axes': axes, 'standalone': True} settings.update(kwargs) return render(**settings)
def planckian_table(uv, cmfs, start, end, count): """ Returns a planckian table from given *CIE UCS* colourspace *uv* chromaticity coordinates, colour matching functions and temperature range using *Ohno (2013)* method. Parameters ---------- uv : array_like *uv* chromaticity coordinates. cmfs : XYZ_ColourMatchingFunctions Standard observer colour matching functions. start : numeric Temperature range start in kelvins. end : numeric Temperature range end in kelvins. count : int Temperatures count in the planckian table. Returns ------- list Planckian table. Examples -------- >>> from colour.colorimetry import ( ... SPECTRAL_SHAPE_DEFAULT, MSDS_CMFS_STANDARD_OBSERVER) >>> from pprint import pprint >>> cmfs = ( ... MSDS_CMFS_STANDARD_OBSERVER['CIE 1931 2 Degree Standard Observer']. ... copy().align(SPECTRAL_SHAPE_DEFAULT) ... ) >>> uv = np.array([0.1978, 0.3122]) >>> pprint(planckian_table(uv, cmfs, 1000, 1010, 10)) ... # doctest: +ELLIPSIS [PlanckianTable_Tuvdi(Ti=1000.0, \ ui=0.4479628..., vi=0.3546296..., di=0.2537355...), PlanckianTable_Tuvdi(Ti=1001.1111111..., \ ui=0.4477030..., vi=0.3546521..., di=0.2534831...), PlanckianTable_Tuvdi(Ti=1002.2222222..., \ ui=0.4474434..., vi=0.3546746..., di=0.2532310...), PlanckianTable_Tuvdi(Ti=1003.3333333..., \ ui=0.4471842..., vi=0.3546970..., di=0.2529792...), PlanckianTable_Tuvdi(Ti=1004.4444444..., \ ui=0.4469252..., vi=0.3547194..., di=0.2527277...), PlanckianTable_Tuvdi(Ti=1005.5555555..., \ ui=0.4466666..., vi=0.3547417..., di=0.2524765...), PlanckianTable_Tuvdi(Ti=1006.6666666..., \ ui=0.4464083..., vi=0.3547640..., di=0.2522256...), PlanckianTable_Tuvdi(Ti=1007.7777777..., \ ui=0.4461502..., vi=0.3547862..., di=0.2519751...), PlanckianTable_Tuvdi(Ti=1008.8888888..., \ ui=0.4458925..., vi=0.3548084..., di=0.2517248...), PlanckianTable_Tuvdi(Ti=1010.0, \ ui=0.4456351..., vi=0.3548306..., di=0.2514749...)] """ ux, vx = uv cmfs = cmfs.copy().trim(SPECTRAL_SHAPE_DEFAULT) shape = cmfs.shape table = [] for Ti in np.linspace(start, end, count): sd = sd_blackbody(Ti, shape) XYZ = sd_to_XYZ(sd, cmfs) XYZ /= np.max(XYZ) UVW = XYZ_to_UCS(XYZ) ui, vi = UCS_to_uv(UVW) di = np.hypot(ux - ui, vx - vi) table.append(PLANCKIAN_TABLE_TUVD(Ti, ui, vi, di)) return table
def generate_documentation_plots(output_directory: str): """ Generate documentation plots. Parameters ---------- output_directory Output directory. """ filter_warnings() colour_style() np.random.seed(0) # ************************************************************************* # "README.rst" # ************************************************************************* filename = os.path.join( output_directory, "Examples_Colour_Automatic_Conversion_Graph.png" ) plot_automatic_colour_conversion_graph(filename) arguments = { "tight_layout": True, "transparent_background": True, "filename": os.path.join( output_directory, "Examples_Plotting_Visible_Spectrum.png" ), } plt.close( plot_visible_spectrum( "CIE 1931 2 Degree Standard Observer", **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Examples_Plotting_Illuminant_F1_SD.png" ) plt.close(plot_single_illuminant_sd("FL1", **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Examples_Plotting_Blackbodies.png" ) blackbody_sds = [ sd_blackbody(i, SpectralShape(0, 10000, 10)) for i in range(1000, 15000, 1000) ] plt.close( plot_multi_sds( blackbody_sds, y_label="W / (sr m$^2$) / m", plot_kwargs={"use_sd_colours": True, "normalise_sd_colours": True}, legend_location="upper right", bounding_box=(0, 1250, 0, 2.5e6), **arguments, )[0] ) arguments["filename"] = os.path.join( output_directory, "Examples_Plotting_Cone_Fundamentals.png" ) plt.close( plot_single_cmfs( "Stockman & Sharpe 2 Degree Cone Fundamentals", y_label="Sensitivity", bounding_box=(390, 870, 0, 1.1), **arguments, )[0] ) arguments["filename"] = os.path.join( output_directory, "Examples_Plotting_Luminous_Efficiency.png" ) plt.close( plot_multi_sds( ( sd_mesopic_luminous_efficiency_function(0.2), SDS_LEFS_PHOTOPIC["CIE 1924 Photopic Standard Observer"], SDS_LEFS_SCOTOPIC["CIE 1951 Scotopic Standard Observer"], ), y_label="Luminous Efficiency", legend_location="upper right", y_tighten=True, margins=(0, 0, 0, 0.1), **arguments, )[0] ) arguments["filename"] = os.path.join( output_directory, "Examples_Plotting_BabelColor_Average.png" ) plt.close( plot_multi_sds( SDS_COLOURCHECKERS["BabelColor Average"].values(), plot_kwargs={"use_sd_colours": True}, title=("BabelColor Average - " "Spectral Distributions"), **arguments, )[0] ) arguments["filename"] = os.path.join( output_directory, "Examples_Plotting_ColorChecker_2005.png" ) plt.close( plot_single_colour_checker( "ColorChecker 2005", text_kwargs={"visible": False}, **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Examples_Plotting_Chromaticities_Prediction.png" ) plt.close( plot_corresponding_chromaticities_prediction( 2, "Von Kries", **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Examples_Plotting_Chromaticities_CIE_1931_Chromaticity_Diagram.png", ) RGB = np.random.random((32, 32, 3)) plt.close( plot_RGB_chromaticities_in_chromaticity_diagram_CIE1931( RGB, "ITU-R BT.709", colourspaces=["ACEScg", "S-Gamut"], show_pointer_gamut=True, **arguments, )[0] ) arguments["filename"] = os.path.join( output_directory, "Examples_Plotting_CRI.png" ) plt.close( plot_single_sd_colour_rendering_index_bars( SDS_ILLUMINANTS["FL2"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Examples_Plotting_Colour_Rendition_Report.png" ) plt.close( plot_single_sd_colour_rendition_report( SDS_ILLUMINANTS["FL2"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Examples_Plotting_Plot_Visible_Spectrum_Section.png" ) plt.close( plot_visible_spectrum_section( section_colours="RGB", section_opacity=0.15, **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Examples_Plotting_Plot_RGB_Colourspace_Section.png" ) plt.close( plot_RGB_colourspace_section( "sRGB", section_colours="RGB", section_opacity=0.15, **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Examples_Plotting_CCT_CIE_1960_UCS_Chromaticity_Diagram.png", ) plt.close( plot_planckian_locus_in_chromaticity_diagram_CIE1960UCS( ["A", "B", "C"], **arguments )[0] ) # ************************************************************************* # Documentation # ************************************************************************* arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_CVD_Simulation_Machado2009.png" ) plt.close(plot_cvd_simulation_Machado2009(RGB, **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_Colour_Checker.png" ) plt.close(plot_single_colour_checker("ColorChecker 2005", **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Multi_Colour_Checkers.png" ) plt.close( plot_multi_colour_checkers( ["ColorChecker 1976", "ColorChecker 2005"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_SD.png" ) data = { 500: 0.0651, 520: 0.0705, 540: 0.0772, 560: 0.0870, 580: 0.1128, 600: 0.1360, } sd = SpectralDistribution(data, name="Custom") plt.close(plot_single_sd(sd, **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Multi_SDS.png" ) data_1 = { 500: 0.004900, 510: 0.009300, 520: 0.063270, 530: 0.165500, 540: 0.290400, 550: 0.433450, 560: 0.594500, } data_2 = { 500: 0.323000, 510: 0.503000, 520: 0.710000, 530: 0.862000, 540: 0.954000, 550: 0.994950, 560: 0.995000, } spd1 = SpectralDistribution(data_1, name="Custom 1") spd2 = SpectralDistribution(data_2, name="Custom 2") plt.close(plot_multi_sds([spd1, spd2], **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_CMFS.png" ) plt.close( plot_single_cmfs("CIE 1931 2 Degree Standard Observer", **arguments)[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Multi_CMFS.png" ) cmfs = ( "CIE 1931 2 Degree Standard Observer", "CIE 1964 10 Degree Standard Observer", ) plt.close(plot_multi_cmfs(cmfs, **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_Illuminant_SD.png" ) plt.close(plot_single_illuminant_sd("A", **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Multi_Illuminant_SDS.png" ) plt.close(plot_multi_illuminant_sds(["A", "B", "C"], **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Visible_Spectrum.png" ) plt.close(plot_visible_spectrum(**arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_Lightness_Function.png" ) plt.close(plot_single_lightness_function("CIE 1976", **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Multi_Lightness_Functions.png" ) plt.close( plot_multi_lightness_functions( ["CIE 1976", "Wyszecki 1963"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_Luminance_Function.png" ) plt.close(plot_single_luminance_function("CIE 1976", **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Multi_Luminance_Functions.png" ) plt.close( plot_multi_luminance_functions( ["CIE 1976", "Newhall 1943"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Blackbody_Spectral_Radiance.png" ) plt.close( plot_blackbody_spectral_radiance( 3500, blackbody="VY Canis Major", **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Blackbody_Colours.png" ) plt.close( plot_blackbody_colours(SpectralShape(150, 12500, 50), **arguments)[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_Colour_Swatch.png" ) RGB = ColourSwatch((0.45620519, 0.03081071, 0.04091952)) plt.close(plot_single_colour_swatch(RGB, **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Multi_Colour_Swatches.png" ) RGB_1 = ColourSwatch((0.45293517, 0.31732158, 0.26414773)) RGB_2 = ColourSwatch((0.77875824, 0.57726450, 0.50453169)) plt.close(plot_multi_colour_swatches([RGB_1, RGB_2], **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_Function.png" ) plt.close(plot_single_function(lambda x: x ** (1 / 2.2), **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Multi_Functions.png" ) functions = { "Gamma 2.2": lambda x: x ** (1 / 2.2), "Gamma 2.4": lambda x: x ** (1 / 2.4), "Gamma 2.6": lambda x: x ** (1 / 2.6), } plt.close(plot_multi_functions(functions, **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Image.png" ) path = os.path.join( colour.__path__[0], "examples", "plotting", "resources", "Ishihara_Colour_Blindness_Test_Plate_3.png", ) plt.close(plot_image(read_image(str(path)), **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Corresponding_Chromaticities_Prediction.png", ) plt.close( plot_corresponding_chromaticities_prediction( 1, "Von Kries", **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Spectral_Locus.png" ) plt.close( plot_spectral_locus(spectral_locus_colours="RGB", **arguments)[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Chromaticity_Diagram_Colours.png" ) plt.close( plot_chromaticity_diagram_colours(diagram_colours="RGB", **arguments)[ 0 ] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Chromaticity_Diagram.png" ) plt.close(plot_chromaticity_diagram(**arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Chromaticity_Diagram_CIE1931.png" ) plt.close(plot_chromaticity_diagram_CIE1931(**arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Chromaticity_Diagram_CIE1960UCS.png" ) plt.close(plot_chromaticity_diagram_CIE1960UCS(**arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Chromaticity_Diagram_CIE1976UCS.png" ) plt.close(plot_chromaticity_diagram_CIE1976UCS(**arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_SDS_In_Chromaticity_Diagram.png" ) A = SDS_ILLUMINANTS["A"] D65 = SDS_ILLUMINANTS["D65"] plt.close(plot_sds_in_chromaticity_diagram([A, D65], **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_SDS_In_Chromaticity_Diagram_CIE1931.png", ) plt.close( plot_sds_in_chromaticity_diagram_CIE1931([A, D65], **arguments)[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_SDS_In_Chromaticity_Diagram_CIE1960UCS.png", ) plt.close( plot_sds_in_chromaticity_diagram_CIE1960UCS([A, D65], **arguments)[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_SDS_In_Chromaticity_Diagram_CIE1976UCS.png", ) plt.close( plot_sds_in_chromaticity_diagram_CIE1976UCS([A, D65], **arguments)[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Pointer_Gamut.png" ) plt.close(plot_pointer_gamut(**arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_RGB_Colourspaces_In_Chromaticity_Diagram.png", ) plt.close( plot_RGB_colourspaces_in_chromaticity_diagram( ["ITU-R BT.709", "ACEScg", "S-Gamut"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_RGB_Colourspaces_In_Chromaticity_Diagram_CIE1931.png", ) plt.close( plot_RGB_colourspaces_in_chromaticity_diagram_CIE1931( ["ITU-R BT.709", "ACEScg", "S-Gamut"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_RGB_Colourspaces_In_" "Chromaticity_Diagram_CIE1960UCS.png", ) plt.close( plot_RGB_colourspaces_in_chromaticity_diagram_CIE1960UCS( ["ITU-R BT.709", "ACEScg", "S-Gamut"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_RGB_Colourspaces_In_" "Chromaticity_Diagram_CIE1976UCS.png", ) plt.close( plot_RGB_colourspaces_in_chromaticity_diagram_CIE1976UCS( ["ITU-R BT.709", "ACEScg", "S-Gamut"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_RGB_Chromaticities_In_" "Chromaticity_Diagram.png", ) RGB = np.random.random((128, 128, 3)) plt.close( plot_RGB_chromaticities_in_chromaticity_diagram( RGB, "ITU-R BT.709", **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_RGB_Chromaticities_In_" "Chromaticity_Diagram_CIE1931.png", ) plt.close( plot_RGB_chromaticities_in_chromaticity_diagram_CIE1931( RGB, "ITU-R BT.709", **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_RGB_Chromaticities_In_" "Chromaticity_Diagram_CIE1960UCS.png", ) plt.close( plot_RGB_chromaticities_in_chromaticity_diagram_CIE1960UCS( RGB, "ITU-R BT.709", **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_RGB_Chromaticities_In_" "Chromaticity_Diagram_CIE1976UCS.png", ) plt.close( plot_RGB_chromaticities_in_chromaticity_diagram_CIE1976UCS( RGB, "ITU-R BT.709", **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Ellipses_MacAdam1942_In_Chromaticity_Diagram.png", ) plt.close( plot_ellipses_MacAdam1942_in_chromaticity_diagram(**arguments)[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Ellipses_MacAdam1942_In_" "Chromaticity_Diagram_CIE1931.png", ) plt.close( plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1931(**arguments)[ 0 ] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Ellipses_MacAdam1942_In_" "Chromaticity_Diagram_CIE1960UCS.png", ) plt.close( plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1960UCS( **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Ellipses_MacAdam1942_In_" "Chromaticity_Diagram_CIE1976UCS.png", ) plt.close( plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1976UCS( **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_CCTF.png" ) plt.close(plot_single_cctf("ITU-R BT.709", **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Multi_CCTFs.png" ) plt.close(plot_multi_cctfs(["ITU-R BT.709", "sRGB"], **arguments)[0]) data = np.array( [ [ None, np.array([0.95010000, 1.00000000, 1.08810000]), np.array([0.40920000, 0.28120000, 0.30600000]), np.array( [ [0.02495100, 0.01908600, 0.02032900], [0.10944300, 0.06235900, 0.06788100], [0.27186500, 0.18418700, 0.19565300], [0.48898900, 0.40749400, 0.44854600], ] ), None, ], [ None, np.array([0.95010000, 1.00000000, 1.08810000]), np.array([0.30760000, 0.48280000, 0.42770000]), np.array( [ [0.02108000, 0.02989100, 0.02790400], [0.06194700, 0.11251000, 0.09334400], [0.15255800, 0.28123300, 0.23234900], [0.34157700, 0.56681300, 0.47035300], ] ), None, ], [ None, np.array([0.95010000, 1.00000000, 1.08810000]), np.array([0.39530000, 0.28120000, 0.18450000]), np.array( [ [0.02436400, 0.01908600, 0.01468800], [0.10331200, 0.06235900, 0.02854600], [0.26311900, 0.18418700, 0.12109700], [0.43158700, 0.40749400, 0.39008600], ] ), None, ], [ None, np.array([0.95010000, 1.00000000, 1.08810000]), np.array([0.20510000, 0.18420000, 0.57130000]), np.array( [ [0.03039800, 0.02989100, 0.06123300], [0.08870000, 0.08498400, 0.21843500], [0.18405800, 0.18418700, 0.40111400], [0.32550100, 0.34047200, 0.50296900], [0.53826100, 0.56681300, 0.80010400], ] ), None, ], [ None, np.array([0.95010000, 1.00000000, 1.08810000]), np.array([0.35770000, 0.28120000, 0.11250000]), np.array( [ [0.03678100, 0.02989100, 0.01481100], [0.17127700, 0.11251000, 0.01229900], [0.30080900, 0.28123300, 0.21229800], [0.52976000, 0.40749400, 0.11720000], ] ), None, ], ] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Constant_Hue_Loci.png" ) plt.close(plot_constant_hue_loci(data, "IPT", **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_Munsell_Value_Function.png" ) plt.close(plot_single_munsell_value_function("ASTM D1535", **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Multi_Munsell_Value_Functions.png" ) plt.close( plot_multi_munsell_value_functions( ["ASTM D1535", "McCamy 1987"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_SD_Rayleigh_Scattering.png" ) plt.close(plot_single_sd_rayleigh_scattering(**arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_The_Blue_Sky.png" ) plt.close(plot_the_blue_sky(**arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Colour_Quality_Bars.png" ) illuminant = SDS_ILLUMINANTS["FL2"] light_source = SDS_LIGHT_SOURCES["Kinoton 75P"] light_source = light_source.copy().align(SpectralShape(360, 830, 1)) cqs_i = colour_quality_scale(illuminant, additional_data=True) cqs_l = colour_quality_scale(light_source, additional_data=True) plt.close(plot_colour_quality_bars([cqs_i, cqs_l], **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_SD_Colour_Rendering_Index_Bars.png", ) illuminant = SDS_ILLUMINANTS["FL2"] plt.close( plot_single_sd_colour_rendering_index_bars(illuminant, **arguments)[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Multi_SDS_Colour_Rendering_Indexes_Bars.png", ) light_source = SDS_LIGHT_SOURCES["Kinoton 75P"] plt.close( plot_multi_sds_colour_rendering_indexes_bars( [illuminant, light_source], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_SD_Colour_Quality_Scale_Bars.png", ) illuminant = SDS_ILLUMINANTS["FL2"] plt.close( plot_single_sd_colour_quality_scale_bars(illuminant, **arguments)[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Multi_SDS_Colour_Quality_Scales_Bars.png", ) light_source = SDS_LIGHT_SOURCES["Kinoton 75P"] plt.close( plot_multi_sds_colour_quality_scales_bars( [illuminant, light_source], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Hull_Section_Colours.png" ) vertices, faces, _outline = primitive_cube(1, 1, 1, 64, 64, 64) XYZ_vertices = RGB_to_XYZ( vertices["position"] + 0.5, RGB_COLOURSPACE_sRGB.whitepoint, RGB_COLOURSPACE_sRGB.whitepoint, RGB_COLOURSPACE_sRGB.matrix_RGB_to_XYZ, ) hull = trimesh.Trimesh(XYZ_vertices, faces, process=False) plt.close( plot_hull_section_colours(hull, section_colours="RGB", **arguments)[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Hull_Section_Contour.png" ) plt.close( plot_hull_section_contour(hull, section_colours="RGB", **arguments)[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Visible_Spectrum_Section.png" ) plt.close( plot_visible_spectrum_section( section_colours="RGB", section_opacity=0.15, **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_RGB_Colourspace_Section.png" ) plt.close( plot_RGB_colourspace_section( "sRGB", section_colours="RGB", section_opacity=0.15, **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Planckian_Locus.png" ) plt.close( plot_planckian_locus(planckian_locus_colours="RGB", **arguments)[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Planckian_Locus_In_Chromaticity_Diagram.png", ) plt.close( plot_planckian_locus_in_chromaticity_diagram( ["A", "B", "C"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Planckian_Locus_In_Chromaticity_Diagram_CIE1931.png", ) plt.close( plot_planckian_locus_in_chromaticity_diagram_CIE1931( ["A", "B", "C"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Planckian_Locus_In_Chromaticity_Diagram_CIE1960UCS.png", ) plt.close( plot_planckian_locus_in_chromaticity_diagram_CIE1960UCS( ["A", "B", "C"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_SD_Colour_Rendition_Report_Full.png", ) plt.close( plot_single_sd_colour_rendition_report( SDS_ILLUMINANTS["FL2"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_SD_Colour_Rendition_Report_Intermediate.png", ) plt.close( plot_single_sd_colour_rendition_report( SDS_ILLUMINANTS["FL2"], "Intermediate", **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_Single_SD_Colour_Rendition_Report_Simple.png", ) plt.close( plot_single_sd_colour_rendition_report( SDS_ILLUMINANTS["FL2"], "Simple", **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_RGB_Colourspaces_Gamuts.png" ) plt.close( plot_RGB_colourspaces_gamuts( ["ITU-R BT.709", "ACEScg", "S-Gamut"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_RGB_Colourspaces_Gamuts.png" ) plt.close( plot_RGB_colourspaces_gamuts( ["ITU-R BT.709", "ACEScg", "S-Gamut"], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Plotting_Plot_RGB_Scatter.png" ) plt.close(plot_RGB_scatter(RGB, "ITU-R BT.709", **arguments)[0]) filename = os.path.join( output_directory, "Plotting_Plot_Colour_Automatic_Conversion_Graph.png" ) plot_automatic_colour_conversion_graph(filename) # ************************************************************************* # "tutorial.rst" # ************************************************************************* arguments["filename"] = os.path.join( output_directory, "Tutorial_Visible_Spectrum.png" ) plt.close(plot_visible_spectrum(**arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Tutorial_Sample_SD.png" ) sample_sd_data = { 380: 0.048, 385: 0.051, 390: 0.055, 395: 0.060, 400: 0.065, 405: 0.068, 410: 0.068, 415: 0.067, 420: 0.064, 425: 0.062, 430: 0.059, 435: 0.057, 440: 0.055, 445: 0.054, 450: 0.053, 455: 0.053, 460: 0.052, 465: 0.052, 470: 0.052, 475: 0.053, 480: 0.054, 485: 0.055, 490: 0.057, 495: 0.059, 500: 0.061, 505: 0.062, 510: 0.065, 515: 0.067, 520: 0.070, 525: 0.072, 530: 0.074, 535: 0.075, 540: 0.076, 545: 0.078, 550: 0.079, 555: 0.082, 560: 0.087, 565: 0.092, 570: 0.100, 575: 0.107, 580: 0.115, 585: 0.122, 590: 0.129, 595: 0.134, 600: 0.138, 605: 0.142, 610: 0.146, 615: 0.150, 620: 0.154, 625: 0.158, 630: 0.163, 635: 0.167, 640: 0.173, 645: 0.180, 650: 0.188, 655: 0.196, 660: 0.204, 665: 0.213, 670: 0.222, 675: 0.231, 680: 0.242, 685: 0.251, 690: 0.261, 695: 0.271, 700: 0.282, 705: 0.294, 710: 0.305, 715: 0.318, 720: 0.334, 725: 0.354, 730: 0.372, 735: 0.392, 740: 0.409, 745: 0.420, 750: 0.436, 755: 0.450, 760: 0.462, 765: 0.465, 770: 0.448, 775: 0.432, 780: 0.421, } sd = SpectralDistribution(sample_sd_data, name="Sample") plt.close(plot_single_sd(sd, **arguments)[0]) arguments["filename"] = os.path.join( output_directory, "Tutorial_SD_Interpolation.png" ) sd_copy = sd.copy() sd_copy.interpolate(SpectralShape(400, 770, 1)) plt.close( plot_multi_sds( [sd, sd_copy], bounding_box=[730, 780, 0.25, 0.5], **arguments )[0] ) arguments["filename"] = os.path.join( output_directory, "Tutorial_Sample_Swatch.png" ) sd = SpectralDistribution(sample_sd_data) cmfs = MSDS_CMFS_STANDARD_OBSERVER["CIE 1931 2 Degree Standard Observer"] illuminant = SDS_ILLUMINANTS["D65"] with domain_range_scale("1"): XYZ = sd_to_XYZ(sd, cmfs, illuminant) RGB = XYZ_to_sRGB(XYZ) plt.close( plot_single_colour_swatch( ColourSwatch(RGB, "Sample"), text_kwargs={"size": "x-large"}, **arguments, )[0] ) arguments["filename"] = os.path.join( output_directory, "Tutorial_Neutral5.png" ) patch_name = "neutral 5 (.70 D)" patch_sd = SDS_COLOURCHECKERS["ColorChecker N Ohta"][patch_name] with domain_range_scale("1"): XYZ = sd_to_XYZ(patch_sd, cmfs, illuminant) RGB = XYZ_to_sRGB(XYZ) plt.close( plot_single_colour_swatch( ColourSwatch(RGB, patch_name.title()), text_kwargs={"size": "x-large"}, **arguments, )[0] ) arguments["filename"] = os.path.join( output_directory, "Tutorial_Colour_Checker.png" ) plt.close( plot_single_colour_checker( colour_checker="ColorChecker 2005", text_kwargs={"visible": False}, **arguments, )[0] ) arguments["filename"] = os.path.join( output_directory, "Tutorial_CIE_1931_Chromaticity_Diagram.png" ) xy = XYZ_to_xy(XYZ) plot_chromaticity_diagram_CIE1931(standalone=False) x, y = xy plt.plot(x, y, "o-", color="white") # Annotating the plot. plt.annotate( patch_sd.name.title(), xy=xy, xytext=(-50, 30), textcoords="offset points", arrowprops=dict(arrowstyle="->", connectionstyle="arc3, rad=-0.2"), ) plt.close( render( standalone=True, limits=(-0.1, 0.9, -0.1, 0.9), x_tighten=True, y_tighten=True, **arguments, )[0] ) # ************************************************************************* # "basics.rst" # ************************************************************************* arguments["filename"] = os.path.join( output_directory, "Basics_Logo_Small_001_CIE_XYZ.png" ) RGB = read_image(os.path.join(output_directory, "Logo_Small_001.png"))[ ..., 0:3 ] XYZ = sRGB_to_XYZ(RGB) plt.close( plot_image(XYZ, text_kwargs={"text": "sRGB to XYZ"}, **arguments)[0] )
def colour_quality_scale(sd_test, additional_data=False): """ Returns the *Colour Quality Scale* (CQS) of given spectral distribution. Parameters ---------- sd_test : SpectralDistribution Test spectral distribution. additional_data : bool, optional Whether to output additional data. Returns ------- numeric or CQS_Specification Color quality scale. References ---------- :cite:`Davis2010a`, :cite:`Ohno2008a` Examples -------- >>> from colour import ILLUMINANTS_SDS >>> sd = ILLUMINANTS_SDS['FL2'] >>> colour_quality_scale(sd) # doctest: +ELLIPSIS 64.6863391... """ cmfs = STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer'].copy( ).trim(ASTME30815_PRACTISE_SHAPE) shape = cmfs.shape sd_test = sd_test.copy().align(shape) vs_sds = {sd.name: sd.copy().align(shape) for sd in VS_SDS.values()} with domain_range_scale('1'): XYZ = sd_to_XYZ(sd_test, cmfs) uv = UCS_to_uv(XYZ_to_UCS(XYZ)) CCT, _D_uv = uv_to_CCT_Ohno2013(uv) if CCT < 5000: sd_reference = sd_blackbody(CCT, shape) else: xy = CCT_to_xy_CIE_D(CCT) sd_reference = sd_CIE_illuminant_D_series(xy) sd_reference.align(shape) test_vs_colorimetry_data = vs_colorimetry_data(sd_test, sd_reference, vs_sds, cmfs, chromatic_adaptation=True) reference_vs_colorimetry_data = vs_colorimetry_data( sd_reference, sd_reference, vs_sds, cmfs) XYZ_r = sd_to_XYZ(sd_reference, cmfs) XYZ_r /= XYZ_r[1] CCT_f = CCT_factor(reference_vs_colorimetry_data, XYZ_r) Q_as = colour_quality_scales(test_vs_colorimetry_data, reference_vs_colorimetry_data, CCT_f) D_E_RMS = delta_E_RMS(Q_as, 'D_E_ab') D_Ep_RMS = delta_E_RMS(Q_as, 'D_Ep_ab') Q_a = scale_conversion(D_Ep_RMS, CCT_f) Q_f = scale_conversion(D_E_RMS, CCT_f, 2.928) p_delta_C = np.average( [sample_data.D_C_ab if sample_data.D_C_ab > 0 else 0 for sample_data in Q_as.values()]) # yapf: disable Q_p = 100 - 3.6 * (D_Ep_RMS - p_delta_C) G_t = gamut_area( [vs_CQS_data.Lab for vs_CQS_data in test_vs_colorimetry_data]) G_r = gamut_area( [vs_CQS_data.Lab for vs_CQS_data in reference_vs_colorimetry_data]) Q_g = G_t / D65_GAMUT_AREA * 100 Q_d = G_t / G_r * CCT_f * 100 if additional_data: return CQS_Specification( sd_test.name, Q_a, Q_f, Q_p, Q_g, Q_d, Q_as, (test_vs_colorimetry_data, reference_vs_colorimetry_data)) else: return Q_a
def generate_documentation_plots(output_directory): """ Generates documentation plots. Parameters ---------- output_directory : unicode Output directory. """ filter_warnings() colour_style() np.random.seed(0) # ************************************************************************* # "README.rst" # ************************************************************************* filename = os.path.join(output_directory, 'Examples_Colour_Automatic_Conversion_Graph.png') plot_automatic_colour_conversion_graph(filename) arguments = { 'tight_layout': True, 'transparent_background': True, 'filename': os.path.join(output_directory, 'Examples_Plotting_Visible_Spectrum.png') } plt.close( plot_visible_spectrum('CIE 1931 2 Degree Standard Observer', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Examples_Plotting_Illuminant_F1_SD.png') plt.close(plot_single_illuminant_sd('FL1', **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Examples_Plotting_Blackbodies.png') blackbody_sds = [ sd_blackbody(i, SpectralShape(0, 10000, 10)) for i in range(1000, 15000, 1000) ] plt.close( plot_multi_sds(blackbody_sds, y_label='W / (sr m$^2$) / m', use_sds_colours=True, normalise_sds_colours=True, legend_location='upper right', bounding_box=(0, 1250, 0, 2.5e15), **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Examples_Plotting_Cone_Fundamentals.png') plt.close( plot_single_cmfs('Stockman & Sharpe 2 Degree Cone Fundamentals', y_label='Sensitivity', bounding_box=(390, 870, 0, 1.1), **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Examples_Plotting_Luminous_Efficiency.png') plt.close( plot_multi_sds((sd_mesopic_luminous_efficiency_function(0.2), PHOTOPIC_LEFS['CIE 1924 Photopic Standard Observer'], SCOTOPIC_LEFS['CIE 1951 Scotopic Standard Observer']), y_label='Luminous Efficiency', legend_location='upper right', y_tighten=True, margins=(0, 0, 0, .1), **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Examples_Plotting_BabelColor_Average.png') plt.close( plot_multi_sds(COLOURCHECKERS_SDS['BabelColor Average'].values(), use_sds_colours=True, title=('BabelColor Average - ' 'Spectral Distributions'), **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Examples_Plotting_ColorChecker_2005.png') plt.close( plot_single_colour_checker('ColorChecker 2005', text_parameters={'visible': False}, **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Examples_Plotting_Chromaticities_Prediction.png') plt.close( plot_corresponding_chromaticities_prediction(2, 'Von Kries', 'Bianco', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Examples_Plotting_CCT_CIE_1960_UCS_Chromaticity_Diagram.png') plt.close( plot_planckian_locus_in_chromaticity_diagram_CIE1960UCS( ['A', 'B', 'C'], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Examples_Plotting_Chromaticities_CIE_1931_Chromaticity_Diagram.png') RGB = np.random.random((32, 32, 3)) plt.close( plot_RGB_chromaticities_in_chromaticity_diagram_CIE1931( RGB, 'ITU-R BT.709', colourspaces=['ACEScg', 'S-Gamut'], show_pointer_gamut=True, **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Examples_Plotting_CRI.png') plt.close( plot_single_sd_colour_rendering_index_bars(ILLUMINANTS_SDS['FL2'], **arguments)[0]) # ************************************************************************* # Documentation # ************************************************************************* arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_CVD_Simulation_Machado2009.png') plt.close(plot_cvd_simulation_Machado2009(RGB, **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Single_Colour_Checker.png') plt.close(plot_single_colour_checker('ColorChecker 2005', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Multi_Colour_Checkers.png') plt.close( plot_multi_colour_checkers(['ColorChecker 1976', 'ColorChecker 2005'], **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_Single_SD.png') data = { 500: 0.0651, 520: 0.0705, 540: 0.0772, 560: 0.0870, 580: 0.1128, 600: 0.1360 } sd = SpectralDistribution(data, name='Custom') plt.close(plot_single_sd(sd, **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_Multi_SDS.png') data_1 = { 500: 0.004900, 510: 0.009300, 520: 0.063270, 530: 0.165500, 540: 0.290400, 550: 0.433450, 560: 0.594500 } data_2 = { 500: 0.323000, 510: 0.503000, 520: 0.710000, 530: 0.862000, 540: 0.954000, 550: 0.994950, 560: 0.995000 } spd1 = SpectralDistribution(data_1, name='Custom 1') spd2 = SpectralDistribution(data_2, name='Custom 2') plt.close(plot_multi_sds([spd1, spd2], **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_Single_CMFS.png') plt.close( plot_single_cmfs('CIE 1931 2 Degree Standard Observer', **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_Multi_CMFS.png') cmfs = ('CIE 1931 2 Degree Standard Observer', 'CIE 1964 10 Degree Standard Observer') plt.close(plot_multi_cmfs(cmfs, **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Single_Illuminant_SD.png') plt.close(plot_single_illuminant_sd('A', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Multi_Illuminant_SDS.png') plt.close(plot_multi_illuminant_sds(['A', 'B', 'C'], **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_Visible_Spectrum.png') plt.close(plot_visible_spectrum(**arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Single_Lightness_Function.png') plt.close(plot_single_lightness_function('CIE 1976', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Multi_Lightness_Functions.png') plt.close( plot_multi_lightness_functions(['CIE 1976', 'Wyszecki 1963'], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Single_Luminance_Function.png') plt.close(plot_single_luminance_function('CIE 1976', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Multi_Luminance_Functions.png') plt.close( plot_multi_luminance_functions(['CIE 1976', 'Newhall 1943'], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Blackbody_Spectral_Radiance.png') plt.close( plot_blackbody_spectral_radiance(3500, blackbody='VY Canis Major', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Blackbody_Colours.png') plt.close( plot_blackbody_colours(SpectralShape(150, 12500, 50), **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Single_Colour_Swatch.png') RGB = ColourSwatch(RGB=(0.45620519, 0.03081071, 0.04091952)) plt.close(plot_single_colour_swatch(RGB, **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Multi_Colour_Swatches.png') RGB_1 = ColourSwatch(RGB=(0.45293517, 0.31732158, 0.26414773)) RGB_2 = ColourSwatch(RGB=(0.77875824, 0.57726450, 0.50453169)) plt.close(plot_multi_colour_swatches([RGB_1, RGB_2], **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_Single_Function.png') plt.close(plot_single_function(lambda x: x**(1 / 2.2), **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_Multi_Functions.png') functions = { 'Gamma 2.2': lambda x: x**(1 / 2.2), 'Gamma 2.4': lambda x: x**(1 / 2.4), 'Gamma 2.6': lambda x: x**(1 / 2.6), } plt.close(plot_multi_functions(functions, **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_Image.png') path = os.path.join(output_directory, 'Logo_Medium_001.png') plt.close(plot_image(read_image(str(path)), **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Corresponding_Chromaticities_Prediction.png') plt.close( plot_corresponding_chromaticities_prediction(1, 'Von Kries', 'CAT02', **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_Spectral_Locus.png') plt.close( plot_spectral_locus(spectral_locus_colours='RGB', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Chromaticity_Diagram_Colours.png') plt.close(plot_chromaticity_diagram_colours(**arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Chromaticity_Diagram.png') plt.close(plot_chromaticity_diagram(**arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Chromaticity_Diagram_CIE1931.png') plt.close(plot_chromaticity_diagram_CIE1931(**arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Chromaticity_Diagram_CIE1960UCS.png') plt.close(plot_chromaticity_diagram_CIE1960UCS(**arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Chromaticity_Diagram_CIE1976UCS.png') plt.close(plot_chromaticity_diagram_CIE1976UCS(**arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_SDS_In_Chromaticity_Diagram.png') A = ILLUMINANTS_SDS['A'] D65 = ILLUMINANTS_SDS['D65'] plt.close(plot_sds_in_chromaticity_diagram([A, D65], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_SDS_In_Chromaticity_Diagram_CIE1931.png') plt.close( plot_sds_in_chromaticity_diagram_CIE1931([A, D65], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_SDS_In_Chromaticity_Diagram_CIE1960UCS.png') plt.close( plot_sds_in_chromaticity_diagram_CIE1960UCS([A, D65], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_SDS_In_Chromaticity_Diagram_CIE1976UCS.png') plt.close( plot_sds_in_chromaticity_diagram_CIE1976UCS([A, D65], **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_Pointer_Gamut.png') plt.close(plot_pointer_gamut(**arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_RGB_Colourspaces_In_Chromaticity_Diagram.png') plt.close( plot_RGB_colourspaces_in_chromaticity_diagram( ['ITU-R BT.709', 'ACEScg', 'S-Gamut'], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_RGB_Colourspaces_In_Chromaticity_Diagram_CIE1931.png') plt.close( plot_RGB_colourspaces_in_chromaticity_diagram_CIE1931( ['ITU-R BT.709', 'ACEScg', 'S-Gamut'], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_RGB_Colourspaces_In_' 'Chromaticity_Diagram_CIE1960UCS.png') plt.close( plot_RGB_colourspaces_in_chromaticity_diagram_CIE1960UCS( ['ITU-R BT.709', 'ACEScg', 'S-Gamut'], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_RGB_Colourspaces_In_' 'Chromaticity_Diagram_CIE1976UCS.png') plt.close( plot_RGB_colourspaces_in_chromaticity_diagram_CIE1976UCS( ['ITU-R BT.709', 'ACEScg', 'S-Gamut'], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_RGB_Chromaticities_In_' 'Chromaticity_Diagram.png') RGB = np.random.random((128, 128, 3)) plt.close( plot_RGB_chromaticities_in_chromaticity_diagram( RGB, 'ITU-R BT.709', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_RGB_Chromaticities_In_' 'Chromaticity_Diagram_CIE1931.png') plt.close( plot_RGB_chromaticities_in_chromaticity_diagram_CIE1931( RGB, 'ITU-R BT.709', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_RGB_Chromaticities_In_' 'Chromaticity_Diagram_CIE1960UCS.png') plt.close( plot_RGB_chromaticities_in_chromaticity_diagram_CIE1960UCS( RGB, 'ITU-R BT.709', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_RGB_Chromaticities_In_' 'Chromaticity_Diagram_CIE1976UCS.png') plt.close( plot_RGB_chromaticities_in_chromaticity_diagram_CIE1976UCS( RGB, 'ITU-R BT.709', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Ellipses_MacAdam1942_In_Chromaticity_Diagram.png') plt.close( plot_ellipses_MacAdam1942_in_chromaticity_diagram(**arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Ellipses_MacAdam1942_In_' 'Chromaticity_Diagram_CIE1931.png') plt.close( plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1931( **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Ellipses_MacAdam1942_In_' 'Chromaticity_Diagram_CIE1960UCS.png') plt.close( plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1960UCS( **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Ellipses_MacAdam1942_In_' 'Chromaticity_Diagram_CIE1976UCS.png') plt.close( plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1976UCS( **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_Single_CCTF.png') plt.close(plot_single_cctf('ITU-R BT.709', **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_Multi_CCTFs.png') plt.close(plot_multi_cctfs(['ITU-R BT.709', 'sRGB'], **arguments)[0]) data = np.array([ [ None, np.array([0.95010000, 1.00000000, 1.08810000]), np.array([0.40920000, 0.28120000, 0.30600000]), np.array([ [0.02495100, 0.01908600, 0.02032900], [0.10944300, 0.06235900, 0.06788100], [0.27186500, 0.18418700, 0.19565300], [0.48898900, 0.40749400, 0.44854600], ]), None, ], [ None, np.array([0.95010000, 1.00000000, 1.08810000]), np.array([0.30760000, 0.48280000, 0.42770000]), np.array([ [0.02108000, 0.02989100, 0.02790400], [0.06194700, 0.11251000, 0.09334400], [0.15255800, 0.28123300, 0.23234900], [0.34157700, 0.56681300, 0.47035300], ]), None, ], [ None, np.array([0.95010000, 1.00000000, 1.08810000]), np.array([0.39530000, 0.28120000, 0.18450000]), np.array([ [0.02436400, 0.01908600, 0.01468800], [0.10331200, 0.06235900, 0.02854600], [0.26311900, 0.18418700, 0.12109700], [0.43158700, 0.40749400, 0.39008600], ]), None, ], [ None, np.array([0.95010000, 1.00000000, 1.08810000]), np.array([0.20510000, 0.18420000, 0.57130000]), np.array([ [0.03039800, 0.02989100, 0.06123300], [0.08870000, 0.08498400, 0.21843500], [0.18405800, 0.18418700, 0.40111400], [0.32550100, 0.34047200, 0.50296900], [0.53826100, 0.56681300, 0.80010400], ]), None, ], [ None, np.array([0.95010000, 1.00000000, 1.08810000]), np.array([0.35770000, 0.28120000, 0.11250000]), np.array([ [0.03678100, 0.02989100, 0.01481100], [0.17127700, 0.11251000, 0.01229900], [0.30080900, 0.28123300, 0.21229800], [0.52976000, 0.40749400, 0.11720000], ]), None, ], ]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Constant_Hue_Loci.png') plt.close(plot_constant_hue_loci(data, 'IPT', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Single_Munsell_Value_Function.png') plt.close(plot_single_munsell_value_function('ASTM D1535', **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Multi_Munsell_Value_Functions.png') plt.close( plot_multi_munsell_value_functions(['ASTM D1535', 'McCamy 1987'], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Single_SD_Rayleigh_Scattering.png') plt.close(plot_single_sd_rayleigh_scattering(**arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_The_Blue_Sky.png') plt.close(plot_the_blue_sky(**arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Colour_Quality_Bars.png') illuminant = ILLUMINANTS_SDS['FL2'] light_source = LIGHT_SOURCES_SDS['Kinoton 75P'] light_source = light_source.copy().align(SpectralShape(360, 830, 1)) cqs_i = colour_quality_scale(illuminant, additional_data=True) cqs_l = colour_quality_scale(light_source, additional_data=True) plt.close(plot_colour_quality_bars([cqs_i, cqs_l], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Single_SD_Colour_Rendering_Index_Bars.png') illuminant = ILLUMINANTS_SDS['FL2'] plt.close( plot_single_sd_colour_rendering_index_bars(illuminant, **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Multi_SDS_Colour_Rendering_Indexes_Bars.png') light_source = LIGHT_SOURCES_SDS['Kinoton 75P'] plt.close( plot_multi_sds_colour_rendering_indexes_bars( [illuminant, light_source], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Single_SD_Colour_Quality_Scale_Bars.png') illuminant = ILLUMINANTS_SDS['FL2'] plt.close( plot_single_sd_colour_quality_scale_bars(illuminant, **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Multi_SDS_Colour_Quality_Scales_Bars.png') light_source = LIGHT_SOURCES_SDS['Kinoton 75P'] plt.close( plot_multi_sds_colour_quality_scales_bars([illuminant, light_source], **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_Planckian_Locus.png') plt.close(plot_planckian_locus(**arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Planckian_Locus_CIE1931.png') plt.close(plot_planckian_locus_CIE1931(**arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Planckian_Locus_CIE1960UCS.png') plt.close(plot_planckian_locus_CIE1960UCS(**arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Planckian_Locus_In_Chromaticity_Diagram.png') plt.close( plot_planckian_locus_in_chromaticity_diagram(['A', 'B', 'C'], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Planckian_Locus_In_Chromaticity_Diagram_CIE1931.png') plt.close( plot_planckian_locus_in_chromaticity_diagram_CIE1931(['A', 'B', 'C'], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_Planckian_Locus_In_Chromaticity_Diagram_CIE1960UCS.png') plt.close( plot_planckian_locus_in_chromaticity_diagram_CIE1960UCS( ['A', 'B', 'C'], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_RGB_Colourspaces_Gamuts.png') plt.close( plot_RGB_colourspaces_gamuts(['ITU-R BT.709', 'ACEScg', 'S-Gamut'], **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Plotting_Plot_RGB_Colourspaces_Gamuts.png') plt.close( plot_RGB_colourspaces_gamuts(['ITU-R BT.709', 'ACEScg', 'S-Gamut'], **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Plotting_Plot_RGB_Scatter.png') plt.close(plot_RGB_scatter(RGB, 'ITU-R BT.709', **arguments)[0]) filename = os.path.join( output_directory, 'Plotting_Plot_Colour_Automatic_Conversion_Graph.png') plot_automatic_colour_conversion_graph(filename) # ************************************************************************* # "tutorial.rst" # ************************************************************************* arguments['filename'] = os.path.join(output_directory, 'Tutorial_Visible_Spectrum.png') plt.close(plot_visible_spectrum(**arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Tutorial_Sample_SD.png') sample_sd_data = { 380: 0.048, 385: 0.051, 390: 0.055, 395: 0.060, 400: 0.065, 405: 0.068, 410: 0.068, 415: 0.067, 420: 0.064, 425: 0.062, 430: 0.059, 435: 0.057, 440: 0.055, 445: 0.054, 450: 0.053, 455: 0.053, 460: 0.052, 465: 0.052, 470: 0.052, 475: 0.053, 480: 0.054, 485: 0.055, 490: 0.057, 495: 0.059, 500: 0.061, 505: 0.062, 510: 0.065, 515: 0.067, 520: 0.070, 525: 0.072, 530: 0.074, 535: 0.075, 540: 0.076, 545: 0.078, 550: 0.079, 555: 0.082, 560: 0.087, 565: 0.092, 570: 0.100, 575: 0.107, 580: 0.115, 585: 0.122, 590: 0.129, 595: 0.134, 600: 0.138, 605: 0.142, 610: 0.146, 615: 0.150, 620: 0.154, 625: 0.158, 630: 0.163, 635: 0.167, 640: 0.173, 645: 0.180, 650: 0.188, 655: 0.196, 660: 0.204, 665: 0.213, 670: 0.222, 675: 0.231, 680: 0.242, 685: 0.251, 690: 0.261, 695: 0.271, 700: 0.282, 705: 0.294, 710: 0.305, 715: 0.318, 720: 0.334, 725: 0.354, 730: 0.372, 735: 0.392, 740: 0.409, 745: 0.420, 750: 0.436, 755: 0.450, 760: 0.462, 765: 0.465, 770: 0.448, 775: 0.432, 780: 0.421 } sd = SpectralDistribution(sample_sd_data, name='Sample') plt.close(plot_single_sd(sd, **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Tutorial_SD_Interpolation.png') sd_copy = sd.copy() sd_copy.interpolate(SpectralShape(400, 770, 1)) plt.close( plot_multi_sds([sd, sd_copy], bounding_box=[730, 780, 0.25, 0.5], **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Tutorial_Sample_Swatch.png') sd = SpectralDistribution(sample_sd_data) cmfs = STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer'] illuminant = ILLUMINANTS_SDS['D65'] with domain_range_scale('1'): XYZ = sd_to_XYZ(sd, cmfs, illuminant) RGB = XYZ_to_sRGB(XYZ) plt.close( plot_single_colour_swatch(ColourSwatch('Sample', RGB), text_parameters={'size': 'x-large'}, **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Tutorial_Neutral5.png') patch_name = 'neutral 5 (.70 D)' patch_sd = COLOURCHECKERS_SDS['ColorChecker N Ohta'][patch_name] with domain_range_scale('1'): XYZ = sd_to_XYZ(patch_sd, cmfs, illuminant) RGB = XYZ_to_sRGB(XYZ) plt.close( plot_single_colour_swatch(ColourSwatch(patch_name.title(), RGB), text_parameters={'size': 'x-large'}, **arguments)[0]) arguments['filename'] = os.path.join(output_directory, 'Tutorial_Colour_Checker.png') plt.close( plot_single_colour_checker(colour_checker='ColorChecker 2005', text_parameters={'visible': False}, **arguments)[0]) arguments['filename'] = os.path.join( output_directory, 'Tutorial_CIE_1931_Chromaticity_Diagram.png') xy = XYZ_to_xy(XYZ) plot_chromaticity_diagram_CIE1931(standalone=False) x, y = xy plt.plot(x, y, 'o-', color='white') # Annotating the plot. plt.annotate(patch_sd.name.title(), xy=xy, xytext=(-50, 30), textcoords='offset points', arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=-0.2')) plt.close( render(standalone=True, limits=(-0.1, 0.9, -0.1, 0.9), x_tighten=True, y_tighten=True, **arguments)[0]) # ************************************************************************* # "basics.rst" # ************************************************************************* arguments['filename'] = os.path.join(output_directory, 'Basics_Logo_Small_001_CIE_XYZ.png') RGB = read_image(os.path.join(output_directory, 'Logo_Small_001.png'))[..., 0:3] XYZ = sRGB_to_XYZ(RGB) plt.close( plot_image(XYZ, text_parameters={'text': 'sRGB to XYZ'}, **arguments)[0])
def colour_quality_scale( sd_test: SpectralDistribution, additional_data: Boolean = False, method: Union[Literal["NIST CQS 7.4", "NIST CQS 9.0"], str] = "NIST CQS 9.0", ) -> Union[Floating, ColourRendering_Specification_CQS]: """ Return the *Colour Quality Scale* (CQS) of given spectral distribution using given method. Parameters ---------- sd_test Test spectral distribution. additional_data Whether to output additional data. method Computation method. Returns ------- :class:`numpy.floating` or \ :class:`colour.quality.ColourRendering_Specification_CQS` *Colour Quality Scale* (CQS). References ---------- :cite:`Davis2010a`, :cite:`Ohno2008a`, :cite:`Ohno2013` Examples -------- >>> from colour import SDS_ILLUMINANTS >>> sd = SDS_ILLUMINANTS['FL2'] >>> colour_quality_scale(sd) # doctest: +ELLIPSIS 64.1117031... """ method = validate_method(method, COLOUR_QUALITY_SCALE_METHODS) # pylint: disable=E1102 cmfs = reshape_msds( MSDS_CMFS["CIE 1931 2 Degree Standard Observer"], SPECTRAL_SHAPE_DEFAULT, ) shape = cmfs.shape sd_test = reshape_sd(sd_test, shape) vs_sds = {sd.name: reshape_sd(sd, shape) for sd in SDS_VS[method].values()} with domain_range_scale("1"): XYZ = sd_to_XYZ(sd_test, cmfs) uv = UCS_to_uv(XYZ_to_UCS(XYZ)) CCT, _D_uv = uv_to_CCT_Ohno2013(uv) if CCT < 5000: sd_reference = sd_blackbody(CCT, shape) else: xy = CCT_to_xy_CIE_D(CCT) sd_reference = sd_CIE_illuminant_D_series(xy) sd_reference.align(shape) test_vs_colorimetry_data = vs_colorimetry_data(sd_test, sd_reference, vs_sds, cmfs, chromatic_adaptation=True) reference_vs_colorimetry_data = vs_colorimetry_data( sd_reference, sd_reference, vs_sds, cmfs) CCT_f: Floating if method == "nist cqs 9.0": CCT_f = 1 scaling_f = 3.2 else: XYZ_r = sd_to_XYZ(sd_reference, cmfs) XYZ_r /= XYZ_r[1] CCT_f = CCT_factor(reference_vs_colorimetry_data, XYZ_r) scaling_f = 3.104 Q_as = colour_quality_scales( test_vs_colorimetry_data, reference_vs_colorimetry_data, scaling_f, CCT_f, ) D_E_RMS = delta_E_RMS(Q_as, "D_E_ab") D_Ep_RMS = delta_E_RMS(Q_as, "D_Ep_ab") Q_a = scale_conversion(D_Ep_RMS, CCT_f, scaling_f) if method == "nist cqs 9.0": scaling_f = 2.93 * 1.0343 else: scaling_f = 2.928 Q_f = scale_conversion(D_E_RMS, CCT_f, scaling_f) G_t = gamut_area( [vs_CQS_data.Lab for vs_CQS_data in test_vs_colorimetry_data]) G_r = gamut_area( [vs_CQS_data.Lab for vs_CQS_data in reference_vs_colorimetry_data]) Q_g = G_t / GAMUT_AREA_D65 * 100 if method == "nist cqs 9.0": Q_p = Q_d = None else: p_delta_C = np.average([ sample_data.D_C_ab if sample_data.D_C_ab > 0 else 0 for sample_data in Q_as.values() ]) Q_p = as_float_scalar(100 - 3.6 * (D_Ep_RMS - p_delta_C)) Q_d = as_float_scalar(G_t / G_r * CCT_f * 100) if additional_data: return ColourRendering_Specification_CQS( sd_test.name, Q_a, Q_f, Q_p, Q_g, Q_d, Q_as, (test_vs_colorimetry_data, reference_vs_colorimetry_data), ) else: return Q_a
def colour_rendering_index(sd_test, additional_data=False): """ Returns the *Colour Rendering Index* (CRI) :math:`Q_a` of given spectral distribution. Parameters ---------- sd_test : SpectralDistribution Test spectral distribution. additional_data : bool, optional Whether to output additional data. Returns ------- numeric or CRI_Specification *Colour Rendering Index* (CRI). References ---------- :cite:`Ohno2008a` Examples -------- >>> from colour import ILLUMINANTS_SDS >>> sd = ILLUMINANTS_SDS['FL2'] >>> colour_rendering_index(sd) # doctest: +ELLIPSIS 64.1515202... """ cmfs = STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer'].copy( ).trim(DEFAULT_SPECTRAL_SHAPE) shape = cmfs.shape sd_test = sd_test.copy().align(shape) tcs_sds = {sd.name: sd.copy().align(shape) for sd in TCS_SDS.values()} with domain_range_scale('1'): XYZ = sd_to_XYZ(sd_test, cmfs) uv = UCS_to_uv(XYZ_to_UCS(XYZ)) CCT, _D_uv = uv_to_CCT_Robertson1968(uv) if CCT < 5000: sd_reference = sd_blackbody(CCT, shape) else: xy = CCT_to_xy_CIE_D(CCT) sd_reference = sd_CIE_illuminant_D_series(xy) sd_reference.align(shape) test_tcs_colorimetry_data = tcs_colorimetry_data(sd_test, sd_reference, tcs_sds, cmfs, chromatic_adaptation=True) reference_tcs_colorimetry_data = tcs_colorimetry_data( sd_reference, sd_reference, tcs_sds, cmfs) Q_as = colour_rendering_indexes(test_tcs_colorimetry_data, reference_tcs_colorimetry_data) Q_a = np.average( [v.Q_a for k, v in Q_as.items() if k in (1, 2, 3, 4, 5, 6, 7, 8)]) if additional_data: return CRI_Specification( sd_test.name, Q_a, Q_as, (test_tcs_colorimetry_data, reference_tcs_colorimetry_data)) else: return Q_a
def generate_illuminants_rawtoaces_v1() -> CaseInsensitiveMapping: """ Generate a series of illuminants according to *RAW to ACES* v1: - *CIE Illuminant D Series* in range [4000, 25000] kelvin degrees. - *Blackbodies* in range [1000, 3500] kelvin degrees. - A.M.P.A.S. variant of *ISO 7589 Studio Tungsten*. Returns ------- :class:`colour.utilities.CaseInsensitiveMapping` Series of illuminants. Notes ----- - This definition introduces a few differences compared to *RAW to ACES* v1: *CIE Illuminant D Series* are computed in range [4002.15, 7003.77] kelvin degrees and the :math:`C_2` change is not used in *RAW to ACES* v1. References ---------- :cite:`Dyer2017` Examples -------- >>> list(sorted(generate_illuminants_rawtoaces_v1().keys())) ['1000K Blackbody', '1500K Blackbody', '2000K Blackbody', \ '2500K Blackbody', '3000K Blackbody', '3500K Blackbody', 'D100', 'D105', \ 'D110', 'D115', 'D120', 'D125', 'D130', 'D135', 'D140', 'D145', 'D150', \ 'D155', 'D160', 'D165', 'D170', 'D175', 'D180', 'D185', 'D190', 'D195', \ 'D200', 'D205', 'D210', 'D215', 'D220', 'D225', 'D230', 'D235', 'D240', \ 'D245', 'D250', 'D40', 'D45', 'D50', 'D55', 'D60', 'D65', 'D70', 'D75', \ 'D80', 'D85', 'D90', 'D95', 'iso7589'] """ global _ILLUMINANTS_RAWTOACES_V1 if _ILLUMINANTS_RAWTOACES_V1 is not None: illuminants = _ILLUMINANTS_RAWTOACES_V1 else: illuminants = CaseInsensitiveMapping() # CIE Illuminants D Series from 4000K to 25000K. for i in np.arange(4000, 25000 + 500, 500): CCT = i * 1.4388 / 1.4380 xy = CCT_to_xy_CIE_D(CCT) sd = sd_CIE_illuminant_D_series(xy) sd.name = f"D{int(CCT / 100):d}" illuminants[sd.name] = sd.align(SPECTRAL_SHAPE_RAWTOACES) # TODO: Remove when removing the "colour.sd_blackbody" definition # warning. with suppress_warnings(colour_usage_warnings=True): # Blackbody from 1000K to 4000K. for i in np.arange(1000, 4000, 500): sd = sd_blackbody(i, SPECTRAL_SHAPE_RAWTOACES) illuminants[sd.name] = sd # A.M.P.A.S. variant of ISO 7589 Studio Tungsten. sd = read_sds_from_csv_file( os.path.join(RESOURCES_DIRECTORY_RAWTOACES, "AMPAS_ISO_7589_Tungsten.csv"))["iso7589"] illuminants.update({sd.name: sd}) _ILLUMINANTS_RAWTOACES_V1 = illuminants return illuminants
def plot_blackbody_colours( shape=SpectralShape(150, 12500, 50), cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots blackbody colours. Parameters ---------- shape : SpectralShape, optional Spectral shape to use as plot boundaries. cmfs : unicode, optional Standard observer colour matching functions. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_blackbody_colours(SpectralShape(150, 12500, 50)) # doctest: +SKIP .. image:: ../_static/Plotting_Plot_Blackbody_Colours.png :align: center :alt: plot_blackbody_colours """ _figure, axes = artist(**kwargs) cmfs = first_item(filter_cmfs(cmfs).values()) colours = [] temperatures = [] for temperature in shape: sd = sd_blackbody(temperature, cmfs.shape) with domain_range_scale('1'): XYZ = sd_to_XYZ(sd, cmfs) RGB = normalise_maximum(XYZ_to_plotting_colourspace(XYZ)) colours.append(RGB) temperatures.append(temperature) x_min, x_max = min(temperatures), max(temperatures) y_min, y_max = 0, 1 padding = 0.1 axes.bar( x=np.array(temperatures) - padding, height=1, width=shape.interval + (padding * shape.interval), color=colours, align='edge') settings = { 'axes': axes, 'bounding_box': (x_min, x_max, y_min, y_max), 'title': 'Blackbody Colours', 'x_label': 'Temperature K', 'y_label': None, } settings.update(kwargs) return render(**settings)
def colour_rendering_index(sd_test, additional_data=False): """ Returns the *Colour Rendering Index* (CRI) :math:`Q_a` of given spectral distribution. Parameters ---------- sd_test : SpectralDistribution Test spectral distribution. additional_data : bool, optional Whether to output additional data. Returns ------- numeric or CRI_Specification *Colour Rendering Index* (CRI). References ---------- :cite:`Ohno2008a` Examples -------- >>> from colour import ILLUMINANTS_SDS >>> sd = ILLUMINANTS_SDS['FL2'] >>> colour_rendering_index(sd) # doctest: +ELLIPSIS 64.1515202... """ cmfs = STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer'].copy( ).trim(ASTME30815_PRACTISE_SHAPE) shape = cmfs.shape sd_test = sd_test.copy().align(shape) tcs_sds = {sd.name: sd.copy().align(shape) for sd in TCS_SDS.values()} with domain_range_scale('1'): XYZ = sd_to_XYZ(sd_test, cmfs) uv = UCS_to_uv(XYZ_to_UCS(XYZ)) CCT, _D_uv = uv_to_CCT_Robertson1968(uv) if CCT < 5000: sd_reference = sd_blackbody(CCT, shape) else: xy = CCT_to_xy_CIE_D(CCT) sd_reference = sd_CIE_illuminant_D_series(xy) sd_reference.align(shape) test_tcs_colorimetry_data = tcs_colorimetry_data( sd_test, sd_reference, tcs_sds, cmfs, chromatic_adaptation=True) reference_tcs_colorimetry_data = tcs_colorimetry_data( sd_reference, sd_reference, tcs_sds, cmfs) Q_as = colour_rendering_indexes(test_tcs_colorimetry_data, reference_tcs_colorimetry_data) Q_a = np.average( [v.Q_a for k, v in Q_as.items() if k in (1, 2, 3, 4, 5, 6, 7, 8)]) if additional_data: return CRI_Specification( sd_test.name, Q_a, Q_as, (test_tcs_colorimetry_data, reference_tcs_colorimetry_data)) else: return Q_a
def plot_blackbody_colours(shape=SpectralShape(150, 12500, 50), cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots blackbody colours. Parameters ---------- shape : SpectralShape, optional Spectral shape to use as plot boundaries. cmfs : unicode, optional Standard observer colour matching functions. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_blackbody_colours(SpectralShape(150, 12500, 50)) ... # doctest: +ELLIPSIS (<Figure size ... with 1 Axes>, \ <matplotlib.axes._subplots.AxesSubplot object at 0x...>) .. image:: ../_static/Plotting_Plot_Blackbody_Colours.png :align: center :alt: plot_blackbody_colours """ _figure, axes = artist(**kwargs) cmfs = first_item(filter_cmfs(cmfs).values()) colours = [] temperatures = [] for temperature in shape: sd = sd_blackbody(temperature, cmfs.shape) with domain_range_scale('1'): XYZ = sd_to_XYZ(sd, cmfs) RGB = normalise_maximum(XYZ_to_plotting_colourspace(XYZ)) colours.append(RGB) temperatures.append(temperature) x_min, x_max = min(temperatures), max(temperatures) y_min, y_max = 0, 1 padding = 0.1 axes.bar(x=np.array(temperatures) - padding, height=1, width=shape.interval + (padding * shape.interval), color=colours, align='edge') settings = { 'axes': axes, 'bounding_box': (x_min, x_max, y_min, y_max), 'title': 'Blackbody Colours', 'x_label': 'Temperature K', 'y_label': None, } settings.update(kwargs) return render(**settings)
def plot_blackbody_colours( shape: SpectralShape = SpectralShape(150, 12500, 50), cmfs: Union[MultiSpectralDistributions, str, Sequence[Union[ MultiSpectralDistributions, str]], ] = "CIE 1931 2 Degree Standard Observer", **kwargs: Any, ) -> Tuple[plt.Figure, plt.Axes]: """ Plot blackbody colours. Parameters ---------- shape Spectral shape to use as plot boundaries. cmfs Standard observer colour matching functions used for computing the blackbody colours. ``cmfs`` can be of any type or form supported by the :func:`colour.plotting.filter_cmfs` definition. Other Parameters ---------------- kwargs {:func:`colour.plotting.artist`, :func:`colour.plotting.render`}, See the documentation of the previously listed definitions. Returns ------- :class:`tuple` Current figure and axes. Examples -------- >>> plot_blackbody_colours(SpectralShape(150, 12500, 50)) ... # doctest: +ELLIPSIS (<Figure size ... with 1 Axes>, <...AxesSubplot...>) .. image:: ../_static/Plotting_Plot_Blackbody_Colours.png :align: center :alt: plot_blackbody_colours """ _figure, axes = artist(**kwargs) cmfs = cast(MultiSpectralDistributions, first_item(filter_cmfs(cmfs).values())) RGB = [] temperatures = [] for temperature in shape: sd = sd_blackbody(temperature, cmfs.shape) with domain_range_scale("1"): XYZ = sd_to_XYZ(sd, cmfs) RGB.append(normalise_maximum(XYZ_to_plotting_colourspace(XYZ))) temperatures.append(temperature) x_min, x_max = min(temperatures), max(temperatures) y_min, y_max = 0, 1 padding = 0.1 axes.bar( x=np.array(temperatures) - padding, height=1, width=shape.interval + (padding * shape.interval), color=RGB, align="edge", zorder=CONSTANTS_COLOUR_STYLE.zorder.background_polygon, ) settings: Dict[str, Any] = { "axes": axes, "bounding_box": (x_min, x_max, y_min, y_max), "title": "Blackbody Colours", "x_label": "Temperature K", "y_label": None, } settings.update(kwargs) return render(**settings)