Exemple #1
0
def colour_rendering_index_bars_plot(spd, **kwargs):
    """
    Plots the *colour rendering index* of given illuminant or light source.

    Parameters
    ----------
    spd : SpectralPowerDistribution
        Illuminant or light source to plot the *colour rendering index*.
    \*\*kwargs : \*\*
        Keywords arguments.

    Returns
    -------
    bool
        Definition success.

    Examples
    --------
    >>> from colour import ILLUMINANTS_RELATIVE_SPDS
    >>> illuminant = ILLUMINANTS_RELATIVE_SPDS.get('F2')
    >>> colour_rendering_index_bars_plot(illuminant)  # doctest: +SKIP
    True
    """

    if colour_quality_bars_plot(
            colour_rendering_index(
                    spd,
                    additional_data=True),
            standalone=False):
        settings = {
            'title': 'Colour Rendering Index - {0}'.format(spd.title)}

        decorate(**settings)
        return display(**settings)
Exemple #2
0
def multi_spd_colour_rendering_index_bars_plot(spds, **kwargs):
    """
    Plots the *colour rendering index* of given illuminants or light sources
    spectral power distributions.

    Parameters
    ----------
    spds : array_like
        Array of illuminants or light sources spectral power distributions to
        plot the *colour rendering index*.
    \**kwargs : dict, optional
        Keywords arguments.

    Returns
    -------
    Figure
        Current figure or None.

    Examples
    --------
    >>> from colour import (
    ...     ILLUMINANTS_RELATIVE_SPDS,
    ...     LIGHT_SOURCES_RELATIVE_SPDS)
    >>> illuminant = ILLUMINANTS_RELATIVE_SPDS.get('F2')
    >>> light_source = LIGHT_SOURCES_RELATIVE_SPDS.get('Kinoton 75P')
    >>> multi_spd_colour_rendering_index_bars_plot(  # doctest: +SKIP
    ...     [illuminant, light_source])
    """

    settings = {}
    settings.update(kwargs)
    settings.update({'standalone': False})

    specifications = [
        colour_rendering_index(spd, additional_data=True) for spd in spds
    ]

    # *colour rendering index* colorimetry data tristimulus values are
    # computed in [0, 100] domain however `colour_quality_bars_plot` expects
    # [0, 1] domain. As we want to keep `colour_quality_bars_plot` definition
    # agnostic from the colour quality data, we update the test spd
    # colorimetry data tristimulus values domain.
    for specification in specifications:
        colorimetry_data = specification.colorimetry_data
        for i, c_d in enumerate(colorimetry_data[0]):
            colorimetry_data[0][i] = TCS_ColorimetryData(
                c_d.name, c_d.XYZ / 100, c_d.uv, c_d.UVW)

    colour_quality_bars_plot(specifications, **settings)

    settings = {
        'title':
        'Colour Rendering Index - {0}'.format(', '.join(
            [spd.title for spd in spds]))
    }
    settings.update(kwargs)

    decorate(**settings)

    return display(**settings)
Exemple #3
0
def multi_spd_colour_rendering_index_bars_plot(spds, **kwargs):
    """
    Plots the *colour rendering index* of given illuminants or light sources
    spectral power distributions.

    Parameters
    ----------
    spds : array_like
        Array of illuminants or light sources spectral power distributions to
        plot the *colour rendering index*.
    \**kwargs : dict, optional
        Keywords arguments.

    Returns
    -------
    bool
        Definition success.

    Examples
    --------
    >>> from colour import (
    ...     ILLUMINANTS_RELATIVE_SPDS,
    ...     LIGHT_SOURCES_RELATIVE_SPDS)
    >>> illuminant = ILLUMINANTS_RELATIVE_SPDS.get('F2')
    >>> light_source = LIGHT_SOURCES_RELATIVE_SPDS.get('Kinoton 75P')
    >>> multi_spd_colour_rendering_index_bars_plot(  # doctest: +SKIP
    ...     [illuminant, light_source])
    True
    """

    settings = {}
    settings.update(kwargs)
    settings.update({'standalone': False})

    specifications = [colour_rendering_index(spd, additional_data=True)
                      for spd in spds]

    # *colour rendering index* colorimetry data tristimulus values are
    # computed in [0, 100] domain however `colour_quality_bars_plot` expects
    # [0, 1] domain. As we want to keep `colour_quality_bars_plot` definition
    # agnostic from the colour quality data, we update the test spd
    # colorimetry data tristimulus values domain.
    for specification in specifications:
        colorimetry_data = specification.colorimetry_data
        for i, c_d in enumerate(colorimetry_data[0]):
            colorimetry_data[0][i] = TCS_ColorimetryData(c_d.name,
                                                         c_d.XYZ / 100,
                                                         c_d.uv,
                                                         c_d.UVW)

    colour_quality_bars_plot(specifications, **settings)

    settings = {'title': 'Colour Rendering Index - {0}'.format(', '.join(
        [spd.title for spd in spds]))}
    settings.update(kwargs)

    decorate(**settings)

    return display(**settings)
Exemple #4
0
    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)
Exemple #5
0
    def test_colour_rendering_index(self):
        """
        Tests :func:`colour.quality.cri.colour_rendering_index` definition.
        """

        self.assertAlmostEqual(
            colour_rendering_index(ILLUMINANTS_SDS['FL2']),
            64.151520202968015,
            places=7)

        self.assertAlmostEqual(
            colour_rendering_index(ILLUMINANTS_SDS['A']),
            99.996732643006169,
            places=7)

        self.assertAlmostEqual(
            colour_rendering_index(SpectralDistribution(SAMPLE_SD_DATA)),
            70.813839034481575,
            places=7)
Exemple #6
0
    def test_colour_rendering_index(self):
        """
        Tests :func:`colour.quality.cri.colour_rendering_index` definition.
        """

        self.assertAlmostEqual(
            colour_rendering_index(ILLUMINANTS_SDS['FL2']),
            64.151520202968015,
            places=7)

        self.assertAlmostEqual(
            colour_rendering_index(ILLUMINANTS_SDS['A']),
            99.996732643006169,
            places=7)

        self.assertAlmostEqual(
            colour_rendering_index(SpectralDistribution(SAMPLE_SD_DATA)),
            70.813839034481575,
            places=7)
Exemple #7
0
    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)
Exemple #8
0
    def test_colour_rendering_index(self):
        """
        Tests :func:`colour.quality.cri.colour_rendering_index` definition.
        """

        self.assertAlmostEqual(colour_rendering_index(
            ILLUMINANTS_RELATIVE_SPDS['F2']),
                               64.151520202968015,
                               places=7)

        self.assertAlmostEqual(colour_rendering_index(
            ILLUMINANTS_RELATIVE_SPDS['A']),
                               99.996732643006169,
                               places=7)

        self.assertAlmostEqual(colour_rendering_index(
            SpectralPowerDistribution(SAMPLE_SPD_DATA)),
                               70.805386570659394,
                               places=7)
Exemple #9
0
    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)
Exemple #10
0
    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)
Exemple #11
0
def plot_multi_sds_colour_rendering_indexes_bars(
    sds: Union[
        Sequence[Union[SpectralDistribution, MultiSpectralDistributions]],
        MultiSpectralDistributions,
    ],
    **kwargs: Any,
) -> Tuple[plt.Figure, plt.Axes]:
    """
    Plot the *Colour Rendering Index* (CRI) of given illuminants or light
    sources spectral distributions.

    Parameters
    ----------
    sds
        Spectral distributions or multi-spectral distributions to
        plot. `sds` can be a single
        :class:`colour.MultiSpectralDistributions` class instance, a list
        of :class:`colour.MultiSpectralDistributions` class instances or a
        list of :class:`colour.SpectralDistribution` class instances.

    Other Parameters
    ----------------
    kwargs
        {:func:`colour.plotting.artist`,
        :func:`colour.plotting.quality.plot_colour_quality_bars`,
        :func:`colour.plotting.render`},
        See the documentation of the previously listed definitions.

    Returns
    -------
    :class:`tuple`
        Current figure and axes.

    Examples
    --------
    >>> from colour import (SDS_ILLUMINANTS,
    ...                     SDS_LIGHT_SOURCES)
    >>> illuminant = SDS_ILLUMINANTS['FL2']
    >>> light_source = SDS_LIGHT_SOURCES['Kinoton 75P']
    >>> plot_multi_sds_colour_rendering_indexes_bars(
    ...     [illuminant, light_source])  # doctest: +ELLIPSIS
    (<Figure size ... with 1 Axes>, <...AxesSubplot...>)

    .. image:: ../_static/Plotting_\
Plot_Multi_SDS_Colour_Rendering_Indexes_Bars.png
        :align: center
        :alt: plot_multi_sds_colour_rendering_indexes_bars
    """

    sds_converted = sds_and_msds_to_sds(sds)

    settings: Dict[str, Any] = dict(kwargs)
    settings.update({"standalone": False})

    specifications = cast(
        List[ColourRendering_Specification_CRI],
        [
            colour_rendering_index(sd, additional_data=True)
            for sd in sds_converted
        ],
    )

    # *colour rendering index* colorimetry data tristimulus values are
    # computed in [0, 100] domain however `plot_colour_quality_bars` expects
    # [0, 1] domain. As we want to keep `plot_colour_quality_bars` definition
    # agnostic from the colour quality data, we update the test sd
    # colorimetry data tristimulus values domain.
    for specification in specifications:
        colorimetry_data = specification.colorimetry_data
        for i in range(len(colorimetry_data[0])):
            colorimetry_data[0][i].XYZ /= 100

    _figure, axes = plot_colour_quality_bars(specifications, **settings)

    title = (
        f"Colour Rendering Index - "
        f"{', '.join([sd.strict_name for sd in sds_converted])}"
    )

    settings = {"axes": axes, "title": title}
    settings.update(kwargs)

    return render(**settings)
Exemple #12
0
def multi_spd_colour_rendering_index_bars_plot(spds, **kwargs):
    """
    Plots the *Colour Rendering Index* (CRI) of given illuminants or light
    sources spectral power distributions.

    Parameters
    ----------
    spds : array_like
        Array of illuminants or light sources spectral power distributions to
        plot the *Colour Rendering Index* (CRI).

    Other Parameters
    ----------------
    \**kwargs : dict, optional
        {:func:`boundaries`, :func:`canvas`, :func:`decorate`,
        :func:`display`},
        Please refer to the documentation of the previously listed definitions.
    labels : bool, optional
        {:func:`colour_quality_bars_plot`},
        Add labels above bars.
    hatching : bool or None, optional
        {:func:`colour_quality_bars_plot`},
        Use hatching for the bars.
    hatching_repeat : int, optional
        {:func:`colour_quality_bars_plot`},
        Hatching pattern repeat.

    Returns
    -------
    Figure
        Current figure or None.

    Examples
    --------
    >>> from colour import (
    ...     ILLUMINANTS_RELATIVE_SPDS,
    ...     LIGHT_SOURCES_RELATIVE_SPDS)
    >>> illuminant = ILLUMINANTS_RELATIVE_SPDS['F2']
    >>> light_source = LIGHT_SOURCES_RELATIVE_SPDS['Kinoton 75P']
    >>> multi_spd_colour_rendering_index_bars_plot(  # doctest: +SKIP
    ...     [illuminant, light_source])
    """

    settings = {}
    settings.update(kwargs)
    settings.update({'standalone': False})

    specifications = [
        colour_rendering_index(spd, additional_data=True) for spd in spds
    ]

    # *colour rendering index* colorimetry data tristimulus values are
    # computed in [0, 100] domain however `colour_quality_bars_plot` expects
    # [0, 1] domain. As we want to keep `colour_quality_bars_plot` definition
    # agnostic from the colour quality data, we update the test spd
    # colorimetry data tristimulus values domain.
    for specification in specifications:
        colorimetry_data = specification.colorimetry_data
        for i, c_d in enumerate(colorimetry_data[0]):
            colorimetry_data[0][i] = TCS_ColorimetryData(
                c_d.name, c_d.XYZ / 100, c_d.uv, c_d.UVW)

    colour_quality_bars_plot(specifications, **settings)

    settings = {
        'title':
        'Colour Rendering Index - {0}'.format(', '.join(
            [spd.title for spd in spds]))
    }
    settings.update(kwargs)

    decorate(**settings)

    return display(**settings)
Exemple #13
0
def plot_multi_sds_colour_rendering_indexes_bars(sds, **kwargs):
    """
    Plots the *Colour Rendering Index* (CRI) of given illuminants or light
    sources spectral distributions.

    Parameters
    ----------
    sds : array_like or MultiSpectralDistributions
        Spectral distributions or multi-spectral distributions to
        plot. `sds` can be a single
        :class:`colour.MultiSpectralDistributions` class instance, a list
        of :class:`colour.MultiSpectralDistributions` class instances or a
        list of :class:`colour.SpectralDistribution` class instances.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        {:func:`colour.plotting.artist`,
        :func:`colour.plotting.quality.plot_colour_quality_bars`,
        :func:`colour.plotting.render`},
        Please refer to the documentation of the previously listed definitions.
    labels : bool, optional
        {:func:`colour.plotting.quality.plot_colour_quality_bars`},
        Add labels above bars.
    hatching : bool or None, optional
        {:func:`colour.plotting.quality.plot_colour_quality_bars`},
        Use hatching for the bars.
    hatching_repeat : int, optional
        {:func:`colour.plotting.quality.plot_colour_quality_bars`},
        Hatching pattern repeat.

    Returns
    -------
    tuple
        Current figure and axes.

    Examples
    --------
    >>> from colour import (ILLUMINANTS_SDS,
    ...                     LIGHT_SOURCES_SDS)
    >>> illuminant = ILLUMINANTS_SDS['FL2']
    >>> light_source = LIGHT_SOURCES_SDS['Kinoton 75P']
    >>> plot_multi_sds_colour_rendering_indexes_bars(
    ...     [illuminant, light_source])  # doctest: +ELLIPSIS
    (<Figure size ... with 1 Axes>, \
<matplotlib.axes._subplots.AxesSubplot object at 0x...>)

    .. image:: ../_static/Plotting_\
Plot_Multi_SDS_Colour_Rendering_Indexes_Bars.png
        :align: center
        :alt: plot_multi_sds_colour_rendering_indexes_bars
    """

    sds = sds_and_multi_sds_to_sds(sds)

    settings = dict(kwargs)
    settings.update({'standalone': False})

    specifications = [
        colour_rendering_index(sd, additional_data=True) for sd in sds
    ]

    # *colour rendering index* colorimetry data tristimulus values are
    # computed in [0, 100] domain however `plot_colour_quality_bars` expects
    # [0, 1] domain. As we want to keep `plot_colour_quality_bars` definition
    # agnostic from the colour quality data, we update the test sd
    # colorimetry data tristimulus values domain.
    for specification in specifications:
        colorimetry_data = specification.colorimetry_data
        for i, c_d in enumerate(colorimetry_data[0]):
            colorimetry_data[0][i] = TCS_ColorimetryData(
                c_d.name, c_d.XYZ / 100, c_d.uv, c_d.UVW)

    _figure, axes = plot_colour_quality_bars(specifications, **settings)

    title = 'Colour Rendering Index - {0}'.format(', '.join(
        [sd.strict_name for sd in sds]))

    settings = {'axes': axes, 'title': title}
    settings.update(kwargs)

    return render(**settings)
Exemple #14
0
def colour_rendering_index_bars_plot(illuminant, **kwargs):
    """
    Plots the *colour rendering index* of given illuminant.

    Parameters
    ----------
    illuminant : SpectralPowerDistribution
        Illuminant to plot the *colour rendering index*.
    \*\*kwargs : \*\*
        Keywords arguments.

    Returns
    -------
    bool
        Definition success.

    Examples
    --------
    >>> from colour import ILLUMINANTS_RELATIVE_SPDS
    >>> illuminant = ILLUMINANTS_RELATIVE_SPDS.get('F2')
    >>> colour_rendering_index_bars_plot(illuminant)  # doctest: +SKIP
    True
    """

    figure, axis = matplotlib.pyplot.subplots()

    cri, colour_rendering_indexes, additional_data = \
        colour_rendering_index(illuminant, additional_data=True)

    colours = ([[1] * 3] + [normalise(XYZ_to_sRGB(x.XYZ / 100))
                            for x in additional_data[0]])
    x, y = tuple(zip(*sorted(colour_rendering_indexes.items(),
                             key=lambda x: x[0])))
    x, y = np.array([0] + list(x)), np.array(
        [cri] + list(y))

    positive = True if np.sign(min(y)) in (0, 1) else False

    width = 0.5
    bars = pylab.bar(x, y, color=colours, width=width)
    y_ticks_steps = 10
    pylab.yticks(range(0 if positive else -100,
                       100 + y_ticks_steps,
                       y_ticks_steps))
    pylab.xticks(x + width / 2,
                 ['Ra'] + ['R{0}'.format(index) for index in x[1:]])

    def label_bars(bars):
        """
        Add labels above given bars.
        """
        for bar in bars:
            y = bar.get_y()
            height = bar.get_height()
            value = height if np.sign(y) in (0, 1) else -height
            axis.text(bar.get_x() + bar.get_width() / 2,
                      0.025 * height + height + y,
                      '{0:.1f}'.format(value),
                      ha='center', va='bottom')

    label_bars(bars)

    settings = {
        'title': 'Colour Rendering Index - {0}'.format(illuminant.name),
        'grid': True,
        'x_tighten': True,
        'y_tighten': True,
        'limits': [-width, 14 + width * 2, -10 if positive else -110,
                   110]}
    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)
    return display(**settings)
Exemple #15
0
def _full_report(spec, source, date, manufacturer, model, notes=None):
    figure = plt.figure(figsize=(8.27, 11.69))

    figure.text(0.5,
                0.97,
                'TM-30-18 Color Rendition Report',
                ha='center',
                size='x-large')

    figure.text(0.250,
                0.935,
                'Source: ',
                ha='right',
                size='large',
                weight='bold')
    figure.text(0.250, 0.935, source, size='large')
    figure.text(0.250,
                0.907,
                'Date: ',
                ha='right',
                size='large',
                weight='bold')
    figure.text(0.250, 0.907, date, size='large')

    figure.text(0.700,
                0.935,
                'Manufacturer: ',
                ha='right',
                size='large',
                weight='bold')
    figure.text(0.700, 0.935, manufacturer, ha='left', size='large')
    figure.text(0.700,
                0.907,
                'Model: ',
                ha='right',
                size='large',
                weight='bold')
    figure.text(0.700, 0.907, model, size='large')

    ax = figure.add_axes((0.057, 0.767, 0.385, 0.112))
    plot_spectra_TM_30_18(ax, spec)

    ax = figure.add_axes((0.036, 0.385, 0.428, 0.333))
    plot_color_vector_graphic(ax, spec)

    ax = figure.add_axes((0.554, 0.736, 0.409, 0.141))
    plot_local_chroma_shifts(ax, spec)

    ax = figure.add_axes((0.554, 0.576, 0.409, 0.141))
    plot_local_hue_shifts(ax, spec)

    ax = figure.add_axes((0.554, 0.401, 0.409, 0.141))
    plot_local_color_fidelities(ax, spec)

    ax = figure.add_axes((0.094, 0.195, 0.870, 0.161))
    plot_colour_fidelity_indexes(ax, spec)

    if notes:
        figure.text(0.139,
                    0.114,
                    'Notes: ',
                    ha='right',
                    size='large',
                    weight='bold')
        figure.text(0.139, 0.114, notes, size='large')

    XYZ = sd_to_XYZ(spec.sd_test)
    xy = XYZ_to_xy(XYZ)
    Luv = XYZ_to_Luv(XYZ, xy)
    up, vp = Luv_to_uv(Luv, xy)

    figure.text(0.712, 0.111, '$x$  {:.4f}'.format(xy[0]), ha='center')
    figure.text(0.712, 0.091, '$y$  {:.4f}'.format(xy[1]), ha='center')
    figure.text(0.712, 0.071, '$u\'$  {:.4f}'.format(up), ha='center')
    figure.text(0.712, 0.051, '$v\'$  {:.4f}'.format(vp), ha='center')

    rect = plt.Rectangle((0.814, 0.035),
                         0.144,
                         0.096,
                         color='black',
                         fill=False)
    figure.add_artist(rect)

    CRI_spec = colour_rendering_index(spec.sd_test, additional_data=True)

    figure.text(0.886, 0.111, 'CIE 13.31-1995', ha='center')
    figure.text(0.886, 0.091, '(CRI)', ha='center')
    figure.text(0.886,
                0.071,
                '$R_a$  {:.0f}'.format(CRI_spec.Q_a),
                ha='center',
                weight='bold')
    figure.text(0.886,
                0.051,
                '$R_9$  {:.0f}'.format(CRI_spec.Q_as[8].Q_a),
                ha='center',
                weight='bold')

    figure.text(0.500,
                0.010,
                'Created with Colour ' + colour.__version__,
                ha='center')
Exemple #16
0
    def test_colour_rendering_index(self):
        """
        Tests :func:`colour.quality.cri.colour_rendering_index` definition.
        """

        self.assertAlmostEqual(colour_rendering_index(SDS_ILLUMINANTS['FL1']),
                               75.852827992149358,
                               places=7)

        self.assertAlmostEqual(colour_rendering_index(SDS_ILLUMINANTS['FL2']),
                               64.233724121664778,
                               places=7)

        self.assertAlmostEqual(colour_rendering_index(SDS_ILLUMINANTS['A']),
                               99.996230290506887,
                               places=7)

        self.assertAlmostEqual(colour_rendering_index(
            SpectralDistribution(DATA_SAMPLE)),
                               70.815265381660197,
                               places=7)

        specification_r = ColourRendering_Specification_CRI(
            name='FL1',
            Q_a=75.852827992149358,
            Q_as={
                1:
                TCS_ColourQualityScaleData(name='TCS01',
                                           Q_a=69.196992839933557),
                2:
                TCS_ColourQualityScaleData(name='TCS02',
                                           Q_a=83.650754065677816),
                3:
                TCS_ColourQualityScaleData(name='TCS03',
                                           Q_a=92.136090764490675),
                4:
                TCS_ColourQualityScaleData(name='TCS04',
                                           Q_a=72.665649420972784),
                5:
                TCS_ColourQualityScaleData(name='TCS05',
                                           Q_a=73.890734513517486),
                6:
                TCS_ColourQualityScaleData(name='TCS06',
                                           Q_a=79.619188860052745),
                7:
                TCS_ColourQualityScaleData(name='TCS07',
                                           Q_a=82.272569853644669),
                8:
                TCS_ColourQualityScaleData(name='TCS08',
                                           Q_a=53.390643618905109),
                9:
                TCS_ColourQualityScaleData(name='TCS09',
                                           Q_a=-47.284477750225903),
                10:
                TCS_ColourQualityScaleData(name='TCS10',
                                           Q_a=61.568336431199967),
                11:
                TCS_ColourQualityScaleData(name='TCS11',
                                           Q_a=67.522241168172485),
                12:
                TCS_ColourQualityScaleData(name='TCS12',
                                           Q_a=74.890093866757994),
                13:
                TCS_ColourQualityScaleData(name='TCS13',
                                           Q_a=72.771930354944615),
                14:
                TCS_ColourQualityScaleData(name='TCS14',
                                           Q_a=94.884867470552663)
            },
            colorimetry_data=([
                TCS_ColorimetryData(
                    name='TCS01',
                    XYZ=np.array([31.19561134, 29.74560797, 23.44190201]),
                    uv=np.array([0.22782766, 0.32585700]),
                    UVW=np.array([25.43090825, 8.72673714, 60.46061819])),
                TCS_ColorimetryData(
                    name='TCS02',
                    XYZ=np.array([26.70829694, 29.25797165, 13.98804447]),
                    uv=np.array([0.21049132, 0.34587843]),
                    UVW=np.array([11.90704877, 24.68727835, 60.03499882])),
                TCS_ColorimetryData(
                    name='TCS03',
                    XYZ=np.array([24.20150315, 31.45341032, 9.19170689]),
                    uv=np.array([0.18489328, 0.36044399]),
                    UVW=np.array([-8.11343024, 37.47469142, 61.91555021])),
                TCS_ColorimetryData(
                    name='TCS04',
                    XYZ=np.array([20.74577359, 29.44046997, 19.40749007]),
                    uv=np.array([0.15940652, 0.33932233]),
                    UVW=np.array([-27.55686536, 19.30727375, 60.19483706])),
                TCS_ColorimetryData(
                    name='TCS05',
                    XYZ=np.array([25.09405566, 30.60912259, 37.93634878]),
                    uv=np.array([0.16784200, 0.30709443]),
                    UVW=np.array([-21.30541564, -6.63859760, 61.20303996])),
                TCS_ColorimetryData(
                    name='TCS06',
                    XYZ=np.array([27.43598853, 28.84467787, 55.15209308]),
                    uv=np.array([0.17543246, 0.27665994]),
                    UVW=np.array([-14.91500194, -30.51166823, 59.67054901])),
                TCS_ColorimetryData(
                    name='TCS07',
                    XYZ=np.array([31.30354023, 28.49931283, 51.55875721]),
                    uv=np.array([0.20410821, 0.27873574]),
                    UVW=np.array([6.88826195, -28.65430811, 59.36332055])),
                TCS_ColorimetryData(
                    name='TCS08',
                    XYZ=np.array([33.81156122, 29.92921717, 44.07459562]),
                    uv=np.array([0.21992203, 0.29200489]),
                    UVW=np.array([19.29699368, -18.57115711, 60.61967045])),
                TCS_ColorimetryData(
                    name='TCS09',
                    XYZ=np.array([14.75210654, 9.07663825, 4.24056478]),
                    uv=np.array([0.36063567, 0.33283649]),
                    UVW=np.array([74.85972274, 8.59043120, 35.14928413])),
                TCS_ColorimetryData(
                    name='TCS10',
                    XYZ=np.array([53.37923227, 60.57123196, 10.90035400]),
                    uv=np.array([0.21466565, 0.36538264]),
                    UVW=np.array([20.48612095, 54.66177264, 81.18130740])),
                TCS_ColorimetryData(
                    name='TCS11',
                    XYZ=np.array([12.25313424, 19.77564573, 14.04738059]),
                    uv=np.array([0.13962494, 0.33801637]),
                    UVW=np.array([-36.00690822, 15.29571595, 50.60573931])),
                TCS_ColorimetryData(
                    name='TCS12',
                    XYZ=np.array([5.77964943, 5.69096075, 24.73530409]),
                    uv=np.array([0.13981616, 0.20650602]),
                    UVW=np.array([-19.30689974, -39.58762581, 27.63428055])),
                TCS_ColorimetryData(
                    name='TCS13',
                    XYZ=np.array([56.62340157, 57.50304691, 39.13768236]),
                    uv=np.array([0.21850039, 0.33284220]),
                    UVW=np.array([23.93135946, 18.85365757, 79.49473722])),
                TCS_ColorimetryData(
                    name='TCS14',
                    XYZ=np.array([9.42270977, 12.06929274, 5.06066928]),
                    uv=np.array([0.18328188, 0.35214117]),
                    UVW=np.array([-6.11563143, 19.91896684, 40.34566797]))
            ], [
                TCS_ColorimetryData(
                    name='TCS01',
                    XYZ=np.array([33.04774537, 29.80902109, 24.23929188]),
                    uv=np.array([0.23908620, 0.32348313]),
                    UVW=np.array([32.11891091, 8.39794012, 60.51562388])),
                TCS_ColorimetryData(
                    name='TCS02',
                    XYZ=np.array([27.53677515, 28.90913487, 14.75211494]),
                    uv=np.array([0.21792745, 0.34318256]),
                    UVW=np.array([15.27177183, 23.58438306, 59.72761646])),
                TCS_ColorimetryData(
                    name='TCS03',
                    XYZ=np.array([23.95706051, 30.44569936, 9.79977770]),
                    uv=np.array([0.18788308, 0.35815528]),
                    UVW=np.array([-8.23665275, 35.99767796, 61.06361523])),
                TCS_ColorimetryData(
                    name='TCS04',
                    XYZ=np.array([20.43647757, 29.46748627, 21.03631859]),
                    uv=np.array([0.15554126, 0.33641389]),
                    UVW=np.array([-33.44111710, 18.47940853, 60.21844268])),
                TCS_ColorimetryData(
                    name='TCS05',
                    XYZ=np.array([24.95511680, 30.81953457, 39.91407614]),
                    uv=np.array([0.16445149, 0.30464603]),
                    UVW=np.array([-26.97713986, -6.51317420, 61.38182431])),
                TCS_ColorimetryData(
                    name='TCS06',
                    XYZ=np.array([28.14601546, 29.75632189, 57.16886797]),
                    uv=np.array([0.17427942, 0.27637560]),
                    UVW=np.array([-18.85053083, -28.64005452, 60.46991712])),
                TCS_ColorimetryData(
                    name='TCS07',
                    XYZ=np.array([33.29720901, 29.36938555, 52.53803430]),
                    uv=np.array([0.21092469, 0.27906521]),
                    UVW=np.array([9.90110830, -26.37778265, 60.13265766])),
                TCS_ColorimetryData(
                    name='TCS08',
                    XYZ=np.array([37.64974363, 31.35401774, 44.84930911]),
                    uv=np.array([0.23439240, 0.29279655]),
                    UVW=np.array([29.04479043, -16.08583648, 61.83233828])),
                TCS_ColorimetryData(
                    name='TCS09',
                    XYZ=np.array([20.69443384, 11.28822434, 4.28723010]),
                    uv=np.array([0.40801431, 0.33384028]),
                    UVW=np.array([106.56664825, 10.68535426, 39.08093160])),
                TCS_ColorimetryData(
                    name='TCS10',
                    XYZ=np.array([55.04099876, 59.04719161, 11.86354410]),
                    uv=np.array([0.22549942, 0.36286881]),
                    UVW=np.array([28.45432459, 52.29127793, 80.35085218])),
                TCS_ColorimetryData(
                    name='TCS11',
                    XYZ=np.array([12.13069359, 20.35272336, 15.17132466]),
                    uv=np.array([0.13369530, 0.33646842]),
                    UVW=np.array([-43.02145539, 15.76573781, 51.25705062])),
                TCS_ColorimetryData(
                    name='TCS12',
                    XYZ=np.array([6.18799870, 6.41132549, 27.28158667]),
                    uv=np.array([0.13437372, 0.20883497]),
                    UVW=np.array([-24.45285903, -39.79705961, 29.44325151])),
                TCS_ColorimetryData(
                    name='TCS13',
                    XYZ=np.array([58.97935503, 57.14777525, 40.83450223]),
                    uv=np.array([0.22712769, 0.33011150]),
                    UVW=np.array([29.75912462, 17.83690656, 79.29560174])),
                TCS_ColorimetryData(
                    name='TCS14',
                    XYZ=np.array([9.34469915, 11.70922060, 5.33442353]),
                    uv=np.array([0.18597686, 0.34955284]),
                    UVW=np.array([-6.34991066, 18.99712303, 39.76962229]))
            ]))

        specification_t = colour_rendering_index(SDS_ILLUMINANTS['FL1'],
                                                 additional_data=True)

        np.testing.assert_almost_equal(
            [
                data.Q_a
                for _index, data in sorted(specification_r.Q_as.items())
            ],
            [
                data.Q_a
                for _index, data in sorted(specification_t.Q_as.items())
            ],
            decimal=7,
        )
Exemple #17
0
def colour_rendering_index_bars_plot(illuminant, **kwargs):
    """
    Plots the *colour rendering index* of given illuminant.

    Parameters
    ----------
    illuminant : SpectralPowerDistribution
        Illuminant to plot the *colour rendering index*.
    \*\*kwargs : \*\*
        Keywords arguments.

    Returns
    -------
    bool
        Definition success.

    Examples
    --------
    >>> from colour import ILLUMINANTS_RELATIVE_SPDS
    >>> illuminant = ILLUMINANTS_RELATIVE_SPDS.get('F2')
    >>> colour_rendering_index_bars_plot(illuminant)  # doctest: +SKIP
    True
    """

    figure, axis = matplotlib.pyplot.subplots()

    cri, colour_rendering_indexes, additional_data = \
        colour_rendering_index(illuminant, additional_data=True)

    colours = (
        [[1] * 3] +
        [normalise(XYZ_to_sRGB(x.XYZ / 100)) for x in additional_data[0]])
    x, y = tuple(
        zip(*sorted(colour_rendering_indexes.items(), key=lambda x: x[0])))
    x, y = np.array([0] + list(x)), np.array([cri] + list(y))

    positive = True if np.sign(min(y)) in (0, 1) else False

    width = 0.5
    bars = pylab.bar(x, y, color=colours, width=width)
    y_ticks_steps = 10
    pylab.yticks(
        range(0 if positive else -100, 100 + y_ticks_steps, y_ticks_steps))
    pylab.xticks(x + width / 2,
                 ['Ra'] + ['R{0}'.format(index) for index in x[1:]])

    def label_bars(bars):
        """
        Add labels above given bars.
        """
        for bar in bars:
            y = bar.get_y()
            height = bar.get_height()
            value = height if np.sign(y) in (0, 1) else -height
            axis.text(bar.get_x() + bar.get_width() / 2,
                      0.025 * height + height + y,
                      '{0:.1f}'.format(value),
                      ha='center',
                      va='bottom')

    label_bars(bars)

    settings = {
        'title': 'Colour Rendering Index - {0}'.format(illuminant.name),
        'grid': True,
        'x_tighten': True,
        'y_tighten': True,
        'limits': [-width, 14 + width * 2, -10 if positive else -110, 110]
    }
    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)
    return display(**settings)
Exemple #18
0
def plot_multi_sds_colour_rendering_indexes_bars(sds, **kwargs):
    """
    Plots the *Colour Rendering Index* (CRI) of given illuminants or light
    sources spectral distributions.

    Parameters
    ----------
    sds : array_like
        Array of illuminants or light sources spectral distributions to
        plot the *Colour Rendering Index* (CRI).

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        {:func:`colour.plotting.artist`,
        :func:`colour.plotting.quality.plot_colour_quality_bars`,
        :func:`colour.plotting.render`},
        Please refer to the documentation of the previously listed definitions.
    labels : bool, optional
        {:func:`colour.plotting.quality.plot_colour_quality_bars`},
        Add labels above bars.
    hatching : bool or None, optional
        {:func:`colour.plotting.quality.plot_colour_quality_bars`},
        Use hatching for the bars.
    hatching_repeat : int, optional
        {:func:`colour.plotting.quality.plot_colour_quality_bars`},
        Hatching pattern repeat.

    Returns
    -------
    tuple
        Current figure and axes.

    Examples
    --------
    >>> from colour import (ILLUMINANTS_SDS,
    ...                     LIGHT_SOURCES_SDS)
    >>> illuminant = ILLUMINANTS_SDS['FL2']
    >>> light_source = LIGHT_SOURCES_SDS['Kinoton 75P']
    >>> plot_multi_sds_colour_rendering_indexes_bars(
    ...     [illuminant, light_source])  # doctest: +SKIP

    .. image:: ../_static/Plotting_\
Plot_Multi_SDs_Colour_Rendering_Indexes_Bars.png
        :align: center
        :alt: plot_multi_sds_colour_rendering_indexes_bars
    """

    settings = dict(kwargs)
    settings.update({'standalone': False})

    specifications = [
        colour_rendering_index(sd, additional_data=True) for sd in sds
    ]

    # *colour rendering index* colorimetry data tristimulus values are
    # computed in [0, 100] domain however `plot_colour_quality_bars` expects
    # [0, 1] domain. As we want to keep `plot_colour_quality_bars` definition
    # agnostic from the colour quality data, we update the test sd
    # colorimetry data tristimulus values domain.
    for specification in specifications:
        colorimetry_data = specification.colorimetry_data
        for i, c_d in enumerate(colorimetry_data[0]):
            colorimetry_data[0][i] = TCS_ColorimetryData(
                c_d.name, c_d.XYZ / 100, c_d.uv, c_d.UVW)

    _figure, axes = plot_colour_quality_bars(specifications, **settings)

    title = 'Colour Rendering Index - {0}'.format(', '.join(
        [sd.strict_name for sd in sds]))

    settings = {'axes': axes, 'title': title}
    settings.update(kwargs)

    return render(**settings)
Exemple #19
0
def plot_single_sd_colour_rendition_report_full(
        sd,
        source=None,
        date=None,
        manufacturer=None,
        model=None,
        notes=None,
        report_size=CONSTANT_REPORT_SIZE_FULL,
        report_row_height_ratios=CONSTANT_REPORT_ROW_HEIGHT_RATIOS_FULL,
        report_box_padding=None,
        **kwargs):
    """
    Generates the full *ANSI/IES TM-30-18 Colour Rendition Report* for given
    spectral distribution.

    Parameters
    ----------
    sd : SpectralDistribution or SpectralDistribution_IESTM2714
        Spectral distribution of the emission source to generate the report
        for.
    source : unicode, optional
        Emission source name, defaults to
        `colour.SpectralDistribution_IESTM2714.header.description` or
        `colour.SpectralDistribution_IESTM2714.name` properties value.
    date : unicode, optional
        Emission source measurement date, defaults to
        `colour.SpectralDistribution_IESTM2714.header.report_date` property
        value.
    manufacturer : unicode, optional
        Emission source manufacturer, defaults to
        `colour.SpectralDistribution_IESTM2714.header.manufacturer` property
        value.
    model : unicode, optional
        Emission source model, defaults to
        `colour.SpectralDistribution_IESTM2714.header.catalog_number` property
        value.
    notes : unicode, optional
        Notes pertaining to the emission source, defaults to
        `colour.SpectralDistribution_IESTM2714.header.comments` property
        value.
    report_size : array_like, optional
        Report size, default to A4 paper size in inches.
    report_row_height_ratios : array_like, optional
        Report size row height ratios.
    report_box_padding : array_like, optional
        Report box padding, tries to define the padding around the figure and
        in-between the axes.

    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
    --------
    >>> from colour import SDS_ILLUMINANTS
    >>> sd = SDS_ILLUMINANTS['FL2']
    >>> plot_single_sd_colour_rendition_report_full(sd)
    ... # doctest: +ELLIPSIS
    (<Figure size ... with ... Axes>, <...AxesSubplot...>)

    .. image:: ../_static/Plotting_\
Plot_Single_SD_Colour_Rendition_Report_Full.png
        :align: center
        :alt: plot_single_sd_colour_rendition_report_full
    """

    if six.PY2:
        runtime_warning(
            'The "ANSI/IES TM-30-18 Colour Rendition Report" uses advanced '
            '"Matplotlib" layout capabilities only available for Python 3!')

        return render()

    if report_box_padding is None:
        report_box_padding = CONSTANT_REPORT_PADDING_FULL

    specification = colour_fidelity_index_ANSIIESTM3018(sd, True)

    sd = (SpectralDistribution_IESTM2714(data=sd, name=sd.name)
          if not isinstance(sd, SpectralDistribution_IESTM2714) else sd)

    source = sd.header.description if source is None else source
    source = sd.name if source is None else source
    date = sd.header.report_date if date is None else date
    date = _NOT_APPLICABLE_VALUE if date is None else date
    manufacturer = (sd.header.manufacturer
                    if manufacturer is None else manufacturer)
    manufacturer = (_NOT_APPLICABLE_VALUE
                    if manufacturer is None else manufacturer)
    model = sd.header.catalog_number if model is None else model
    model = _NOT_APPLICABLE_VALUE if model is None else model
    notes = sd.header.comments if notes is None else notes
    notes = _NOT_APPLICABLE_VALUE if notes is None else notes

    figure = plt.figure(figsize=report_size, constrained_layout=True)

    settings = kwargs.copy()
    settings['standalone'] = False
    settings['tight_layout'] = False

    gridspec_report = figure.add_gridspec(
        5, 1, height_ratios=report_row_height_ratios)

    # Title Row
    gridspec_title = gridspec_report[0].subgridspec(1, 1)
    axes_title = figure.add_subplot(gridspec_title[0])
    _plot_report_header(axes_title)

    # Description Rows & Columns
    gridspec_description = gridspec_report[1].subgridspec(1, 2)
    # Source & Date Column
    axes_source_date = figure.add_subplot(gridspec_description[0])
    axes_source_date.set_axis_off()
    axes_source_date.text(0.25,
                          2 / 3,
                          'Source: ',
                          ha='right',
                          va='center',
                          size='medium',
                          weight='bold')
    axes_source_date.text(0.25, 2 / 3, source, va='center', size='medium')

    axes_source_date.text(0.25,
                          1 / 3,
                          'Date: ',
                          ha='right',
                          va='center',
                          size='medium',
                          weight='bold')
    axes_source_date.text(0.25, 1 / 3, date, va='center', size='medium')

    # Manufacturer & Model Column
    axes_manufacturer_model = figure.add_subplot(gridspec_description[1])
    axes_manufacturer_model.set_axis_off()
    axes_manufacturer_model.text(0.25,
                                 2 / 3,
                                 'Manufacturer: ',
                                 ha='right',
                                 va='center',
                                 size='medium',
                                 weight='bold')
    axes_manufacturer_model.text(0.25,
                                 2 / 3,
                                 manufacturer,
                                 va='center',
                                 size='medium')

    axes_manufacturer_model.text(0.25,
                                 1 / 3,
                                 'Model: ',
                                 ha='right',
                                 va='center',
                                 size='medium',
                                 weight='bold')
    axes_manufacturer_model.text(0.25,
                                 1 / 3,
                                 model,
                                 va='center',
                                 size='medium')

    # Main Figures Rows & Columns
    gridspec_figures = gridspec_report[2].subgridspec(
        4, 2, height_ratios=[1, 1, 1, 1.5])
    axes_spectra = figure.add_subplot(gridspec_figures[0, 0])
    plot_spectra_ANSIIESTM3018(specification, axes=axes_spectra, **settings)

    axes_vector_graphics = figure.add_subplot(gridspec_figures[1:3, 0])
    plot_colour_vector_graphic(specification,
                               axes=axes_vector_graphics,
                               **settings)

    axes_chroma_shifts = figure.add_subplot(gridspec_figures[0, 1])
    plot_local_chroma_shifts(specification,
                             axes=axes_chroma_shifts,
                             **settings)

    axes_hue_shifts = figure.add_subplot(gridspec_figures[1, 1])
    plot_local_hue_shifts(specification, axes=axes_hue_shifts, **settings)

    axes_colour_fidelities = figure.add_subplot(gridspec_figures[2, 1])
    plot_local_colour_fidelities(specification,
                                 axes=axes_colour_fidelities,
                                 x_ticker=True,
                                 **settings)

    # Colour Fidelity Indexes Row
    axes_colour_fidelity_indexes = figure.add_subplot(gridspec_figures[3, :])
    plot_colour_fidelity_indexes(specification,
                                 axes=axes_colour_fidelity_indexes,
                                 **settings)

    # Notes & Chromaticities / CRI Row and Columns
    gridspec_notes_chromaticities_CRI = gridspec_report[3].subgridspec(1, 2)
    axes_notes = figure.add_subplot(gridspec_notes_chromaticities_CRI[0])
    axes_notes.set_axis_off()
    axes_notes.text(0.25,
                    1,
                    'Notes: ',
                    ha='right',
                    va='center',
                    size='medium',
                    weight='bold')
    axes_notes.text(0.25, 1, notes, va='center', size='medium')
    gridspec_chromaticities_CRI = gridspec_notes_chromaticities_CRI[
        1].subgridspec(1, 2)

    XYZ = sd_to_XYZ(specification.sd_test)
    xy = XYZ_to_xy(XYZ)
    Luv = XYZ_to_Luv(XYZ, xy)
    uv_p = Luv_to_uv(Luv, xy)

    gridspec_chromaticities = gridspec_chromaticities_CRI[0].subgridspec(1, 1)
    axes_chromaticities = figure.add_subplot(gridspec_chromaticities[0])
    axes_chromaticities.set_axis_off()
    axes_chromaticities.text(0.5,
                             4 / 5,
                             '$x$ {:.4f}'.format(xy[0]),
                             ha='center',
                             va='center',
                             size='medium',
                             weight='bold')

    axes_chromaticities.text(0.5,
                             3 / 5,
                             '$y$ {:.4f}'.format(xy[1]),
                             ha='center',
                             va='center',
                             size='medium',
                             weight='bold')

    axes_chromaticities.text(0.5,
                             2 / 5,
                             '$u\'$ {:.4f}'.format(uv_p[0]),
                             ha='center',
                             va='center',
                             size='medium',
                             weight='bold')

    axes_chromaticities.text(0.5,
                             1 / 5,
                             '$v\'$ {:.4f}'.format(uv_p[1]),
                             ha='center',
                             va='center',
                             size='medium',
                             weight='bold')

    gridspec_CRI = gridspec_chromaticities_CRI[1].subgridspec(1, 1)

    CRI_spec = colour_rendering_index(specification.sd_test,
                                      additional_data=True)

    axes_CRI = figure.add_subplot(gridspec_CRI[0])
    axes_CRI.set_xticks([])
    axes_CRI.set_yticks([])
    axes_CRI.text(0.5,
                  4 / 5,
                  'CIE 13.31-1995',
                  ha='center',
                  va='center',
                  size='medium',
                  weight='bold')

    axes_CRI.text(0.5,
                  3 / 5,
                  '(CRI)',
                  ha='center',
                  va='center',
                  size='medium',
                  weight='bold')

    axes_CRI.text(0.5,
                  2 / 5,
                  '$R_a$ {:.0f}'.format(CRI_spec.Q_a),
                  ha='center',
                  va='center',
                  size='medium',
                  weight='bold')

    axes_CRI.text(0.5,
                  1 / 5,
                  '$R_9$ {:.0f}'.format(CRI_spec.Q_as[8].Q_a),
                  ha='center',
                  va='center',
                  size='medium',
                  weight='bold')

    gridspec_footer = gridspec_report[4].subgridspec(1, 1)
    axes_footer = figure.add_subplot(gridspec_footer[0])
    _plot_report_footer(axes_footer)

    figure.set_constrained_layout_pads(**report_box_padding)

    settings = kwargs.copy()
    settings['tight_layout'] = False

    return render(**settings)
Exemple #20
0
def plot_single_sd_colour_rendition_report_full(
    sd: SpectralDistribution,
    source: Optional[str] = None,
    date: Optional[str] = None,
    manufacturer: Optional[str] = None,
    model: Optional[str] = None,
    notes: Optional[str] = None,
    report_size: Tuple = CONSTANT_REPORT_SIZE_FULL,
    report_row_height_ratios: Tuple = CONSTANT_REPORT_ROW_HEIGHT_RATIOS_FULL,
    report_box_padding: Optional[Dict] = None,
    **kwargs: Any,
) -> Tuple[plt.Figure, plt.Axes]:  # noqa: D405,D407,D410,D411
    """
    Generate the full *ANSI/IES TM-30-18 Colour Rendition Report* for given
    spectral distribution.

    Parameters
    ----------
    sd
        Spectral distribution of the emission source to generate the report
        for.
    source
        Emission source name, defaults to
        `colour.SpectralDistribution_IESTM2714.header.description` or
        `colour.SpectralDistribution_IESTM2714.name` properties value.
    date
        Emission source measurement date, defaults to
        `colour.SpectralDistribution_IESTM2714.header.report_date` property
        value.
    manufacturer
        Emission source manufacturer, defaults to
        `colour.SpectralDistribution_IESTM2714.header.manufacturer` property
        value.
    model
        Emission source model, defaults to
        `colour.SpectralDistribution_IESTM2714.header.catalog_number` property
        value.
    notes
        Notes pertaining to the emission source, defaults to
        `colour.SpectralDistribution_IESTM2714.header.comments` property
        value.
    report_size
        Report size, default to A4 paper size in inches.
    report_row_height_ratios
        Report size row height ratios.
    report_box_padding
        Report box padding, tries to define the padding around the figure and
        in-between the axes.

    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
    --------
    >>> from colour import SDS_ILLUMINANTS
    >>> sd = SDS_ILLUMINANTS['FL2']
    >>> plot_single_sd_colour_rendition_report_full(sd)
    ... # doctest: +ELLIPSIS
    (<Figure size ... with ... Axes>, <...AxesSubplot...>)

    .. image:: ../_static/Plotting_\
Plot_Single_SD_Colour_Rendition_Report_Full.png
        :align: center
        :alt: plot_single_sd_colour_rendition_report_full
    """

    report_box_padding = optional(report_box_padding,
                                  CONSTANT_REPORT_PADDING_FULL)

    specification: ColourQuality_Specification_ANSIIESTM3018 = cast(
        ColourQuality_Specification_ANSIIESTM3018,
        colour_fidelity_index_ANSIIESTM3018(sd, True),
    )

    sd = (SpectralDistribution_IESTM2714(data=sd, name=sd.name)
          if not isinstance(sd, SpectralDistribution_IESTM2714) else sd)

    NA = _VALUE_NOT_APPLICABLE

    source = optional(optional(source, sd.header.description), sd.name)
    date = optional(optional(date, sd.header.report_date), NA)
    manufacturer = optional(optional(manufacturer, sd.header.manufacturer), NA)
    model = optional(optional(model, sd.header.catalog_number), NA)
    notes = optional(optional(notes, sd.header.comments), NA)

    figure = plt.figure(figsize=report_size, constrained_layout=True)

    settings: Dict[str, Any] = dict(kwargs)
    settings["standalone"] = False
    settings["tight_layout"] = False

    gridspec_report = figure.add_gridspec(
        5, 1, height_ratios=report_row_height_ratios)

    # Title Row
    gridspec_title = gridspec_report[0].subgridspec(1, 1)
    axes_title = figure.add_subplot(gridspec_title[0])
    _plot_report_header(axes_title)

    # Description Rows & Columns
    gridspec_description = gridspec_report[1].subgridspec(1, 2)
    # Source & Date Column
    axes_source_date = figure.add_subplot(gridspec_description[0])
    axes_source_date.set_axis_off()
    axes_source_date.text(
        0.25,
        2 / 3,
        "Source: ",
        ha="right",
        va="center",
        size="medium",
        weight="bold",
    )
    axes_source_date.text(0.25, 2 / 3, source, va="center", size="medium")

    axes_source_date.text(
        0.25,
        1 / 3,
        "Date: ",
        ha="right",
        va="center",
        size="medium",
        weight="bold",
    )
    axes_source_date.text(0.25, 1 / 3, date, va="center", size="medium")

    # Manufacturer & Model Column
    axes_manufacturer_model = figure.add_subplot(gridspec_description[1])
    axes_manufacturer_model.set_axis_off()
    axes_manufacturer_model.text(
        0.25,
        2 / 3,
        "Manufacturer: ",
        ha="right",
        va="center",
        size="medium",
        weight="bold",
    )
    axes_manufacturer_model.text(0.25,
                                 2 / 3,
                                 manufacturer,
                                 va="center",
                                 size="medium")

    axes_manufacturer_model.text(
        0.25,
        1 / 3,
        "Model: ",
        ha="right",
        va="center",
        size="medium",
        weight="bold",
    )
    axes_manufacturer_model.text(0.25,
                                 1 / 3,
                                 model,
                                 va="center",
                                 size="medium")

    # Main Figures Rows & Columns
    gridspec_figures = gridspec_report[2].subgridspec(
        4, 2, height_ratios=[1, 1, 1, 1.5])
    axes_spectra = figure.add_subplot(gridspec_figures[0, 0])
    plot_spectra_ANSIIESTM3018(specification, axes=axes_spectra, **settings)

    axes_vector_graphics = figure.add_subplot(gridspec_figures[1:3, 0])
    plot_colour_vector_graphic(specification,
                               axes=axes_vector_graphics,
                               **settings)

    axes_chroma_shifts = figure.add_subplot(gridspec_figures[0, 1])
    plot_local_chroma_shifts(specification,
                             axes=axes_chroma_shifts,
                             **settings)

    axes_hue_shifts = figure.add_subplot(gridspec_figures[1, 1])
    plot_local_hue_shifts(specification, axes=axes_hue_shifts, **settings)

    axes_colour_fidelities = figure.add_subplot(gridspec_figures[2, 1])
    plot_local_colour_fidelities(specification,
                                 axes=axes_colour_fidelities,
                                 x_ticker=True,
                                 **settings)

    # Colour Fidelity Indexes Row
    axes_colour_fidelity_indexes = figure.add_subplot(gridspec_figures[3, :])
    plot_colour_fidelity_indexes(specification,
                                 axes=axes_colour_fidelity_indexes,
                                 **settings)

    # Notes & Chromaticities / CRI Row and Columns
    gridspec_notes_chromaticities_CRI = gridspec_report[3].subgridspec(1, 2)
    axes_notes = figure.add_subplot(gridspec_notes_chromaticities_CRI[0])
    axes_notes.set_axis_off()
    axes_notes.text(
        0.25,
        1,
        "Notes: ",
        ha="right",
        va="center",
        size="medium",
        weight="bold",
    )
    axes_notes.text(0.25, 1, notes, va="center", size="medium")
    gridspec_chromaticities_CRI = gridspec_notes_chromaticities_CRI[
        1].subgridspec(1, 2)

    XYZ = sd_to_XYZ(specification.sd_test)
    xy = XYZ_to_xy(XYZ)
    Luv = XYZ_to_Luv(XYZ, xy)
    uv_p = Luv_to_uv(Luv, xy)

    gridspec_chromaticities = gridspec_chromaticities_CRI[0].subgridspec(1, 1)
    axes_chromaticities = figure.add_subplot(gridspec_chromaticities[0])
    axes_chromaticities.set_axis_off()
    axes_chromaticities.text(
        0.5,
        4 / 5,
        f"$x$ {xy[0]:.4f}",
        ha="center",
        va="center",
        size="medium",
        weight="bold",
    )

    axes_chromaticities.text(
        0.5,
        3 / 5,
        f"$y$ {xy[1]:.4f}",
        ha="center",
        va="center",
        size="medium",
        weight="bold",
    )

    axes_chromaticities.text(
        0.5,
        2 / 5,
        f"$u'$ {uv_p[0]:.4f}",
        ha="center",
        va="center",
        size="medium",
        weight="bold",
    )

    axes_chromaticities.text(
        0.5,
        1 / 5,
        f"$v'$ {uv_p[1]:.4f}",
        ha="center",
        va="center",
        size="medium",
        weight="bold",
    )

    gridspec_CRI = gridspec_chromaticities_CRI[1].subgridspec(1, 1)

    CRI_spec: ColourRendering_Specification_CRI = cast(
        ColourRendering_Specification_CRI,
        colour_rendering_index(specification.sd_test, additional_data=True),
    )

    axes_CRI = figure.add_subplot(gridspec_CRI[0])
    axes_CRI.set_xticks([])
    axes_CRI.set_yticks([])
    axes_CRI.text(
        0.5,
        4 / 5,
        "CIE 13.31-1995",
        ha="center",
        va="center",
        size="medium",
        weight="bold",
    )

    axes_CRI.text(
        0.5,
        3 / 5,
        "(CRI)",
        ha="center",
        va="center",
        size="medium",
        weight="bold",
    )

    axes_CRI.text(
        0.5,
        2 / 5,
        f"$R_a$ {float(CRI_spec.Q_a):.0f}",
        ha="center",
        va="center",
        size="medium",
        weight="bold",
    )

    axes_CRI.text(
        0.5,
        1 / 5,
        f"$R_9$ {float(CRI_spec.Q_as[8].Q_a):.0f}",
        ha="center",
        va="center",
        size="medium",
        weight="bold",
    )

    gridspec_footer = gridspec_report[4].subgridspec(1, 1)
    axes_footer = figure.add_subplot(gridspec_footer[0])
    _plot_report_footer(axes_footer)

    figure.set_constrained_layout_pads(**report_box_padding)

    settings = dict(kwargs)
    settings["tight_layout"] = False

    return render(**settings)
Exemple #21
0
    def test_colour_rendering_index(self):
        """
        Tests :func:`colour.quality.cri.colour_rendering_index` definition.
        """

        self.assertAlmostEqual(
            colour_rendering_index(ILLUMINANTS_SDS['FL1']),
            75.821550491976069,
            places=7)

        self.assertAlmostEqual(
            colour_rendering_index(ILLUMINANTS_SDS['FL2']),
            64.151520202968015,
            places=7)

        self.assertAlmostEqual(
            colour_rendering_index(ILLUMINANTS_SDS['A']),
            99.996732643006169,
            places=7)

        self.assertAlmostEqual(
            colour_rendering_index(SpectralDistribution(SAMPLE_SD_DATA)),
            70.813839034481575,
            places=7)

        specification_r = CRI_Specification(
            name='FL1',
            Q_a=75.821550491976069,
            Q_as={
                1:
                    TCS_ColourQualityScaleData(
                        name='TCS01', Q_a=69.146993939830651),
                2:
                    TCS_ColourQualityScaleData(
                        name='TCS02', Q_a=83.621259237346464),
                3:
                    TCS_ColourQualityScaleData(
                        name='TCS03', Q_a=92.103176674726171),
                4:
                    TCS_ColourQualityScaleData(
                        name='TCS04', Q_a=72.659091884741599),
                5:
                    TCS_ColourQualityScaleData(
                        name='TCS05', Q_a=73.875477056438399),
                6:
                    TCS_ColourQualityScaleData(
                        name='TCS06', Q_a=79.561558275578435),
                7:
                    TCS_ColourQualityScaleData(
                        name='TCS07', Q_a=82.238690395582836),
                8:
                    TCS_ColourQualityScaleData(
                        name='TCS08', Q_a=53.366156471564040),
                9:
                    TCS_ColourQualityScaleData(
                        name='TCS09', Q_a=-47.429377845680563),
                10:
                    TCS_ColourQualityScaleData(
                        name='TCS10', Q_a=61.459446471229136),
                11:
                    TCS_ColourQualityScaleData(
                        name='TCS11', Q_a=67.488681008259860),
                12:
                    TCS_ColourQualityScaleData(
                        name='TCS12', Q_a=74.912512331077920),
                13:
                    TCS_ColourQualityScaleData(
                        name='TCS13', Q_a=72.752285379884341),
                14:
                    TCS_ColourQualityScaleData(
                        name='TCS14', Q_a=94.874668874605561)
            },
            colorimetry_data=([
                TCS_ColorimetryData(
                    name='TCS01',
                    XYZ=np.array([31.20331782, 29.74794094, 23.46699878]),
                    uv=np.array([0.22783485, 0.32581236]),
                    UVW=np.array([25.41292946, 8.7380799, 60.46264324])),
                TCS_ColorimetryData(
                    name='TCS02',
                    XYZ=np.array([26.7148606, 29.25905082, 14.00052658]),
                    uv=np.array([0.21051808, 0.34585016]),
                    UVW=np.array([11.89933381, 24.70828029, 60.03594595])),
                TCS_ColorimetryData(
                    name='TCS03',
                    XYZ=np.array([24.20882878, 31.45657446, 9.19966949]),
                    uv=np.array([0.18492146, 0.36042609]),
                    UVW=np.array([-8.1256375, 37.50367669, 61.91819636])),
                TCS_ColorimetryData(
                    name='TCS04',
                    XYZ=np.array([20.75294445, 29.43766611, 19.42067879]),
                    uv=np.array([0.15946018, 0.33928696]),
                    UVW=np.array([-27.55034027, 19.3247759, 60.19238635])),
                TCS_ColorimetryData(
                    name='TCS05',
                    XYZ=np.array([25.10593837, 30.60666903, 37.97182815]),
                    uv=np.array([0.1678986, 0.30702797]),
                    UVW=np.array([-21.29395798, -6.63937802, 61.20095038])),
                TCS_ColorimetryData(
                    name='TCS06',
                    XYZ=np.array([27.45144596, 28.84090621, 55.21254008]),
                    uv=np.array([0.17549196, 0.27656177]),
                    UVW=np.array([-14.89855536, -30.53194048, 59.66720711])),
                TCS_ColorimetryData(
                    name='TCS07',
                    XYZ=np.array([31.31828342, 28.49717267, 51.6262295]),
                    uv=np.array([0.20414276, 0.27863076]),
                    UVW=np.array([6.89004159, -28.68174855, 59.36140901])),
                TCS_ColorimetryData(
                    name='TCS08',
                    XYZ=np.array([33.82293106, 29.92724727, 44.13391542]),
                    uv=np.array([0.21993884, 0.29190983]),
                    UVW=np.array([19.28664162, -18.59403459, 60.61796747])),
                TCS_ColorimetryData(
                    name='TCS09',
                    XYZ=np.array([14.74628552, 9.07383027, 4.24660598]),
                    uv=np.array([0.36055908, 0.33279417]),
                    UVW=np.array([74.80963996, 8.5929104, 35.14390587])),
                TCS_ColorimetryData(
                    name='TCS10',
                    XYZ=np.array([53.38914901, 60.57766887, 10.90608553]),
                    uv=np.array([0.21467884, 0.36537604]),
                    UVW=np.array([20.46081762, 54.70909846, 81.18478519])),
                TCS_ColorimetryData(
                    name='TCS11',
                    XYZ=np.array([12.25740399, 19.77026703, 14.05795099]),
                    uv=np.array([0.13969138, 0.33796747]),
                    UVW=np.array([-35.99235266, 15.30093833, 50.59960948])),
                TCS_ColorimetryData(
                    name='TCS12',
                    XYZ=np.array([5.7789513, 5.68760485, 24.7298429]),
                    uv=np.array([0.13985629, 0.20646843]),
                    UVW=np.array([-19.30294902, -39.56090075, 27.62550537])),
                TCS_ColorimetryData(
                    name='TCS13',
                    XYZ=np.array([56.63907549, 57.50545374, 39.17805]),
                    uv=np.array([0.21852443, 0.33280062]),
                    UVW=np.array([23.92148732, 18.87040227, 79.49608348])),
                TCS_ColorimetryData(
                    name='TCS14',
                    XYZ=np.array([9.42594992, 12.07064446, 5.06612415]),
                    uv=np.array([0.18330936, 0.35211232]),
                    UVW=np.array([-6.1238664, 19.9332886, 40.34780872]))
            ], [
                TCS_ColorimetryData(
                    name='TCS01',
                    XYZ=np.array([33.04406274, 29.80722965, 24.25677014]),
                    uv=np.array([0.23905009, 0.32345089]),
                    UVW=np.array([32.11150701, 8.4025005, 60.51407102])),
                TCS_ColorimetryData(
                    name='TCS02',
                    XYZ=np.array([27.53323581, 28.90793444, 14.76248032]),
                    uv=np.array([0.21789532, 0.34316182]),
                    UVW=np.array([15.26809231, 23.59761128, 59.72655443])),
                TCS_ColorimetryData(
                    name='TCS03',
                    XYZ=np.array([23.95435019, 30.44568852, 9.80615507]),
                    uv=np.array([0.18785584, 0.35814374]),
                    UVW=np.array([-8.23625903, 36.01892099, 61.06360597])),
                TCS_ColorimetryData(
                    name='TCS04',
                    XYZ=np.array([20.43638681, 29.46870454, 21.05101191]),
                    uv=np.array([0.15552214, 0.33638794]),
                    UVW=np.array([-33.43495759, 18.48941724, 60.21950681])),
                TCS_ColorimetryData(
                    name='TCS05',
                    XYZ=np.array([24.95728556, 30.82110743, 39.94366077]),
                    uv=np.array([0.16443476, 0.30460412]),
                    UVW=np.array([-26.96894169, -6.51619473, 61.38315768])),
                TCS_ColorimetryData(
                    name='TCS06',
                    XYZ=np.array([28.15012994, 29.75806707, 57.21213255]),
                    uv=np.array([0.17426171, 0.27632333]),
                    UVW=np.array([-18.84311713, -28.6517426, 60.4714316])),
                TCS_ColorimetryData(
                    name='TCS07',
                    XYZ=np.array([33.29875981, 29.36956806, 52.57688943]),
                    uv=np.array([0.21089415, 0.27901355]),
                    UVW=np.array([9.89894512, -26.38829247, 60.13281743])),
                TCS_ColorimetryData(
                    name='TCS08',
                    XYZ=np.array([37.64824851, 31.35309879, 44.88145951]),
                    uv=np.array([0.23435348, 0.29275098]),
                    UVW=np.array([29.03544464, -16.09146766, 61.83156811])),
                TCS_ColorimetryData(
                    name='TCS09',
                    XYZ=np.array([20.68888349, 11.28578196, 4.29031293]),
                    uv=np.array([0.40797112, 0.33382225]),
                    UVW=np.array([106.54776544, 10.69454868, 39.07688665])),
                TCS_ColorimetryData(
                    name='TCS10',
                    XYZ=np.array([55.03120276, 59.04411929, 11.87116937]),
                    uv=np.array([0.22546691, 0.36286219]),
                    UVW=np.array([28.44874091, 52.32328834, 80.34916371])),
                TCS_ColorimetryData(
                    name='TCS11',
                    XYZ=np.array([12.13121967, 20.3541437, 15.18142797]),
                    uv=np.array([0.1336819, 0.33644357]),
                    UVW=np.array([-43.01323833, 15.77519367, 51.25863839])),
                TCS_ColorimetryData(
                    name='TCS12',
                    XYZ=np.array([6.19245638, 6.41273455, 27.30815071]),
                    uv=np.array([0.13439371, 0.20876154]),
                    UVW=np.array([-24.4374163, -39.8151001, 29.44665364])),
                TCS_ColorimetryData(
                    name='TCS13',
                    XYZ=np.array([58.97285728, 57.14500933, 40.86401249]),
                    uv=np.array([0.22709381, 0.33008264]),
                    UVW=np.array([29.75220364, 17.84629845, 79.29404816])),
                TCS_ColorimetryData(
                    name='TCS14',
                    XYZ=np.array([9.34392028, 11.70931454, 5.33816006]),
                    uv=np.array([0.1859504, 0.34953505]),
                    UVW=np.array([-6.3492713, 19.0078073, 39.7697741]))
            ]))

        specification_t = colour_rendering_index(
            ILLUMINANTS_SDS['FL1'], additional_data=True)

        np.testing.assert_almost_equal(
            [
                data.Q_a
                for _index, data in sorted(specification_r.Q_as.items())
            ],
            [
                data.Q_a
                for _index, data in sorted(specification_t.Q_as.items())
            ],
            decimal=7,
        )