Exemple #1
0
def multi_transfer_function_plot(colourspaces=None,
                                 inverse=False, **kwargs):
    """
    Plots given colourspaces transfer functions.

    Parameters
    ----------
    colourspaces : list, optional
        Colourspaces transfer functions to plot.
    inverse : bool
        Plot inverse transfer functions.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> multi_transfer_function_plot(['sRGB', 'Rec. 709'])  # doctest: +SKIP
    True
    """

    if colourspaces is None:
        colourspaces = ['sRGB', 'Rec. 709']

    samples = np.linspace(0, 1, 1000)
    for i, colourspace in enumerate(colourspaces):
        colourspace, name = get_RGB_colourspace(colourspace), colourspace

        RGBs = np.array([colourspace.inverse_transfer_function(x)
                         if inverse else
                         colourspace.transfer_function(x)
                         for x in samples])
        pylab.plot(samples,
                   RGBs,
                   label=u'{0}'.format(colourspace.name),
                   linewidth=2)

    settings = {
        'title': '{0} - Transfer Functions'.format(
            ', '.join(colourspaces)),
        'x_tighten': True,
        'legend': True,
        'legend_location': 'upper left',
        'x_ticker': True,
        'y_ticker': True,
        'grid': True,
        'limits': [0, 1, 0, 1]}

    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #2
0
def multi_munsell_value_function_plot(
        functions=None,
        **kwargs):
    """
    Plots given *Munsell* value functions.

    Parameters
    ----------
    functions : array_like, optional
        *Munsell* value functions to plot.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Raises
    ------
    KeyError
        If one of the given *Munsell* value function is not found in the
        factory *Munsell* value functions.

    Examples
    --------
    >>> fs = ('ASTM D1535-08', 'McCamy 1987')
    >>> multi_munsell_value_function_plot(fs)  # doctest: +SKIP
    True
    """

    if functions is None:
        functions = ('ASTM D1535-08',
                     'McCamy 1987')

    samples = np.linspace(0, 100, 1000)
    for i, function in enumerate(functions):
        function, name = MUNSELL_VALUE_METHODS.get(function), function
        if function is None:
            raise KeyError(
                ('"{0}" "Munsell" value function not found in '
                 'factory "Munsell" value functions: "{1}".').format(
                    name, sorted(MUNSELL_VALUE_METHODS.keys())))

        pylab.plot(samples,
                   [function(x) for x in samples],
                   label=u'{0}'.format(name),
                   linewidth=2)

    settings = {
        'title': '{0} - Munsell Functions'.format(', '.join(functions)),
        'x_label': 'Luminance Y',
        'y_label': 'Munsell Value V',
        'x_tighten': True,
        'legend': True,
        'legend_location': 'upper left',
        'x_ticker': True,
        'y_ticker': True,
        'grid': True,
        'limits': [0, 100, 0, 100]}

    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #3
0
def blackbody_spectral_radiance_plot(
        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.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> blackbody_spectral_radiance_plot()  # doctest: +SKIP
    True
    """

    cmfs, name = get_cmfs(cmfs), cmfs

    matplotlib.pyplot.subplots_adjust(hspace=0.4)

    spd = blackbody_spd(temperature, cmfs.shape)

    matplotlib.pyplot.figure(1)
    matplotlib.pyplot.subplot(211)

    settings = {'title': '{0} - Spectral Radiance'.format(blackbody),
                'y_label': u'W / (sr m²) / m',
                'standalone': False}
    settings.update(kwargs)

    single_spd_plot(spd, name, **settings)

    XYZ = spectral_to_XYZ(spd, cmfs)
    RGB = normalise(XYZ_to_sRGB(XYZ / 100))

    matplotlib.pyplot.subplot(212)

    settings = {'title': '{0} - Colour'.format(blackbody),
                'x_label': '{0}K'.format(temperature),
                'y_label': '',
                'aspect': None,
                'standalone': False}

    single_colour_plot(colour_parameter(name='', RGB=RGB), **settings)

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

    bounding_box(**settings)
    aspect(**settings)
    return display(**settings)
Exemple #4
0
def multi_lightness_function_plot(functions=None, **kwargs):
    """
    Plots given *Lightness* functions.

    Parameters
    ----------
    functions : array_like, optional
        *Lightness* functions to plot.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Raises
    ------
    KeyError
        If one of the given *Lightness* function is not found in the factory
        *Lightness* functions.

    Examples
    --------
    >>> fs = ('CIE 1976', 'Wyszecki 1964')
    >>> multi_lightness_function_plot(fs)  # doctest: +SKIP
    True
    """

    if functions is None:
        functions = ('CIE 1976', 'Wyszecki 1964')

    samples = np.linspace(0, 100, 1000)
    for i, function in enumerate(functions):
        function, name = LIGHTNESS_METHODS.get(function), function
        if function is None:
            raise KeyError(
                ('"{0}" "Lightness" function not found in factory '
                 '"Lightness" functions: "{1}".').format(
                    name, sorted(LIGHTNESS_METHODS.keys())))

        pylab.plot(samples,
                   [function(x) for x in samples],
                   label=u'{0}'.format(name),
                   linewidth=2)

    settings = {
        'title': '{0} - Lightness Functions'.format(', '.join(functions)),
        'x_label': 'Luminance Y',
        'y_label': 'Lightness L*',
        'x_tighten': True,
        'legend': True,
        'legend_location': 'upper left',
        'x_ticker': True,
        'y_ticker': True,
        'grid': True,
        'limits': [0, 100, 0, 100]}

    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #5
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 #6
0
def colourspaces_CIE_1931_chromaticity_diagram_plot(
        colourspaces=None,
        cmfs='CIE 1931 2 Degree Standard Observer',
        **kwargs):
    """
    Plots given colourspaces in *CIE 1931 Chromaticity Diagram*.

    Parameters
    ----------
    colourspaces : list, optional
        Colourspaces to plot.
    cmfs : unicode, optional
        Standard observer colour matching functions used for diagram bounds.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> csps = ['sRGB', 'ACES RGB']
    >>> colourspaces_CIE_1931_chromaticity_diagram_plot(csps)  # doctest: +SKIP
    True
    """

    if colourspaces is None:
        colourspaces = ('sRGB', 'ACES RGB', 'Pointer Gamut')

    cmfs, name = get_cmfs(cmfs), cmfs

    settings = {'title': '{0} - {1}'.format(', '.join(colourspaces), name),
                'standalone': False}
    settings.update(kwargs)

    if not CIE_1931_chromaticity_diagram_plot(**settings):
        return

    x_limit_min, x_limit_max = [-0.1], [0.9]
    y_limit_min, y_limit_max = [-0.1], [0.9]
    for colourspace in colourspaces:
        if colourspace == 'Pointer Gamut':
            x, y = tuple(zip(*POINTER_GAMUT_DATA))
            pylab.plot(x,
                       y,
                       label='Pointer Gamut',
                       color='0.95',
                       linewidth=2)
            pylab.plot([x[-1],
                        x[0]],
                       [y[-1],
                        y[0]],
                       color='0.95',
                       linewidth=2)
        else:
            colourspace, name = get_RGB_colourspace(
                colourspace), colourspace

            random_colour = lambda: float(random.randint(64, 224)) / 255
            r, g, b = random_colour(), random_colour(), random_colour()

            primaries = colourspace.primaries
            whitepoint = colourspace.whitepoint

            pylab.plot([whitepoint[0], whitepoint[0]],
                       [whitepoint[1], whitepoint[1]],
                       color=(r, g, b),
                       label=colourspace.name,
                       linewidth=2)
            pylab.plot([whitepoint[0], whitepoint[0]],
                       [whitepoint[1], whitepoint[1]],
                       'o',
                       color=(r, g, b),
                       linewidth=2)
            pylab.plot([primaries[0, 0], primaries[1, 0]],
                       [primaries[0, 1], primaries[1, 1]],
                       'o-',
                       color=(r, g, b),
                       linewidth=2)
            pylab.plot([primaries[1, 0], primaries[2, 0]],
                       [primaries[1, 1], primaries[2, 1]],
                       'o-',
                       color=(r, g, b),
                       linewidth=2)
            pylab.plot([primaries[2, 0], primaries[0, 0]],
                       [primaries[2, 1], primaries[0, 1]],
                       'o-',
                       color=(r, g, b),
                       linewidth=2)

            x_limit_min.append(np.amin(primaries[:, 0]))
            y_limit_min.append(np.amin(primaries[:, 1]))
            x_limit_max.append(np.amax(primaries[:, 0]))
            y_limit_max.append(np.amax(primaries[:, 1]))

    settings.update({'legend': True,
                     'legend_location': 'upper right',
                     'x_tighten': True,
                     'y_tighten': True,
                     'limits': [min(x_limit_min), max(x_limit_max),
                                min(y_limit_min), max(y_limit_max)],
                     'margins': [-0.05, 0.05, -0.05, 0.05],
                     'standalone': True})

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #7
0
def CIE_1931_chromaticity_diagram_colours_plot(
        surface=1.25,
        spacing=0.00075,
        cmfs='CIE 1931 2 Degree Standard Observer',
        **kwargs):
    """
    Plots the *CIE 1931 Chromaticity Diagram* colours.

    Parameters
    ----------
    surface : numeric, optional
        Generated markers surface.
    spacing : numeric, optional
        Spacing between markers.
    cmfs : unicode, optional
        Standard observer colour matching functions used for diagram bounds.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> CIE_1931_chromaticity_diagram_colours_plot()  # doctest: +SKIP
    True
    """

    cmfs, name = get_cmfs(cmfs), cmfs

    illuminant = ILLUMINANTS.get(
        'CIE 1931 2 Degree Standard Observer').get('E')

    XYZs = [value for key, value in cmfs]

    x, y = tuple(zip(*([XYZ_to_xy(x) for x in XYZs])))

    path = matplotlib.path.Path(tuple(zip(x, y)))
    x_dot, y_dot, colours = [], [], []
    for i in np.arange(0, 1, spacing):
        for j in np.arange(0, 1, spacing):
            if path.contains_path(matplotlib.path.Path([[i, j], [i, j]])):
                x_dot.append(i)
                y_dot.append(j)

                XYZ = xy_to_XYZ((i, j))
                RGB = normalise(XYZ_to_sRGB(XYZ, illuminant))

                colours.append(RGB)

    pylab.scatter(x_dot, y_dot, color=colours, s=surface)

    settings = {'no_ticks': True,
                'bounding_box': [0, 1, 0, 1],
                'bbox_inches': 'tight',
                'pad_inches': 0}
    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #8
0
def CIE_1931_chromaticity_diagram_plot(
        cmfs='CIE 1931 2 Degree Standard Observer', **kwargs):
    """
    Plots the *CIE 1931 Chromaticity Diagram*.

    Parameters
    ----------
    cmfs : unicode, optional
        Standard observer colour matching functions used for diagram bounds.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> CIE_1931_chromaticity_diagram_plot()  # doctest: +SKIP
    True

    """

    cmfs, name = get_cmfs(cmfs), cmfs

    image = matplotlib.image.imread(
        os.path.join(PLOTTING_RESOURCES_DIRECTORY,
                     'CIE_1931_Chromaticity_Diagram_{0}_Small.png'.format(
                         cmfs.name.replace(' ', '_'))))
    pylab.imshow(image, interpolation='nearest', extent=(0, 1, 0, 1))

    labels = (
        [390, 460, 470, 480, 490, 500, 510, 520, 540, 560, 580, 600, 620,
         700])

    wavelengths = cmfs.wavelengths
    equal_energy = np.array([1 / 3] * 2)

    XYZs = [value for key, value in cmfs]

    x, y = tuple(zip(*([XYZ_to_xy(x) for x in XYZs])))

    wavelengths_chromaticity_coordinates = dict(
        tuple(zip(wavelengths, tuple(zip(x, y)))))

    pylab.plot(x, y, color='black', linewidth=2)
    pylab.plot((x[-1], x[0]), (y[-1], y[0]), color='black', linewidth=2)

    for label in labels:
        x, y = wavelengths_chromaticity_coordinates.get(label)
        pylab.plot(x, y, 'o', color='black', linewidth=2)

        index = bisect.bisect(wavelengths, label)
        left = wavelengths[index - 1] if index >= 0 else wavelengths[index]
        right = (wavelengths[index]
                 if index < len(wavelengths) else
                 wavelengths[-1])

        dx = (wavelengths_chromaticity_coordinates.get(right)[0] -
              wavelengths_chromaticity_coordinates.get(left)[0])
        dy = (wavelengths_chromaticity_coordinates.get(right)[1] -
              wavelengths_chromaticity_coordinates.get(left)[1])

        norme = lambda x: x / np.linalg.norm(x)

        xy = np.array([x, y])
        direction = np.array((-dy, dx))

        normal = (np.array((-dy, dx))
                  if np.dot(norme(xy - equal_energy),
                            norme(direction)) > 0 else
                  np.array((dy, -dx)))
        normal = norme(normal)
        normal /= 25

        pylab.plot([x, x + normal[0] * 0.75],
                   [y, y + normal[1] * 0.75],
                   color='black',
                   linewidth=1.5)
        pylab.text(x + normal[0],
                   y + normal[1],
                   label,
                   clip_on=True,
                   ha='left' if normal[0] >= 0 else 'right',
                   va='center',
                   fontdict={'size': 'small'})

    settings = {
        'title': 'CIE 1931 Chromaticity Diagram - {0}'.format(name),
        'x_label': 'CIE x',
        'y_label': 'CIE y',
        'x_ticker': True,
        'y_ticker': True,
        'grid': True,
        'bounding_box': [-0.1, 0.9, -0.1, 0.9],
        'bbox_inches': 'tight',
        'pad_inches': 0}
    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #9
0
def multi_cmfs_plot(cmfss=None, **kwargs):
    """
    Plots given colour matching functions.

    Parameters
    ----------
    cmfss : array_like, optional
        Colour matching functions to plot.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> cmfss = [
    ... 'CIE 1931 2 Degree Standard Observer',
    ... 'CIE 1964 10 Degree Standard Observer']
    >>> multi_cmfs_plot(cmfss)  # doctest: +SKIP
    True
    """

    if cmfss is None:
        cmfss = ('CIE 1931 2 Degree Standard Observer',
                 'CIE 1964 10 Degree Standard Observer')

    x_limit_min, x_limit_max, y_limit_min, y_limit_max = [], [], [], []
    for axis, rgb in (('x', [1, 0, 0]), ('y', [0, 1, 0]), ('z', [0, 0, 1])):
        for i, cmfs in enumerate(cmfss):
            cmfs, name = get_cmfs(cmfs), cmfs

            rgb = [reduce(lambda y, _: y * 0.5, range(i), x) for x in rgb]
            wavelengths, values = tuple(
                zip(*[(key, value) for key, value in getattr(cmfs, axis)]))

            shape = cmfs.shape
            x_limit_min.append(shape.start)
            x_limit_max.append(shape.end)
            y_limit_min.append(min(values))
            y_limit_max.append(max(values))

            pylab.plot(wavelengths,
                       values,
                       color=rgb,
                       label=u'{0} - {1}'.format(cmfs.labels.get(axis),
                                                 cmfs.name),
                       linewidth=2)

    settings = {
        'title':
        '{0} - Colour Matching Functions'.format(', '.join(cmfss)),
        'x_label':
        u'Wavelength λ (nm)',
        'y_label':
        'Tristimulus Values',
        'x_tighten':
        True,
        'legend':
        True,
        'legend_location':
        'upper right',
        'x_ticker':
        True,
        'y_ticker':
        True,
        'grid':
        True,
        'y_axis_line':
        True,
        'limits': [
            min(x_limit_min),
            max(x_limit_max),
            min(y_limit_min),
            max(y_limit_max)
        ]
    }
    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #10
0
def multi_spd_plot(spds,
                   cmfs='CIE 1931 2 Degree Standard Observer',
                   use_spds_colours=False,
                   normalise_spds_colours=False,
                   **kwargs):
    """
    Plots given spectral power distributions.

    Parameters
    ----------
    spds : list, optional
        Spectral power distributions to plot.
    cmfs : unicode, optional
        Standard observer colour matching functions used for spectrum creation.
    use_spds_colours : bool, optional
        Use spectral power distributions colours.
    normalise_spds_colours : bool
        Should spectral power distributions colours normalised.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> from colour import SpectralPowerDistribution
    >>> data1 = {400: 0.0641, 420: 0.0645, 440: 0.0562}
    >>> data2 = {400: 0.134, 420: 0.789, 440: 1.289}
    >>> spd1 = SpectralPowerDistribution('Custom1', data1)
    >>> spd2 = SpectralPowerDistribution('Custom2', data2)
    >>> multi_spd_plot([spd1, spd2])  # doctest: +SKIP
    True
    """

    cmfs, name = get_cmfs(cmfs), cmfs

    if use_spds_colours:
        illuminant = ILLUMINANTS_RELATIVE_SPDS.get('D65')

    x_limit_min, x_limit_max, y_limit_min, y_limit_max = [], [], [], []
    for spd in spds:
        wavelengths, values = tuple(zip(*[(key, value) for key, value in spd]))

        shape = spd.shape
        x_limit_min.append(shape.start)
        x_limit_max.append(shape.end)
        y_limit_min.append(min(values))
        y_limit_max.append(max(values))

        matplotlib.pyplot.rc("axes", color_cycle=["r", "g", "b", "y"])

        if use_spds_colours:
            XYZ = spectral_to_XYZ(spd, cmfs, illuminant) / 100
            if normalise_spds_colours:
                XYZ = normalise(XYZ, clip=False)
            RGB = np.clip(XYZ_to_sRGB(XYZ), 0, 1)

            pylab.plot(wavelengths,
                       values,
                       color=RGB,
                       label=spd.name,
                       linewidth=2)
        else:
            pylab.plot(wavelengths, values, label=spd.name, linewidth=2)

    settings = {
        'x_label':
        u'Wavelength λ (nm)',
        'y_label':
        'Spectral Power Distribution',
        'x_tighten':
        True,
        'legend':
        True,
        'legend_location':
        'upper left',
        'x_ticker':
        True,
        'y_ticker':
        True,
        'limits': [
            min(x_limit_min),
            max(x_limit_max),
            min(y_limit_min),
            max(y_limit_max)
        ]
    }
    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #11
0
def CIE_1931_chromaticity_diagram_colours_plot(
        surface=1.25,
        spacing=0.00075,
        cmfs='CIE 1931 2 Degree Standard Observer',
        **kwargs):
    """
    Plots the *CIE 1931 Chromaticity Diagram* colours.

    Parameters
    ----------
    surface : numeric, optional
        Generated markers surface.
    spacing : numeric, optional
        Spacing between markers.
    cmfs : unicode, optional
        Standard observer colour matching functions used for diagram bounds.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> CIE_1931_chromaticity_diagram_colours_plot()  # doctest: +SKIP
    True
    """

    cmfs, name = get_cmfs(cmfs), cmfs

    illuminant = ILLUMINANTS.get('CIE 1931 2 Degree Standard Observer').get(
        'E')

    XYZs = [value for key, value in cmfs]

    x, y = tuple(zip(*([XYZ_to_xy(x) for x in XYZs])))

    path = matplotlib.path.Path(tuple(zip(x, y)))
    x_dot, y_dot, colours = [], [], []
    for i in np.arange(0, 1, spacing):
        for j in np.arange(0, 1, spacing):
            if path.contains_path(matplotlib.path.Path([[i, j], [i, j]])):
                x_dot.append(i)
                y_dot.append(j)

                XYZ = xy_to_XYZ((i, j))
                RGB = normalise(XYZ_to_sRGB(XYZ, illuminant))

                colours.append(RGB)

    pylab.scatter(x_dot, y_dot, color=colours, s=surface)

    settings = {
        'no_ticks': True,
        'bounding_box': [0, 1, 0, 1],
        'bbox_inches': 'tight',
        'pad_inches': 0
    }
    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #12
0
def CIE_1976_UCS_chromaticity_diagram_plot(
        cmfs='CIE 1931 2 Degree Standard Observer', **kwargs):
    """
    Plots the *CIE 1976 UCS Chromaticity Diagram*.

    Parameters
    ----------
    cmfs : unicode, optional
        Standard observer colour matching functions used for diagram bounds.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> CIE_1976_UCS_chromaticity_diagram_plot()  # doctest: +SKIP
    True
    """

    cmfs, name = get_cmfs(cmfs), cmfs

    image = matplotlib.image.imread(
        os.path.join(
            PLOTTING_RESOURCES_DIRECTORY,
            'CIE_1976_UCS_Chromaticity_Diagram_{0}_Small.png'.format(
                cmfs.name.replace(' ', '_'))))
    pylab.imshow(image, interpolation='nearest', extent=(0, 1, 0, 1))

    labels = [
        420, 430, 440, 450, 460, 470, 480, 490, 500, 510, 520, 530, 540, 550,
        560, 570, 580, 590, 600, 610, 620, 630, 640, 680
    ]

    wavelengths = cmfs.wavelengths
    equal_energy = np.array([1 / 3] * 2)

    illuminant = ILLUMINANTS.get('CIE 1931 2 Degree Standard Observer').get(
        'D50')

    Luvs = [XYZ_to_Luv(value, illuminant) for key, value in cmfs]

    u, v = tuple(zip(*([Luv_to_uv(x) for x in Luvs])))

    wavelengths_chromaticity_coordinates = dict(
        zip(wavelengths, tuple(zip(u, v))))

    pylab.plot(u, v, color='black', linewidth=2)
    pylab.plot((u[-1], u[0]), (v[-1], v[0]), color='black', linewidth=2)

    for label in labels:
        u, v = wavelengths_chromaticity_coordinates.get(label)
        pylab.plot(u, v, 'o', color='black', linewidth=2)

        index = bisect.bisect(wavelengths, label)
        left = wavelengths[index - 1] if index >= 0 else wavelengths[index]
        right = (wavelengths[index]
                 if index < len(wavelengths) else wavelengths[-1])

        dx = (wavelengths_chromaticity_coordinates.get(right)[0] -
              wavelengths_chromaticity_coordinates.get(left)[0])
        dy = (wavelengths_chromaticity_coordinates.get(right)[1] -
              wavelengths_chromaticity_coordinates.get(left)[1])

        norme = lambda x: x / np.linalg.norm(x)

        uv = np.array([u, v])
        direction = np.array((-dy, dx))

        normal = (np.array(
            (-dy,
             dx)) if np.dot(norme(uv - equal_energy), norme(direction)) > 0
                  else np.array((dy, -dx)))
        normal = norme(normal)
        normal /= 25

        pylab.plot([u, u + normal[0] * 0.75], [v, v + normal[1] * 0.75],
                   color='black',
                   linewidth=1.5)
        pylab.text(u + normal[0],
                   v + normal[1],
                   label,
                   clip_on=True,
                   ha='left' if normal[0] >= 0 else 'right',
                   va='center',
                   fontdict={'size': 'small'})

    settings = {
        'title': 'CIE 1976 UCS Chromaticity Diagram - {0}'.format(name),
        'x_label': 'CIE u"',
        'y_label': 'CIE v"',
        'x_ticker': True,
        'y_ticker': True,
        'grid': True,
        'bounding_box': [-0.1, .7, -.1, .7],
        'bbox_inches': 'tight',
        'pad_inches': 0
    }
    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #13
0
def CIE_1931_chromaticity_diagram_plot(
        cmfs='CIE 1931 2 Degree Standard Observer', **kwargs):
    """
    Plots the *CIE 1931 Chromaticity Diagram*.

    Parameters
    ----------
    cmfs : unicode, optional
        Standard observer colour matching functions used for diagram bounds.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> CIE_1931_chromaticity_diagram_plot()  # doctest: +SKIP
    True

    """

    cmfs, name = get_cmfs(cmfs), cmfs

    image = matplotlib.image.imread(
        os.path.join(
            PLOTTING_RESOURCES_DIRECTORY,
            'CIE_1931_Chromaticity_Diagram_{0}_Small.png'.format(
                cmfs.name.replace(' ', '_'))))
    pylab.imshow(image, interpolation='nearest', extent=(0, 1, 0, 1))

    labels = ([
        390, 460, 470, 480, 490, 500, 510, 520, 540, 560, 580, 600, 620, 700
    ])

    wavelengths = cmfs.wavelengths
    equal_energy = np.array([1 / 3] * 2)

    XYZs = [value for key, value in cmfs]

    x, y = tuple(zip(*([XYZ_to_xy(x) for x in XYZs])))

    wavelengths_chromaticity_coordinates = dict(
        tuple(zip(wavelengths, tuple(zip(x, y)))))

    pylab.plot(x, y, color='black', linewidth=2)
    pylab.plot((x[-1], x[0]), (y[-1], y[0]), color='black', linewidth=2)

    for label in labels:
        x, y = wavelengths_chromaticity_coordinates.get(label)
        pylab.plot(x, y, 'o', color='black', linewidth=2)

        index = bisect.bisect(wavelengths, label)
        left = wavelengths[index - 1] if index >= 0 else wavelengths[index]
        right = (wavelengths[index]
                 if index < len(wavelengths) else wavelengths[-1])

        dx = (wavelengths_chromaticity_coordinates.get(right)[0] -
              wavelengths_chromaticity_coordinates.get(left)[0])
        dy = (wavelengths_chromaticity_coordinates.get(right)[1] -
              wavelengths_chromaticity_coordinates.get(left)[1])

        norme = lambda x: x / np.linalg.norm(x)

        xy = np.array([x, y])
        direction = np.array((-dy, dx))

        normal = (np.array(
            (-dy,
             dx)) if np.dot(norme(xy - equal_energy), norme(direction)) > 0
                  else np.array((dy, -dx)))
        normal = norme(normal)
        normal /= 25

        pylab.plot([x, x + normal[0] * 0.75], [y, y + normal[1] * 0.75],
                   color='black',
                   linewidth=1.5)
        pylab.text(x + normal[0],
                   y + normal[1],
                   label,
                   clip_on=True,
                   ha='left' if normal[0] >= 0 else 'right',
                   va='center',
                   fontdict={'size': 'small'})

    settings = {
        'title': 'CIE 1931 Chromaticity Diagram - {0}'.format(name),
        'x_label': 'CIE x',
        'y_label': 'CIE y',
        'x_ticker': True,
        'y_ticker': True,
        'grid': True,
        'bounding_box': [-0.1, 0.9, -0.1, 0.9],
        'bbox_inches': 'tight',
        'pad_inches': 0
    }
    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #14
0
def colour_checker_plot(colour_checker='ColorChecker 2005', **kwargs):
    """
    Plots given colour checker.

    Parameters
    ----------
    colour_checker : unicode, optional
        Color checker name.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Raises
    ------
    KeyError
        If the given colour rendition chart is not found in the factory colour
        rendition charts.

    Examples
    --------
    >>> colour_checker_plot()  # doctest: +SKIP
    True
    """

    colour_checker, name = COLOURCHECKERS.get(colour_checker), colour_checker
    if colour_checker is None:
        raise KeyError(('Colour checker "{0}" not found in '
                        'factory colour checkers: "{1}".').format(
                            name, sorted(COLOURCHECKERS.keys())))

    _, data, illuminant = colour_checker
    colour_parameters = []
    for index, label, x, y, Y in data:
        XYZ = xyY_to_XYZ((x, y, Y))
        RGB = XYZ_to_sRGB(XYZ, illuminant)

        colour_parameters.append(
            colour_parameter(label.title(), np.clip(np.ravel(RGB), 0, 1)))

    background_colour = '0.1'
    matplotlib.pyplot.gca().patch.set_facecolor(background_colour)

    width = height = 1.0
    spacing = 0.25
    across = 6

    settings = {
        'standalone': False,
        'width': width,
        'height': height,
        'spacing': spacing,
        'across': across,
        'text_size': 8,
        'margins': [-0.125, 0.125, -0.5, 0.125]
    }
    settings.update(kwargs)

    multi_colour_plot(colour_parameters, **settings)

    text_x = width * (across / 2) + (across * (spacing / 2)) - spacing / 2
    text_y = -(len(colour_parameters) / across + spacing / 2)

    pylab.text(text_x,
               text_y,
               '{0} - {1} - Colour Rendition Chart'.format(
                   name,
                   RGB_COLOURSPACES.get('sRGB').name),
               color='0.95',
               clip_on=True,
               ha='center')

    settings.update({
        'title': name,
        'facecolor': background_colour,
        'edgecolor': None,
        'standalone': True
    })

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #15
0
def the_blue_sky_plot(cmfs='CIE 1931 2 Degree Standard Observer', **kwargs):
    """
    Plots the blue sky.

    Parameters
    ----------
    cmfs : unicode, optional
        Standard observer colour matching functions.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> the_blue_sky_plot()  # doctest: +SKIP
    True
    """

    cmfs, name = get_cmfs(cmfs), cmfs

    ASTM_G_173_spd = ASTM_G_173_ETR.clone()
    rayleigh_spd = rayleigh_scattering_spd()
    ASTM_G_173_spd.align(rayleigh_spd.shape)

    spd = rayleigh_spd * ASTM_G_173_spd

    matplotlib.pyplot.subplots_adjust(hspace=0.4)

    matplotlib.pyplot.figure(1)
    matplotlib.pyplot.subplot(211)

    settings = {
        'title': 'The Blue Sky - Synthetic Spectral Power Distribution',
        'y_label': u'W / m-2 / nm-1',
        'standalone': False
    }
    settings.update(kwargs)

    single_spd_plot(spd, name, **settings)

    matplotlib.pyplot.subplot(212)

    settings = {
        'title':
        'The Blue Sky - Colour',
        'x_label': ('The sky is blue because molecules in the atmosphere '
                    'scatter shorter wavelengths more than longer ones.\n'
                    'The synthetic spectral power distribution is computed as '
                    'follows: '
                    '(ASTM G-173 ETR * Standard Air Rayleigh Scattering).'),
        'y_label':
        '',
        'aspect':
        None,
        'standalone':
        False
    }

    blue_sky_color = XYZ_to_sRGB(spectral_to_XYZ(spd))
    single_colour_plot(colour_parameter('', normalise(blue_sky_color)),
                       **settings)

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

    bounding_box(**settings)
    aspect(**settings)
    return display(**settings)
Exemple #16
0
def colour_checker_plot(colour_checker='ColorChecker 2005', **kwargs):
    """
    Plots given colour checker.

    Parameters
    ----------
    colour_checker : unicode, optional
        Color checker name.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Raises
    ------
    KeyError
        If the given colour rendition chart is not found in the factory colour
        rendition charts.

    Examples
    --------
    >>> colour_checker_plot()  # doctest: +SKIP
    True
    """

    colour_checker, name = COLOURCHECKERS.get(colour_checker), colour_checker
    if colour_checker is None:
        raise KeyError(
            ('Colour checker "{0}" not found in '
             'factory colour checkers: "{1}".').format(
                name, sorted(COLOURCHECKERS.keys())))

    _, data, illuminant = colour_checker
    colour_parameters = []
    for index, label, x, y, Y in data:
        XYZ = xyY_to_XYZ((x, y, Y))
        RGB = XYZ_to_sRGB(XYZ, illuminant)

        colour_parameters.append(
            colour_parameter(label.title(), np.clip(np.ravel(RGB), 0, 1)))

    background_colour = '0.1'
    matplotlib.pyplot.gca().patch.set_facecolor(background_colour)

    width = height = 1.0
    spacing = 0.25
    across = 6

    settings = {'standalone': False,
                'width': width,
                'height': height,
                'spacing': spacing,
                'across': across,
                'text_size': 8,
                'margins': [-0.125, 0.125, -0.5, 0.125]}
    settings.update(kwargs)

    multi_colour_plot(colour_parameters, **settings)

    text_x = width * (across / 2) + (across * (spacing / 2)) - spacing / 2
    text_y = -(len(colour_parameters) / across + spacing / 2)

    pylab.text(text_x,
               text_y,
               '{0} - {1} - Colour Rendition Chart'.format(
                   name, RGB_COLOURSPACES.get('sRGB').name),
               color='0.95',
               clip_on=True,
               ha='center')

    settings.update({'title': name,
                     'facecolor': background_colour,
                     'edgecolor': None,
                     'standalone': True})

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #17
0
def multi_lightness_function_plot(functions=None, **kwargs):
    """
    Plots given *Lightness* functions.

    Parameters
    ----------
    functions : array_like, optional
        *Lightness* functions to plot.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Raises
    ------
    KeyError
        If one of the given *Lightness* function is not found in the factory
        *Lightness* functions.

    Examples
    --------
    >>> fs = ('CIE 1976', 'Wyszecki 1964')
    >>> multi_lightness_function_plot(fs)  # doctest: +SKIP
    True
    """

    if functions is None:
        functions = ('CIE 1976', 'Wyszecki 1964')

    samples = np.linspace(0, 100, 1000)
    for i, function in enumerate(functions):
        function, name = LIGHTNESS_METHODS.get(function), function
        if function is None:
            raise KeyError(('"{0}" "Lightness" function not found in factory '
                            '"Lightness" functions: "{1}".').format(
                                name, sorted(LIGHTNESS_METHODS.keys())))

        pylab.plot(samples, [function(x) for x in samples],
                   label=u'{0}'.format(name),
                   linewidth=2)

    settings = {
        'title': '{0} - Lightness Functions'.format(', '.join(functions)),
        'x_label': 'Luminance Y',
        'y_label': 'Lightness L*',
        'x_tighten': True,
        'legend': True,
        'legend_location': 'upper left',
        'x_ticker': True,
        'y_ticker': True,
        'grid': True,
        'limits': [0, 100, 0, 100]
    }

    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #18
0
def CIE_1976_UCS_chromaticity_diagram_plot(
        cmfs='CIE 1931 2 Degree Standard Observer', **kwargs):
    """
    Plots the *CIE 1976 UCS Chromaticity Diagram*.

    Parameters
    ----------
    cmfs : unicode, optional
        Standard observer colour matching functions used for diagram bounds.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> CIE_1976_UCS_chromaticity_diagram_plot()  # doctest: +SKIP
    True
    """

    cmfs, name = get_cmfs(cmfs), cmfs

    image = matplotlib.image.imread(
        os.path.join(PLOTTING_RESOURCES_DIRECTORY,
                     'CIE_1976_UCS_Chromaticity_Diagram_{0}_Small.png'.format(
                         cmfs.name.replace(' ', '_'))))
    pylab.imshow(image, interpolation='nearest', extent=(0, 1, 0, 1))

    labels = [420, 430, 440, 450, 460, 470, 480, 490, 500, 510, 520, 530,
              540, 550, 560, 570, 580, 590, 600, 610, 620, 630, 640, 680]

    wavelengths = cmfs.wavelengths
    equal_energy = np.array([1 / 3] * 2)

    illuminant = ILLUMINANTS.get(
        'CIE 1931 2 Degree Standard Observer').get('D50')

    Luvs = [XYZ_to_Luv(value, illuminant) for key, value in cmfs]

    u, v = tuple(zip(*([Luv_to_uv(x) for x in Luvs])))

    wavelengths_chromaticity_coordinates = dict(zip(wavelengths,
                                                    tuple(zip(u, v))))

    pylab.plot(u, v, color='black', linewidth=2)
    pylab.plot((u[-1], u[0]), (v[-1], v[0]), color='black', linewidth=2)

    for label in labels:
        u, v = wavelengths_chromaticity_coordinates.get(label)
        pylab.plot(u, v, 'o', color='black', linewidth=2)

        index = bisect.bisect(wavelengths, label)
        left = wavelengths[index - 1] if index >= 0 else wavelengths[index]
        right = (wavelengths[index]
                 if index < len(wavelengths) else
                 wavelengths[-1])

        dx = (wavelengths_chromaticity_coordinates.get(right)[0] -
              wavelengths_chromaticity_coordinates.get(left)[0])
        dy = (wavelengths_chromaticity_coordinates.get(right)[1] -
              wavelengths_chromaticity_coordinates.get(left)[1])

        norme = lambda x: x / np.linalg.norm(x)

        uv = np.array([u, v])
        direction = np.array((-dy, dx))

        normal = (np.array((-dy, dx))
                  if np.dot(norme(uv - equal_energy),
                            norme(direction)) > 0 else
                  np.array((dy, -dx)))
        normal = norme(normal)
        normal /= 25

        pylab.plot([u, u + normal[0] * 0.75],
                   [v, v + normal[1] * 0.75],
                   color='black',
                   linewidth=1.5)
        pylab.text(u + normal[0],
                   v + normal[1],
                   label,
                   clip_on=True,
                   ha='left' if normal[0] >= 0 else 'right',
                   va='center',
                   fontdict={'size': 'small'})

    settings = {
        'title': 'CIE 1976 UCS Chromaticity Diagram - {0}'.format(name),
        'x_label': 'CIE u"',
        'y_label': 'CIE v"',
        'x_ticker': True,
        'y_ticker': True,
        'grid': True,
        'bounding_box': [-0.1, .7, -.1, .7],
        'bbox_inches': 'tight',
        'pad_inches': 0}
    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #19
0
def blackbody_spectral_radiance_plot(
        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.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> blackbody_spectral_radiance_plot()  # doctest: +SKIP
    True
    """

    cmfs, name = get_cmfs(cmfs), cmfs

    matplotlib.pyplot.subplots_adjust(hspace=0.4)

    spd = blackbody_spd(temperature, cmfs.shape)

    matplotlib.pyplot.figure(1)
    matplotlib.pyplot.subplot(211)

    settings = {
        'title': '{0} - Spectral Radiance'.format(blackbody),
        'y_label': u'W / (sr m²) / m',
        'standalone': False
    }
    settings.update(kwargs)

    single_spd_plot(spd, name, **settings)

    XYZ = spectral_to_XYZ(spd, cmfs)
    RGB = normalise(XYZ_to_sRGB(XYZ / 100))

    matplotlib.pyplot.subplot(212)

    settings = {
        'title': '{0} - Colour'.format(blackbody),
        'x_label': '{0}K'.format(temperature),
        'y_label': '',
        'aspect': None,
        'standalone': False
    }

    single_colour_plot(colour_parameter(name='', RGB=RGB), **settings)

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

    bounding_box(**settings)
    aspect(**settings)
    return display(**settings)
Exemple #20
0
def multi_spd_plot(spds,
                   cmfs='CIE 1931 2 Degree Standard Observer',
                   use_spds_colours=False,
                   normalise_spds_colours=False,
                   **kwargs):
    """
    Plots given spectral power distributions.

    Parameters
    ----------
    spds : list, optional
        Spectral power distributions to plot.
    cmfs : unicode, optional
        Standard observer colour matching functions used for spectrum creation.
    use_spds_colours : bool, optional
        Use spectral power distributions colours.
    normalise_spds_colours : bool
        Should spectral power distributions colours normalised.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> from colour import SpectralPowerDistribution
    >>> data1 = {400: 0.0641, 420: 0.0645, 440: 0.0562}
    >>> data2 = {400: 0.134, 420: 0.789, 440: 1.289}
    >>> spd1 = SpectralPowerDistribution('Custom1', data1)
    >>> spd2 = SpectralPowerDistribution('Custom2', data2)
    >>> multi_spd_plot([spd1, spd2])  # doctest: +SKIP
    True
    """

    cmfs, name = get_cmfs(cmfs), cmfs

    if use_spds_colours:
        illuminant = ILLUMINANTS_RELATIVE_SPDS.get('D65')

    x_limit_min, x_limit_max, y_limit_min, y_limit_max = [], [], [], []
    for spd in spds:
        wavelengths, values = tuple(zip(*[(key, value) for key, value in spd]))

        shape = spd.shape
        x_limit_min.append(shape.start)
        x_limit_max.append(shape.end)
        y_limit_min.append(min(values))
        y_limit_max.append(max(values))

        matplotlib.pyplot.rc("axes", color_cycle=["r", "g", "b", "y"])

        if use_spds_colours:
            XYZ = spectral_to_XYZ(spd, cmfs, illuminant) / 100
            if normalise_spds_colours:
                XYZ = normalise(XYZ, clip=False)
            RGB = np.clip(XYZ_to_sRGB(XYZ), 0, 1)

            pylab.plot(wavelengths, values, color=RGB, label=spd.name,
                       linewidth=2)
        else:
            pylab.plot(wavelengths, values, label=spd.name, linewidth=2)

    settings = {'x_label': u'Wavelength λ (nm)',
                'y_label': 'Spectral Power Distribution',
                'x_tighten': True,
                'legend': True,
                'legend_location': 'upper left',
                'x_ticker': True,
                'y_ticker': True,
                'limits': [min(x_limit_min), max(x_limit_max),
                           min(y_limit_min), max(y_limit_max)]}
    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #21
0
def multi_cmfs_plot(cmfss=None, **kwargs):
    """
    Plots given colour matching functions.

    Parameters
    ----------
    cmfss : array_like, optional
        Colour matching functions to plot.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> cmfss = [
    ... 'CIE 1931 2 Degree Standard Observer',
    ... 'CIE 1964 10 Degree Standard Observer']
    >>> multi_cmfs_plot(cmfss)  # doctest: +SKIP
    True
    """

    if cmfss is None:
        cmfss = ('CIE 1931 2 Degree Standard Observer',
                 'CIE 1964 10 Degree Standard Observer')

    x_limit_min, x_limit_max, y_limit_min, y_limit_max = [], [], [], []
    for axis, rgb in (('x', [1, 0, 0]),
                      ('y', [0, 1, 0]),
                      ('z', [0, 0, 1])):
        for i, cmfs in enumerate(cmfss):
            cmfs, name = get_cmfs(cmfs), cmfs

            rgb = [reduce(lambda y, _: y * 0.5, range(i), x) for x in rgb]
            wavelengths, values = tuple(
                zip(*[(key, value) for key, value in getattr(cmfs, axis)]))

            shape = cmfs.shape
            x_limit_min.append(shape.start)
            x_limit_max.append(shape.end)
            y_limit_min.append(min(values))
            y_limit_max.append(max(values))

            pylab.plot(wavelengths,
                       values,
                       color=rgb,
                       label=u'{0} - {1}'.format(
                           cmfs.labels.get(axis), cmfs.name),
                       linewidth=2)

    settings = {
        'title': '{0} - Colour Matching Functions'.format(', '.join(cmfss)),
        'x_label': u'Wavelength λ (nm)',
        'y_label': 'Tristimulus Values',
        'x_tighten': True,
        'legend': True,
        'legend_location': 'upper right',
        'x_ticker': True,
        'y_ticker': True,
        'grid': True,
        'y_axis_line': True,
        'limits': [min(x_limit_min), max(x_limit_max), min(y_limit_min),
                   max(y_limit_max)]}
    settings.update(kwargs)

    bounding_box(**settings)
    aspect(**settings)

    return display(**settings)
Exemple #22
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 #23
0
def the_blue_sky_plot(
        cmfs='CIE 1931 2 Degree Standard Observer',
        **kwargs):
    """
    Plots the blue sky.

    Parameters
    ----------
    cmfs : unicode, optional
        Standard observer colour matching functions.
    \*\*kwargs : \*\*
        Keywords arguments.

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

    Examples
    --------
    >>> the_blue_sky_plot()  # doctest: +SKIP
    True
    """

    cmfs, name = get_cmfs(cmfs), cmfs

    ASTM_G_173_spd = ASTM_G_173_ETR.clone()
    rayleigh_spd = rayleigh_scattering_spd()
    ASTM_G_173_spd.align(rayleigh_spd.shape)

    spd = rayleigh_spd * ASTM_G_173_spd

    matplotlib.pyplot.subplots_adjust(hspace=0.4)

    matplotlib.pyplot.figure(1)
    matplotlib.pyplot.subplot(211)

    settings = {
        'title': 'The Blue Sky - Synthetic Spectral Power Distribution',
        'y_label': u'W / m-2 / nm-1',
        'standalone': False}
    settings.update(kwargs)

    single_spd_plot(spd, name, **settings)

    matplotlib.pyplot.subplot(212)

    settings = {
        'title': 'The Blue Sky - Colour',
        'x_label': ('The sky is blue because molecules in the atmosphere '
                    'scatter shorter wavelengths more than longer ones.\n'
                    'The synthetic spectral power distribution is computed as '
                    'follows: '
                    '(ASTM G-173 ETR * Standard Air Rayleigh Scattering).'),
        'y_label': '',
        'aspect': None,
        'standalone': False}

    blue_sky_color = XYZ_to_sRGB(spectral_to_XYZ(spd))
    single_colour_plot(colour_parameter('', normalise(blue_sky_color)),
                       **settings)

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

    bounding_box(**settings)
    aspect(**settings)
    return display(**settings)