Source code for colour.plotting.models

# -*- coding: utf-8 -*-
"""
Colour Models Plotting
======================

Defines the colour models plotting objects:

-   :func:`colour.plotting.\
plot_RGB_colourspaces_in_chromaticity_diagram_CIE1931`
-   :func:`colour.plotting.\
plot_RGB_colourspaces_in_chromaticity_diagram_CIE1960UCS`
-   :func:`colour.plotting.\
plot_RGB_colourspaces_in_chromaticity_diagram_CIE1976UCS`
-   :func:`colour.plotting.\
plot_RGB_chromaticities_in_chromaticity_diagram_CIE1931`
-   :func:`colour.plotting.\
plot_RGB_chromaticities_in_chromaticity_diagram_CIE1960UCS`
-   :func:`colour.plotting.\
plot_RGB_chromaticities_in_chromaticity_diagram_CIE1976UCS`
-   :func:`colour.plotting.\
plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1931`
-   :func:`colour.plotting.\
plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1960UCS`
-   :func:`colour.plotting.\
plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1976UCS`
-   :func:`colour.plotting.plot_single_cctf`
-   :func:`colour.plotting.plot_multi_cctfs`
"""

from __future__ import division

import numpy as np
from matplotlib.patches import Ellipse
from matplotlib.path import Path

from colour.constants import EPSILON
from colour.algebra import (point_at_angle_on_ellipse,
                            ellipse_coefficients_canonical_form,
                            ellipse_fitting)
from colour.models import (
    ENCODING_CCTFS, DECODING_CCTFS, LCHab_to_Lab, Lab_to_XYZ, Luv_to_uv,
    MACADAM_1942_ELLIPSES_DATA, POINTER_GAMUT_BOUNDARIES, POINTER_GAMUT_DATA,
    POINTER_GAMUT_ILLUMINANT, RGB_to_RGB, RGB_to_XYZ, UCS_to_uv, XYZ_to_Luv,
    XYZ_to_UCS, XYZ_to_xy, xy_to_Luv_uv, xy_to_UCS_uv)
from colour.plotting import (
    COLOUR_STYLE_CONSTANTS, plot_chromaticity_diagram_CIE1931, artist,
    plot_chromaticity_diagram_CIE1960UCS, plot_chromaticity_diagram_CIE1976UCS,
    colour_cycle, colour_style, filter_passthrough, filter_RGB_colourspaces,
    filter_cmfs, plot_multi_functions, override_style, render)
from colour.plotting.diagrams import plot_chromaticity_diagram
from colour.utilities import (as_float_array, domain_range_scale, first_item,
                              tsplit)

__author__ = 'Colour Developers'
__copyright__ = 'Copyright (C) 2013-2019 - Colour Developers'
__license__ = 'New BSD License - http://opensource.org/licenses/BSD-3-Clause'
__maintainer__ = 'Colour Developers'
__email__ = 'colour-science@googlegroups.com'
__status__ = 'Production'

__all__ = [
    'plot_pointer_gamut', 'plot_RGB_colourspaces_in_chromaticity_diagram',
    'plot_RGB_colourspaces_in_chromaticity_diagram_CIE1931',
    'plot_RGB_colourspaces_in_chromaticity_diagram_CIE1960UCS',
    'plot_RGB_colourspaces_in_chromaticity_diagram_CIE1976UCS',
    'plot_RGB_chromaticities_in_chromaticity_diagram',
    'plot_RGB_chromaticities_in_chromaticity_diagram_CIE1931',
    'plot_RGB_chromaticities_in_chromaticity_diagram_CIE1960UCS',
    'plot_RGB_chromaticities_in_chromaticity_diagram_CIE1976UCS',
    'ellipses_MacAdam1942',
    'plot_ellipses_MacAdam1942_in_chromaticity_diagram',
    'plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1931',
    'plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1960UCS',
    'plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1976UCS',
    'plot_single_cctf', 'plot_multi_cctfs'
]


[docs]@override_style() def plot_pointer_gamut(method='CIE 1931', **kwargs): """ Plots *Pointer's Gamut* according to given method. Parameters ---------- method : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, Plotting method. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_pointer_gamut() # doctest: +SKIP .. image:: ../_static/Plotting_Plot_Pointer_Gamut.png :align: center :alt: plot_pointer_gamut """ settings = {'uniform': True} settings.update(kwargs) _figure, axes = artist(**settings) method = method.upper() if method == 'CIE 1931': def XYZ_to_ij(XYZ, *args): """ Converts given *CIE XYZ* tristimulus values to *ij* chromaticity coordinates. """ return XYZ_to_xy(XYZ, *args) def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy elif method == 'CIE 1960 UCS': def XYZ_to_ij(XYZ, *args): """ Converts given *CIE XYZ* tristimulus values to *ij* chromaticity coordinates. """ return UCS_to_uv(XYZ_to_UCS(XYZ)) def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy_to_UCS_uv(xy) elif method == 'CIE 1976 UCS': def XYZ_to_ij(XYZ, *args): """ Converts given *CIE XYZ* tristimulus values to *ij* chromaticity coordinates. """ return Luv_to_uv(XYZ_to_Luv(XYZ, *args), *args) def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy_to_Luv_uv(xy) else: raise ValueError( 'Invalid method: "{0}", must be one of ' '{{\'CIE 1931\', \'CIE 1960 UCS\', \'CIE 1976 UCS\'}}'.format( method)) ij = xy_to_ij(as_float_array(POINTER_GAMUT_BOUNDARIES)) alpha_p = COLOUR_STYLE_CONSTANTS.opacity.high colour_p = COLOUR_STYLE_CONSTANTS.colour.darkest axes.plot( ij[..., 0], ij[..., 1], label='Pointer\'s Gamut', color=colour_p, alpha=alpha_p) axes.plot( (ij[-1][0], ij[0][0]), (ij[-1][1], ij[0][1]), color=colour_p, alpha=alpha_p) XYZ = Lab_to_XYZ( LCHab_to_Lab(POINTER_GAMUT_DATA), POINTER_GAMUT_ILLUMINANT) ij = XYZ_to_ij(XYZ, POINTER_GAMUT_ILLUMINANT) axes.scatter( ij[..., 0], ij[..., 1], alpha=alpha_p / 2, color=colour_p, marker='+') settings.update({'axes': axes}) settings.update(kwargs) return render(**settings)
[docs]@override_style() def plot_RGB_colourspaces_in_chromaticity_diagram( colourspaces=None, cmfs='CIE 1931 2 Degree Standard Observer', chromaticity_diagram_callable=plot_chromaticity_diagram, method='CIE 1931', show_whitepoints=True, show_pointer_gamut=False, **kwargs): """ Plots given *RGB* colourspaces in the *Chromaticity Diagram* according to given method. Parameters ---------- colourspaces : array_like, optional *RGB* colourspaces to plot. cmfs : unicode, optional Standard observer colour matching functions used for *Chromaticity Diagram* bounds. chromaticity_diagram_callable : callable, optional Callable responsible for drawing the *Chromaticity Diagram*. method : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, *Chromaticity Diagram* method. show_whitepoints : bool, optional Whether to display the *RGB* colourspaces whitepoints. show_pointer_gamut : bool, optional Whether to display the *Pointer's Gamut*. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.plot_pointer_gamut`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_RGB_colourspaces_in_chromaticity_diagram( ... ['ITU-R BT.709', 'ACEScg', 'S-Gamut']) ... # doctest: +SKIP .. image:: ../_static/Plotting_\ Plot_RGB_Colourspaces_In_Chromaticity_Diagram.png :align: center :alt: plot_RGB_colourspaces_in_chromaticity_diagram """ if colourspaces is None: colourspaces = ['ITU-R BT.709', 'ACEScg', 'S-Gamut'] colourspaces = filter_RGB_colourspaces(colourspaces).values() settings = {'uniform': True} settings.update(kwargs) _figure, axes = artist(**settings) method = method.upper() cmfs = first_item(filter_cmfs(cmfs).values()) title = '{0}\n{1} - {2} Chromaticity Diagram'.format( ', '.join([colourspace.name for colourspace in colourspaces]), cmfs.name, method) settings = {'axes': axes, 'title': title, 'method': method} settings.update(kwargs) settings['standalone'] = False chromaticity_diagram_callable(**settings) if show_pointer_gamut: settings = {'axes': axes, 'method': method} settings.update(kwargs) settings['standalone'] = False plot_pointer_gamut(**settings) if method == 'CIE 1931': def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy x_limit_min, x_limit_max = [-0.1], [0.9] y_limit_min, y_limit_max = [-0.1], [0.9] elif method == 'CIE 1960 UCS': def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy_to_UCS_uv(xy) x_limit_min, x_limit_max = [-0.1], [0.7] y_limit_min, y_limit_max = [-0.2], [0.6] elif method == 'CIE 1976 UCS': def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy_to_Luv_uv(xy) x_limit_min, x_limit_max = [-0.1], [0.7] y_limit_min, y_limit_max = [-0.1], [0.7] else: raise ValueError( 'Invalid method: "{0}", must be one of ' '{{\'CIE 1931\', \'CIE 1960 UCS\', \'CIE 1976 UCS\'}}'.format( method)) settings = {'colour_cycle_count': len(colourspaces)} settings.update(kwargs) cycle = colour_cycle(**settings) for colourspace in colourspaces: R, G, B, _A = next(cycle) # RGB colourspaces such as *ACES2065-1* have primaries with # chromaticity coordinates set to 0 thus we prevent nan from being # yield by zero division in later colour transformations. P = np.where( colourspace.primaries == 0, EPSILON, colourspace.primaries, ) P = xy_to_ij(P) W = xy_to_ij(colourspace.whitepoint) axes.plot( (W[0], W[0]), (W[1], W[1]), color=(R, G, B), label=colourspace.name) if show_whitepoints: axes.plot((W[0], W[0]), (W[1], W[1]), 'o', color=(R, G, B)) axes.plot( (P[0, 0], P[1, 0]), (P[0, 1], P[1, 1]), 'o-', color=(R, G, B)) axes.plot( (P[1, 0], P[2, 0]), (P[1, 1], P[2, 1]), 'o-', color=(R, G, B)) axes.plot( (P[2, 0], P[0, 0]), (P[2, 1], P[0, 1]), 'o-', color=(R, G, B)) x_limit_min.append(np.amin(P[..., 0]) - 0.1) y_limit_min.append(np.amin(P[..., 1]) - 0.1) x_limit_max.append(np.amax(P[..., 0]) + 0.1) y_limit_max.append(np.amax(P[..., 1]) + 0.1) bounding_box = ( min(x_limit_min), max(x_limit_max), min(y_limit_min), max(y_limit_max), ) settings.update({ 'standalone': True, 'legend': True, 'bounding_box': bounding_box, }) settings.update(kwargs) return render(**settings)
[docs]@override_style() def plot_RGB_colourspaces_in_chromaticity_diagram_CIE1931( colourspaces=None, cmfs='CIE 1931 2 Degree Standard Observer', chromaticity_diagram_callable_CIE1931=( plot_chromaticity_diagram_CIE1931), **kwargs): """ Plots given *RGB* colourspaces in the *CIE 1931 Chromaticity Diagram*. Parameters ---------- colourspaces : array_like, optional *RGB* colourspaces to plot. cmfs : unicode, optional Standard observer colour matching functions used for *Chromaticity Diagram* bounds. chromaticity_diagram_callable_CIE1931 : callable, optional Callable responsible for drawing the *CIE 1931 Chromaticity Diagram*. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_RGB_colourspaces_in_chromaticity_diagram_CIE1931( ... ['ITU-R BT.709', 'ACEScg', 'S-Gamut']) ... # doctest: +SKIP .. image:: ../_static/Plotting_\ Plot_RGB_Colourspaces_In_Chromaticity_Diagram_CIE1931.png :align: center :alt: plot_RGB_colourspaces_in_chromaticity_diagram_CIE1931 """ settings = dict(kwargs) settings.update({'method': 'CIE 1931'}) return plot_RGB_colourspaces_in_chromaticity_diagram( colourspaces, cmfs, chromaticity_diagram_callable_CIE1931, **settings)
[docs]@override_style() def plot_RGB_colourspaces_in_chromaticity_diagram_CIE1960UCS( colourspaces=None, cmfs='CIE 1931 2 Degree Standard Observer', chromaticity_diagram_callable_CIE1960UCS=( plot_chromaticity_diagram_CIE1960UCS), **kwargs): """ Plots given *RGB* colourspaces in the *CIE 1960 UCS Chromaticity Diagram*. Parameters ---------- colourspaces : array_like, optional *RGB* colourspaces to plot. cmfs : unicode, optional Standard observer colour matching functions used for *Chromaticity Diagram* bounds. chromaticity_diagram_callable_CIE1960UCS : callable, optional Callable responsible for drawing the *CIE 1960 UCS Chromaticity Diagram*. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_RGB_colourspaces_in_chromaticity_diagram_CIE1960UCS(( ... ['ITU-R BT.709', 'ACEScg', 'S-Gamut']) ... # doctest: +SKIP .. image:: ../_static/Plotting_\ Plot_RGB_Colourspaces_In_Chromaticity_Diagram_CIE1960UCS.png :align: center :alt: plot_RGB_colourspaces_in_chromaticity_diagram_CIE1960UCS """ settings = dict(kwargs) settings.update({'method': 'CIE 1960 UCS'}) return plot_RGB_colourspaces_in_chromaticity_diagram( colourspaces, cmfs, chromaticity_diagram_callable_CIE1960UCS, **settings)
[docs]@override_style() def plot_RGB_colourspaces_in_chromaticity_diagram_CIE1976UCS( colourspaces=None, cmfs='CIE 1931 2 Degree Standard Observer', chromaticity_diagram_callable_CIE1976UCS=( plot_chromaticity_diagram_CIE1976UCS), **kwargs): """ Plots given *RGB* colourspaces in the *CIE 1976 UCS Chromaticity Diagram*. Parameters ---------- colourspaces : array_like, optional *RGB* colourspaces to plot. cmfs : unicode, optional Standard observer colour matching functions used for *Chromaticity Diagram* bounds. chromaticity_diagram_callable_CIE1976UCS : callable, optional Callable responsible for drawing the *CIE 1976 UCS Chromaticity Diagram*. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_RGB_colourspaces_in_chromaticity_diagram_CIE1976UCS(( ... ['ITU-R BT.709', 'ACEScg', 'S-Gamut']) ... # doctest: +SKIP .. image:: ../_static/Plotting_\ Plot_RGB_Colourspaces_In_Chromaticity_Diagram_CIE1976UCS.png :align: center :alt: plot_RGB_colourspaces_in_chromaticity_diagram_CIE1976UCS """ settings = dict(kwargs) settings.update({'method': 'CIE 1976 UCS'}) return plot_RGB_colourspaces_in_chromaticity_diagram( colourspaces, cmfs, chromaticity_diagram_callable_CIE1976UCS, **settings)
[docs]@override_style() def plot_RGB_chromaticities_in_chromaticity_diagram( RGB, colourspace='sRGB', chromaticity_diagram_callable=( plot_RGB_colourspaces_in_chromaticity_diagram), method='CIE 1931', scatter_parameters=None, **kwargs): """ Plots given *RGB* colourspace array in the *Chromaticity Diagram* according to given method. Parameters ---------- RGB : array_like *RGB* colourspace array. colourspace : optional, unicode *RGB* colourspace of the *RGB* array. chromaticity_diagram_callable : callable, optional Callable responsible for drawing the *Chromaticity Diagram*. method : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, *Chromaticity Diagram* method. scatter_parameters : dict, optional Parameters for the :func:`plt.scatter` definition, if ``c`` is set to *RGB*, the scatter will use given ``RGB`` colours. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.diagrams.\ plot_RGB_colourspaces_in_chromaticity_diagram`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> RGB = np.random.random((128, 128, 3)) >>> plot_RGB_chromaticities_in_chromaticity_diagram( ... RGB, 'ITU-R BT.709') ... # doctest: +SKIP .. image:: ../_static/Plotting_\ Plot_RGB_Chromaticities_In_Chromaticity_Diagram_Plot.png :align: center :alt: plot_RGB_chromaticities_in_chromaticity_diagram """ RGB = as_float_array(RGB).reshape(-1, 3) settings = {'uniform': True} settings.update(kwargs) _figure, axes = artist(**settings) method = method.upper() scatter_settings = { 's': 40, 'c': 'RGB', 'marker': 'o', 'alpha': 0.85, } if scatter_parameters is not None: scatter_settings.update(scatter_parameters) settings = dict(kwargs) settings.update({'axes': axes, 'standalone': False}) colourspace = first_item(filter_RGB_colourspaces(colourspace).values()) settings['colourspaces'] = ( ['^{0}$'.format(colourspace.name)] + settings.get('colourspaces', [])) chromaticity_diagram_callable(**settings) use_RGB_colours = scatter_settings['c'].upper() == 'RGB' if use_RGB_colours: RGB = RGB[RGB[:, 1].argsort()] scatter_settings['c'] = np.clip( RGB_to_RGB( RGB, colourspace, COLOUR_STYLE_CONSTANTS.colour.colourspace, apply_encoding_cctf=True).reshape(-1, 3), 0, 1) XYZ = RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix) if method == 'CIE 1931': ij = XYZ_to_xy(XYZ, colourspace.whitepoint) elif method == 'CIE 1960 UCS': ij = UCS_to_uv(XYZ_to_UCS(XYZ)) elif method == 'CIE 1976 UCS': ij = Luv_to_uv( XYZ_to_Luv(XYZ, colourspace.whitepoint), colourspace.whitepoint) axes.scatter(ij[..., 0], ij[..., 1], **scatter_settings) settings.update({'standalone': True}) settings.update(kwargs) return render(**settings)
[docs]@override_style() def plot_RGB_chromaticities_in_chromaticity_diagram_CIE1931( RGB, colourspace='sRGB', chromaticity_diagram_callable_CIE1931=( plot_RGB_colourspaces_in_chromaticity_diagram_CIE1931), scatter_parameters=None, **kwargs): """ Plots given *RGB* colourspace array in the *CIE 1931 Chromaticity Diagram*. Parameters ---------- RGB : array_like *RGB* colourspace array. colourspace : optional, unicode *RGB* colourspace of the *RGB* array. chromaticity_diagram_callable_CIE1931 : callable, optional Callable responsible for drawing the *CIE 1931 Chromaticity Diagram*. scatter_parameters : dict, optional Parameters for the :func:`plt.scatter` definition, if ``c`` is set to *RGB*, the scatter will use given ``RGB`` colours. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.diagrams.\ plot_RGB_colourspaces_in_chromaticity_diagram`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> RGB = np.random.random((128, 128, 3)) >>> plot_RGB_chromaticities_in_chromaticity_diagram_CIE1931( ... RGB, 'ITU-R BT.709') ... # doctest: +SKIP .. image:: ../_static/Plotting_\ Plot_RGB_Chromaticities_In_Chromaticity_Diagram_CIE1931.png :align: center :alt: plot_RGB_chromaticities_in_chromaticity_diagram_CIE1931 """ settings = dict(kwargs) settings.update({'method': 'CIE 1931'}) return plot_RGB_chromaticities_in_chromaticity_diagram( RGB, colourspace, chromaticity_diagram_callable_CIE1931, scatter_parameters=scatter_parameters, **settings)
[docs]@override_style() def plot_RGB_chromaticities_in_chromaticity_diagram_CIE1960UCS( RGB, colourspace='sRGB', chromaticity_diagram_callable_CIE1960UCS=( plot_RGB_colourspaces_in_chromaticity_diagram_CIE1960UCS), scatter_parameters=None, **kwargs): """ Plots given *RGB* colourspace array in the *CIE 1960 UCS Chromaticity Diagram*. Parameters ---------- RGB : array_like *RGB* colourspace array. colourspace : optional, unicode *RGB* colourspace of the *RGB* array. chromaticity_diagram_callable_CIE1960UCS : callable, optional Callable responsible for drawing the *CIE 1960 UCS Chromaticity Diagram*. scatter_parameters : dict, optional Parameters for the :func:`plt.scatter` definition, if ``c`` is set to *RGB*, the scatter will use given ``RGB`` colours. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.diagrams.\ plot_RGB_colourspaces_in_chromaticity_diagram`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> RGB = np.random.random((128, 128, 3)) >>> plot_RGB_chromaticities_in_chromaticity_diagram_CIE1960UCS( ... RGB, 'ITU-R BT.709') ... # doctest: +SKIP .. image:: ../_static/Plotting_\ Plot_RGB_Chromaticities_In_Chromaticity_Diagram_CIE1960UCS.png :align: center :alt: plot_RGB_chromaticities_in_chromaticity_diagram_CIE1960UCS """ settings = dict(kwargs) settings.update({'method': 'CIE 1960 UCS'}) return plot_RGB_chromaticities_in_chromaticity_diagram( RGB, colourspace, chromaticity_diagram_callable_CIE1960UCS, scatter_parameters=scatter_parameters, **settings)
[docs]@override_style() def plot_RGB_chromaticities_in_chromaticity_diagram_CIE1976UCS( RGB, colourspace='sRGB', chromaticity_diagram_callable_CIE1976UCS=( plot_RGB_colourspaces_in_chromaticity_diagram_CIE1976UCS), scatter_parameters=None, **kwargs): """ Plots given *RGB* colourspace array in the *CIE 1976 UCS Chromaticity Diagram*. Parameters ---------- RGB : array_like *RGB* colourspace array. colourspace : optional, unicode *RGB* colourspace of the *RGB* array. chromaticity_diagram_callable_CIE1976UCS : callable, optional Callable responsible for drawing the *CIE 1976 UCS Chromaticity Diagram*. scatter_parameters : dict, optional Parameters for the :func:`plt.scatter` definition, if ``c`` is set to *RGB*, the scatter will use given ``RGB`` colours. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.diagrams.\ plot_RGB_colourspaces_in_chromaticity_diagram`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> RGB = np.random.random((128, 128, 3)) >>> plot_RGB_chromaticities_in_chromaticity_diagram_CIE1976UCS( ... RGB, 'ITU-R BT.709') ... # doctest: +SKIP .. image:: ../_static/Plotting_\ Plot_RGB_Chromaticities_In_Chromaticity_Diagram_CIE1976UCS.png :align: center :alt: plot_RGB_chromaticities_in_chromaticity_diagram_CIE1976UCS """ settings = dict(kwargs) settings.update({'method': 'CIE 1976 UCS'}) return plot_RGB_chromaticities_in_chromaticity_diagram( RGB, colourspace, chromaticity_diagram_callable_CIE1976UCS, scatter_parameters=scatter_parameters, **settings)
def ellipses_MacAdam1942(method='CIE 1931'): """ Returns *MacAdam (1942) Ellipses (Observer PGN)* coefficients according to given method. Parameters ---------- method : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, Computation method. Returns ------- tuple Current figure and axes. Examples -------- >>> ellipses_MacAdam1942()[0] # doctest: +SKIP array([ 1.60000000e-01, 5.70000000e-02, 5.00000023e-03, 1.56666660e-02, -2.77000015e+01]) """ method = method.upper() if method == 'CIE 1931': def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy elif method == 'CIE 1960 UCS': def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy_to_UCS_uv(xy) elif method == 'CIE 1976 UCS': def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy_to_Luv_uv(xy) else: raise ValueError( 'Invalid method: "{0}", must be one of ' '{{\'CIE 1931\', \'CIE 1960 UCS\', \'CIE 1976 UCS\'}}'.format( method)) x, y, _a, _b, _theta, a, b, theta = tsplit(MACADAM_1942_ELLIPSES_DATA) ellipses_coefficients = [] # pylint: disable=C0200 for i in range(len(theta)): xy = point_at_angle_on_ellipse( np.linspace(0, 360, 36), [x[i], y[i], a[i] / 60, b[i] / 60, theta[i]], ) ij = xy_to_ij(xy) ellipses_coefficients.append( ellipse_coefficients_canonical_form(ellipse_fitting(ij))) return ellipses_coefficients @override_style() def plot_ellipses_MacAdam1942_in_chromaticity_diagram( chromaticity_diagram_callable=plot_chromaticity_diagram, method='CIE 1931', chromaticity_diagram_clipping=False, ellipse_parameters=None, **kwargs): """ Plots *MacAdam (1942) Ellipses (Observer PGN)* in the *Chromaticity Diagram* according to given method. Parameters ---------- chromaticity_diagram_callable : callable, optional Callable responsible for drawing the *Chromaticity Diagram*. method : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, *Chromaticity Diagram* method. chromaticity_diagram_clipping : bool, optional, Whether to clip the *Chromaticity Diagram* colours with the ellipses. ellipse_parameters : dict or array_like, optional Parameters for the :class:`Ellipse` class, ``ellipse_parameters`` can be either a single dictionary applied to all the ellipses with same settings or a sequence of dictionaries with different settings for each ellipse. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_ellipses_MacAdam1942_in_chromaticity_diagram() # doctest: +SKIP .. image:: ../_static/\ Plotting_Plot_Ellipses_MacAdam1942_In_Chromaticity_Diagram.png :align: center :alt: plot_ellipses_MacAdam1942_in_chromaticity_diagram """ settings = {'uniform': True} settings.update(kwargs) _figure, axes = artist(**settings) settings = dict(kwargs) settings.update({'axes': axes, 'standalone': False}) ellipses_coefficients = ellipses_MacAdam1942(method=method) if chromaticity_diagram_clipping: diagram_clipping_path_x = [] diagram_clipping_path_y = [] for coefficients in ellipses_coefficients: coefficients = np.copy(coefficients) coefficients[2:4] /= 2 x, y = tsplit( point_at_angle_on_ellipse( np.linspace(0, 360, 36), coefficients, )) diagram_clipping_path_x.append(x) diagram_clipping_path_y.append(y) diagram_clipping_path = np.rollaxis( np.array([diagram_clipping_path_x, diagram_clipping_path_y]), 0, 3) diagram_clipping_path = Path.make_compound_path_from_polys( diagram_clipping_path).vertices settings.update({'diagram_clipping_path': diagram_clipping_path}) chromaticity_diagram_callable(**settings) ellipse_settings_collection = [{ 'color': COLOUR_STYLE_CONSTANTS.colour.cycle[4], 'alpha': 0.4, 'edgecolor': COLOUR_STYLE_CONSTANTS.colour.cycle[1], 'linewidth': colour_style()['lines.linewidth'] } for _ellipses_coefficient in ellipses_coefficients] if ellipse_parameters is not None: if not isinstance(ellipse_parameters, dict): assert len(ellipse_parameters) == len(ellipses_coefficients), ( 'Multiple ellipse parameters defined, but they do not match ' 'the ellipses count!') for i, ellipse_settings in enumerate(ellipse_settings_collection): if isinstance(ellipse_parameters, dict): ellipse_settings.update(ellipse_parameters) else: ellipse_settings.update(ellipse_parameters[i]) for i, coefficients in enumerate(ellipses_coefficients): x_c, y_c, a_a, a_b, theta_e = coefficients ellipse = Ellipse((x_c, y_c), a_a, a_b, theta_e, **ellipse_settings_collection[i]) axes.add_artist(ellipse) settings.update({'standalone': True}) settings.update(kwargs) return render(**settings)
[docs]@override_style() def plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1931( chromaticity_diagram_callable_CIE1931=( plot_chromaticity_diagram_CIE1931), chromaticity_diagram_clipping=False, ellipse_parameters=None, **kwargs): """ Plots *MacAdam (1942) Ellipses (Observer PGN)* in the *CIE 1931 Chromaticity Diagram*. Parameters ---------- chromaticity_diagram_callable_CIE1931 : callable, optional Callable responsible for drawing the *CIE 1931 Chromaticity Diagram*. chromaticity_diagram_clipping : bool, optional, Whether to clip the *CIE 1931 Chromaticity Diagram* colours with the ellipses. ellipse_parameters : dict or array_like, optional Parameters for the :class:`Ellipse` class, ``ellipse_parameters`` can be either a single dictionary applied to all the ellipses with same settings or a sequence of dictionaries with different settings for each ellipse. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.models.\ plot_ellipses_MacAdam1942_in_chromaticity_diagram`}, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1931() ... # doctest: +SKIP .. image:: ../_static/\ Plotting_Plot_Ellipses_MacAdam1942_In_Chromaticity_Diagram_CIE1931.png :align: center :alt: plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1931 """ settings = dict(kwargs) settings.update({'method': 'CIE 1931'}) return plot_ellipses_MacAdam1942_in_chromaticity_diagram( chromaticity_diagram_callable_CIE1931, chromaticity_diagram_clipping=chromaticity_diagram_clipping, ellipse_parameters=ellipse_parameters, **settings)
[docs]@override_style() def plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1960UCS( chromaticity_diagram_callable_CIE1960UCS=( plot_chromaticity_diagram_CIE1960UCS), chromaticity_diagram_clipping=False, ellipse_parameters=None, **kwargs): """ Plots *MacAdam (1942) Ellipses (Observer PGN)* in the *CIE 1960 UCS Chromaticity Diagram*. Parameters ---------- chromaticity_diagram_callable_CIE1960UCS : callable, optional Callable responsible for drawing the *CIE 1960 UCS Chromaticity Diagram*. chromaticity_diagram_clipping : bool, optional, Whether to clip the *CIE 1960 UCS Chromaticity Diagram* colours with the ellipses. ellipse_parameters : dict or array_like, optional Parameters for the :class:`Ellipse` class, ``ellipse_parameters`` can be either a single dictionary applied to all the ellipses with same settings or a sequence of dictionaries with different settings for each ellipse. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.models.\ plot_ellipses_MacAdam1942_in_chromaticity_diagram`}, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1960UCS() ... # doctest: +SKIP .. image:: ../_static/\ Plotting_Plot_Ellipses_MacAdam1942_In_Chromaticity_Diagram_CIE1960UCS.png :align: center :alt: plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1960UCS """ settings = dict(kwargs) settings.update({'method': 'CIE 1960 UCS'}) return plot_ellipses_MacAdam1942_in_chromaticity_diagram( chromaticity_diagram_callable_CIE1960UCS, chromaticity_diagram_clipping=chromaticity_diagram_clipping, ellipse_parameters=ellipse_parameters, **settings)
[docs]@override_style() def plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1976UCS( chromaticity_diagram_callable_CIE1976UCS=( plot_chromaticity_diagram_CIE1976UCS), chromaticity_diagram_clipping=False, ellipse_parameters=None, **kwargs): """ Plots *MacAdam (1942) Ellipses (Observer PGN)* in the *CIE 1976 UCS Chromaticity Diagram*. Parameters ---------- chromaticity_diagram_callable_CIE1976UCS : callable, optional Callable responsible for drawing the *CIE 1976 UCS Chromaticity Diagram*. chromaticity_diagram_clipping : bool, optional, Whether to clip the *CIE 1976 UCS Chromaticity Diagram* colours with the ellipses. ellipse_parameters : dict or array_like, optional Parameters for the :class:`Ellipse` class, ``ellipse_parameters`` can be either a single dictionary applied to all the ellipses with same settings or a sequence of dictionaries with different settings for each ellipse. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.models.\ plot_ellipses_MacAdam1942_in_chromaticity_diagram`}, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1976UCS() ... # doctest: +SKIP .. image:: ../_static/\ Plotting_Plot_Ellipses_MacAdam1942_In_Chromaticity_Diagram_CIE1976UCS.png :align: center :alt: plot_ellipses_MacAdam1942_in_chromaticity_diagram_CIE1976UCS """ settings = dict(kwargs) settings.update({'method': 'CIE 1976 UCS'}) return plot_ellipses_MacAdam1942_in_chromaticity_diagram( chromaticity_diagram_callable_CIE1976UCS, chromaticity_diagram_clipping=chromaticity_diagram_clipping, ellipse_parameters=ellipse_parameters, **settings)
[docs]@override_style() def plot_single_cctf(cctf='ITU-R BT.709', decoding_cctf=False, **kwargs): """ Plots given colourspace colour component transfer function. Parameters ---------- cctf : unicode, optional Colour component transfer function to plot. decoding_cctf : bool Plot the decoding colour component transfer function instead. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.plot_multi_functions`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_single_cctf('ITU-R BT.709') # doctest: +SKIP .. image:: ../_static/Plotting_Plot_Single_CCTF.png :align: center :alt: plot_single_cctf """ settings = { 'title': '{0} - {1} CCTF'.format( cctf, 'Decoding' if decoding_cctf else 'Encoding') } settings.update(kwargs) return plot_multi_cctfs([cctf], decoding_cctf, **settings)
[docs]@override_style() def plot_multi_cctfs(cctfs=None, decoding_cctf=False, **kwargs): """ Plots given colour component transfer functions. Parameters ---------- cctfs : array_like, optional Colour component transfer function to plot. decoding_cctf : bool Plot the decoding colour component transfer function instead. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.plot_multi_functions`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_multi_cctfs(['ITU-R BT.709', 'sRGB']) # doctest: +SKIP .. image:: ../_static/Plotting_Plot_Multi_CCTFs.png :align: center :alt: plot_multi_cctfs """ if cctfs is None: cctfs = ('ITU-R BT.709', 'sRGB') cctfs = filter_passthrough( DECODING_CCTFS if decoding_cctf else ENCODING_CCTFS, cctfs) mode = 'Decoding' if decoding_cctf else 'Encoding' title = '{0} - {1} CCTFs'.format(', '.join([cctf for cctf in cctfs]), mode) settings = { 'bounding_box': (0, 1, 0, 1), 'legend': True, 'title': title, 'x_label': 'Signal Value' if decoding_cctf else 'Tristimulus Value', 'y_label': 'Tristimulus Value' if decoding_cctf else 'Signal Value', } settings.update(kwargs) with domain_range_scale(1): return plot_multi_functions(cctfs, **settings)