def single_cmfs_plot(cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given colour matching functions. Parameters ---------- cmfs : unicode, optional Colour matching functions to plot. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> single_cmfs_plot() # doctest: +SKIP True """ cmfs = get_cmfs(cmfs) settings = { 'title': '{0} - Colour Matching Functions'.format(cmfs.title)} settings.update(kwargs) return multi_cmfs_plot((cmfs.name, ), **settings)
def single_cmfs_plot(cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given colour matching functions. Parameters ---------- cmfs : unicode, optional Colour matching functions to plot. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> single_cmfs_plot() # doctest: +SKIP """ cmfs = get_cmfs(cmfs) settings = {'title': '{0} - Colour Matching Functions'.format(cmfs.title)} settings.update(kwargs) return multi_cmfs_plot((cmfs.name, ), **settings)
def single_cmfs_plot(cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given colour matching functions. Parameters ---------- cmfs : unicode, optional Colour matching functions to plot. Other Parameters ---------------- \**kwargs : dict, optional {:func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definition. Returns ------- Figure Current figure or None. Examples -------- >>> single_cmfs_plot() # doctest: +SKIP """ cmfs = get_cmfs(cmfs) settings = { 'title': '{0} - Colour Matching Functions'.format(cmfs.strict_name) } settings.update(kwargs) return multi_cmfs_plot((cmfs.name, ), **settings)
def single_illuminant_relative_spd_plot( illuminant='A', cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given single illuminant relative spectral power distribution. Parameters ---------- illuminant : unicode, optional Factory illuminant to plot. cmfs : unicode, optional Standard observer colour matching functions to plot. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> single_illuminant_relative_spd_plot() # doctest: +SKIP """ cmfs = get_cmfs(cmfs) title = 'Illuminant {0} - {1}'.format(illuminant, cmfs.title) illuminant = get_illuminant(illuminant) settings = {'title': title, 'y_label': 'Relative Power'} settings.update(kwargs) return single_spd_plot(illuminant, **settings)
def single_rayleigh_scattering_spd_plot( CO2_concentration=STANDARD_CO2_CONCENTRATION, temperature=STANDARD_AIR_TEMPERATURE, pressure=AVERAGE_PRESSURE_MEAN_SEA_LEVEL, latitude=DEFAULT_LATITUDE, altitude=DEFAULT_ALTITUDE, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots a single *Rayleigh* scattering spectral power distribution. Parameters ---------- CO2_concentration : numeric, optional :math:`CO_2` concentration in parts per million (ppm). temperature : numeric, optional Air temperature :math:`T[K]` in kelvin degrees. pressure : numeric Surface pressure :math:`P` of the measurement site. latitude : numeric, optional Latitude of the site in degrees. altitude : numeric, optional Altitude of the site in meters. cmfs : unicode, optional Standard observer colour matching functions. Other Parameters ---------------- \**kwargs : dict, optional {:func:`boundaries`, :func:`canvas`, :func:`decorate`, :func:`display`}, Please refer to the documentation of the previously listed definitions. out_of_gamut_clipping : bool, optional {:func:`single_spd_plot`}, Whether to clip out of gamut colours otherwise, the colours will be offset by the absolute minimal colour leading to a rendering on gray background, less saturated and smoother. [1]_ Returns ------- Figure Current figure or None. Examples -------- >>> single_rayleigh_scattering_spd_plot() # doctest: +SKIP """ title = 'Rayleigh Scattering' cmfs = get_cmfs(cmfs) settings = {'title': title, 'y_label': 'Optical Depth'} settings.update(kwargs) spd = rayleigh_scattering_spd(cmfs.shape, CO2_concentration, temperature, pressure, latitude, altitude) return single_spd_plot(spd, **settings)
def chromaticity_diagram_colours_CIE1976UCS( samples=4096, cmfs='CIE 1931 2 Degree Standard Observer', antialiasing=True): """ Plots the *CIE 1976 UCS Chromaticity Diagram* colours. Parameters ---------- samples : numeric, optional Samples count on one axis. cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. antialiasing : bool, optional Whether to apply anti-aliasing to the image. Other Parameters ---------------- \**kwargs : dict, optional {:func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definition. Returns ------- Figure Current figure or None. Examples -------- >>> chromaticity_diagram_colours_CIE1976UCS() # doctest: +SKIP """ cmfs = get_cmfs(cmfs) illuminant = DEFAULT_PLOTTING_ILLUMINANT triangulation = Delaunay(Luv_to_uv(XYZ_to_Luv(cmfs.values, illuminant), illuminant), qhull_options='Qu QJ') xx, yy = np.meshgrid(np.linspace(0, 1, samples), np.linspace(1, 0, samples)) xy = tstack((xx, yy)) mask = (triangulation.find_simplex(xy) < 0).astype(DEFAULT_FLOAT_DTYPE) if antialiasing: kernel = np.array([ [0, 1, 0], [1, 2, 1], [0, 1, 0], ]).astype(DEFAULT_FLOAT_DTYPE) kernel /= np.sum(kernel) mask = convolve(mask, kernel) mask = 1 - mask[:, :, np.newaxis] XYZ = xy_to_XYZ(Luv_uv_to_xy(xy)) RGB = normalise_maximum(XYZ_to_sRGB(XYZ, illuminant), axis=-1) return np.dstack([RGB, mask])
def chromaticity_diagram_construction_visual( cmfs='CIE 1931 2 Degree Standard Observer', width=2.0, method='gl', parent=None): """ Returns a :class:`vispy.scene.visuals.Node` class instance representing the chromaticity diagram construction with the spectral locus. Parameters ---------- cmfs : unicode, optional Standard observer colour matching functions used to draw the spectral locus. width : numeric, optional Line width. method : unicode, optional **{'gl', 'agg'}**, Line drawing method. parent : Node, optional Parent of the spectral locus visual in the `SceneGraph`. Returns ------- Node Chromaticity diagram construction visual. """ from colour_analysis.visuals import Primitive node = Node(parent=parent) simplex_p = np.array([(1, 0, 0), (0, 1, 0), (0, 0, 1)]) simplex_f = np.array([(0, 1, 2)]) simplex_c = np.array([(1, 1, 1), (1, 1, 1), (1, 1, 1)]) Primitive(simplex_p, simplex_f, uniform_opacity=0.5, vertex_colours=simplex_c, parent=node) simplex_f = np.array([(0, 1, 2), (1, 2, 0), (2, 0, 1)]) Primitive(simplex_p, simplex_f, uniform_opacity=1.0, vertex_colours=simplex_c, wireframe=True, parent=node) lines = [] for XYZ in get_cmfs(cmfs).values: lines.append(XYZ * 1.75) lines.append((0, 0, 0)) lines = np.array(lines) Line(lines, (0, 0, 0), width=width, method=method, parent=node) return node
def chromaticity_diagram_visual( samples=256, cmfs='CIE 1931 2 Degree Standard Observer', transformation='CIE 1931', parent=None): """ Creates a chromaticity diagram visual based on :class:`colour_analysis.visuals.Primitive` class. Parameters ---------- samples : int, optional Inner samples count used to construct the chromaticity diagram triangulation. cmfs : unicode, optional Standard observer colour matching functions used for the chromaticity diagram boundaries. transformation : unicode, optional {'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'} Chromaticity diagram transformation. parent : Node, optional Parent of the chromaticity diagram in the `SceneGraph`. Returns ------- Primitive Chromaticity diagram visual. """ cmfs = get_cmfs(cmfs) illuminant = DEFAULT_PLOTTING_ILLUMINANT XYZ_to_ij = ( CHROMATICITY_DIAGRAM_TRANSFORMATIONS[transformation]['XYZ_to_ij']) ij_to_XYZ = ( CHROMATICITY_DIAGRAM_TRANSFORMATIONS[transformation]['ij_to_XYZ']) ij_c = XYZ_to_ij(cmfs.values, illuminant) triangulation = Delaunay(ij_c, qhull_options='QJ') samples = np.linspace(0, 1, samples) ii, jj = np.meshgrid(samples, samples) ij = tstack((ii, jj)) ij = np.vstack((ij_c, ij[triangulation.find_simplex(ij) > 0])) ij_p = np.hstack((ij, np.full((ij.shape[0], 1), 0))) triangulation = Delaunay(ij, qhull_options='QJ') RGB = normalise(XYZ_to_sRGB(ij_to_XYZ(ij, illuminant), illuminant), axis=-1) diagram = Primitive(vertices=ij_p, faces=triangulation.simplices, vertex_colours=RGB, parent=parent) return diagram
def spds_CIE_1976_UCS_chromaticity_diagram_plot( spds, cmfs='CIE 1931 2 Degree Standard Observer', annotate=True, **kwargs): """ Plots given spectral power distribution chromaticity coordinates into the *CIE 1976 UCS Chromaticity Diagram*. Parameters ---------- spds : list, optional Spectral power distributions to plot. cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. annotate : bool Should resulting chromaticity coordinates annotated with their respective spectral power distribution names. \*\*kwargs : \*\* Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> from colour import ILLUMINANTS_RELATIVE_SPDS >>> A = ILLUMINANTS_RELATIVE_SPDS['A'] >>> D65 = ILLUMINANTS_RELATIVE_SPDS['D65'] >>> spds_CIE_1976_UCS_chromaticity_diagram_plot([A, D65]) # doctest: +SKIP True """ CIE_1976_UCS_chromaticity_diagram_plot(standalone=False, **kwargs) cmfs = get_cmfs(cmfs) cmfs_shape = cmfs.shape for spd in spds: spd = spd.clone().align(cmfs_shape) XYZ = spectral_to_XYZ(spd) / 100 uv = Luv_to_uv(XYZ_to_Luv(XYZ)) pylab.plot(uv[0], uv[1], 'o', color='white') if spd.name is not None and annotate: pylab.annotate(spd.name, xy=uv, xytext=(50, 30), textcoords='offset points', arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=0.2')) display(standalone=True)
def chromaticity_diagram_visual(samples=256, cmfs='CIE 1931 2 Degree Standard Observer', transformation='CIE 1931', parent=None): """ Creates a chromaticity diagram visual based on :class:`colour_analysis.visuals.Primitive` class. Parameters ---------- samples : int, optional Inner samples count used to construct the chromaticity diagram triangulation. cmfs : unicode, optional Standard observer colour matching functions used for the chromaticity diagram boundaries. transformation : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, Chromaticity diagram transformation. parent : Node, optional Parent of the chromaticity diagram in the `SceneGraph`. Returns ------- Primitive Chromaticity diagram visual. """ cmfs = get_cmfs(cmfs) illuminant = DEFAULT_PLOTTING_ILLUMINANT XYZ_to_ij = ( CHROMATICITY_DIAGRAM_TRANSFORMATIONS[transformation]['XYZ_to_ij']) ij_to_XYZ = ( CHROMATICITY_DIAGRAM_TRANSFORMATIONS[transformation]['ij_to_XYZ']) ij_c = XYZ_to_ij(cmfs.values, illuminant) triangulation = Delaunay(ij_c, qhull_options='QJ') samples = np.linspace(0, 1, samples) ii, jj = np.meshgrid(samples, samples) ij = tstack((ii, jj)) ij = np.vstack((ij_c, ij[triangulation.find_simplex(ij) > 0])) ij_p = np.hstack((ij, np.full((ij.shape[0], 1), 0, DEFAULT_FLOAT_DTYPE))) triangulation = Delaunay(ij, qhull_options='QJ') RGB = normalise_maximum( XYZ_to_sRGB(ij_to_XYZ(ij, illuminant), illuminant), axis=-1) diagram = Primitive( vertices=ij_p, faces=triangulation.simplices, vertex_colours=RGB, parent=parent) return diagram
def visible_spectrum_plot(cmfs='CIE 1931 2 Degree Standard Observer', out_of_gamut_clipping=True, **kwargs): """ Plots the visible colours spectrum using given standard observer *CIE XYZ* colour matching functions. Parameters ---------- cmfs : unicode, optional Standard observer colour matching functions used for spectrum creation. out_of_gamut_clipping : bool, optional Out of gamut colours will be clipped if *True* otherwise, the colours will be offset by the absolute minimal colour leading to a rendering on gray background, less saturated and smoother. [1]_ \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> visible_spectrum_plot() # doctest: +SKIP """ cmfs = get_cmfs(cmfs) cmfs = cmfs.clone().align(DEFAULT_SPECTRAL_SHAPE) wavelengths = cmfs.shape.range() colours = XYZ_to_sRGB( wavelength_to_XYZ(wavelengths, cmfs), ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['E'], apply_encoding_cctf=False) if not out_of_gamut_clipping: colours += np.abs(np.min(colours)) colours = DEFAULT_PLOTTING_ENCODING_CCTF(normalise_maximum(colours)) settings = { 'title': 'The Visible Spectrum - {0}'.format(cmfs.title), 'x_label': 'Wavelength $\\lambda$ (nm)', 'y_label': False, 'x_tighten': True, 'y_ticker': False } settings.update(kwargs) return colour_parameters_plot([ ColourParameter(x=x[0], RGB=x[1]) for x in tuple(zip(wavelengths, colours)) ], **settings)
def single_rayleigh_scattering_spd_plot( CO2_concentration=STANDARD_CO2_CONCENTRATION, temperature=STANDARD_AIR_TEMPERATURE, pressure=AVERAGE_PRESSURE_MEAN_SEA_LEVEL, latitude=DEFAULT_LATITUDE, altitude=DEFAULT_ALTITUDE, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots a single rayleigh scattering spectral power distribution. Parameters ---------- CO2_concentration : numeric, optional :math:`CO_2` concentration in parts per million (ppm). temperature : numeric, optional Air temperature :math:`T[K]` in kelvin degrees. pressure : numeric Surface pressure :math:`P` of the measurement site. latitude : numeric, optional Latitude of the site in degrees. altitude : numeric, optional Altitude of the site in meters. cmfs : unicode, optional Standard observer colour matching functions. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> single_rayleigh_scattering_spd_plot() # doctest: +SKIP True """ title = 'Rayleigh Scattering' cmfs = get_cmfs(cmfs) settings = { 'title': title, 'y_label': 'Optical Depth'} settings.update(kwargs) spd = rayleigh_scattering_spd(cmfs.shape, CO2_concentration, temperature, pressure, latitude, altitude) return single_spd_plot(spd, **settings)
def single_rayleigh_scattering_spd_plot( CO2_concentration=STANDARD_CO2_CONCENTRATION, temperature=STANDARD_AIR_TEMPERATURE, pressure=AVERAGE_PRESSURE_MEAN_SEA_LEVEL, latitude=DEFAULT_LATITUDE, altitude=DEFAULT_ALTITUDE, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots a single rayleigh scattering spectral power distribution. Parameters ---------- CO2_concentration : numeric, optional :math:`CO_2` concentration in parts per million (ppm). temperature : numeric, optional Air temperature :math:`T[K]` in kelvin degrees. pressure : numeric Surface pressure :math:`P` of the measurement site. latitude : numeric, optional Latitude of the site in degrees. altitude : numeric, optional Altitude of the site in meters. cmfs : unicode, optional Standard observer colour matching functions. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> single_rayleigh_scattering_spd_plot() # doctest: +SKIP """ title = 'Rayleigh Scattering' cmfs = get_cmfs(cmfs) settings = { 'title': title, 'y_label': 'Optical Depth'} settings.update(kwargs) spd = rayleigh_scattering_spd(cmfs.shape, CO2_concentration, temperature, pressure, latitude, altitude) return single_spd_plot(spd, **settings)
def visible_spectrum_plot(cmfs='CIE 1931 2 Degree Standard Observer', out_of_gamut_clipping=True, **kwargs): """ Plots the visible colours spectrum using given standard observer *CIE XYZ* colour matching functions. Parameters ---------- cmfs : unicode, optional Standard observer colour matching functions used for spectrum creation. out_of_gamut_clipping : bool, optional Out of gamut colours will be clipped if *True* otherwise, the colours will be offset by the absolute minimal colour leading to a rendering on gray background, less saturated and smoother. [1]_ \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> visible_spectrum_plot() # doctest: +SKIP """ cmfs = get_cmfs(cmfs) cmfs = cmfs.clone().align(DEFAULT_SPECTRAL_SHAPE) wavelengths = cmfs.shape.range() colours = XYZ_to_sRGB( wavelength_to_XYZ(wavelengths, cmfs), ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['E'], apply_encoding_cctf=False) if not out_of_gamut_clipping: colours += np.abs(np.min(colours)) colours = DEFAULT_PLOTTING_ENCODING_CCTF(normalise_maximum(colours)) settings = { 'title': 'The Visible Spectrum - {0}'.format(cmfs.title), 'x_label': 'Wavelength $\\lambda$ (nm)', 'y_label': False, 'x_tighten': True, 'y_ticker': False} settings.update(kwargs) return colour_parameters_plot([ColourParameter(x=x[0], RGB=x[1]) for x in tuple(zip(wavelengths, colours))], **settings)
def visible_spectrum_plot(cmfs='CIE 1931 2 Degree Standard Observer', out_of_gamut_clipping=True, **kwargs): """ Plots the visible colours spectrum using given standard observer *CIE XYZ* colour matching functions. Parameters ---------- cmfs : unicode, optional Standard observer colour matching functions used for spectrum creation. out_of_gamut_clipping : bool, optional Whether to clip out of gamut colours otherwise, the colours will be offset by the absolute minimal colour leading to a rendering on gray background, less saturated and smoother. Other Parameters ---------------- \**kwargs : dict, optional {:func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definition. Returns ------- Figure Current figure or None. References ---------- - :cite:`Spiker2015a` Examples -------- >>> visible_spectrum_plot() # doctest: +SKIP """ settings = {'y_label': None, 'y_ticker': False, 'standalone': False} single_spd_plot(ones_spd(DEFAULT_SPECTRAL_SHAPE), cmfs=cmfs, out_of_gamut_clipping=out_of_gamut_clipping, **settings) cmfs = get_cmfs(cmfs) settings = { 'title': 'The Visible Spectrum - {0}'.format(cmfs.strict_name), 'x_label': 'Wavelength $\\lambda$ (nm)', 'standalone': True } settings.update(kwargs) return render(**settings)
def blackbody_colours_plot(shape=SpectralShape(150, 12500, 50), cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots blackbody colours. Parameters ---------- shape : SpectralShape, optional Spectral shape to use as plot boundaries. cmfs : unicode, optional Standard observer colour matching functions. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> blackbody_colours_plot() # doctest: +SKIP True """ cmfs = get_cmfs(cmfs) colours = [] temperatures = [] for temperature in shape: spd = blackbody_spd(temperature, cmfs.shape) XYZ = spectral_to_XYZ(spd, cmfs) RGB = normalise(XYZ_to_sRGB(XYZ / 100)) colours.append(RGB) temperatures.append(temperature) settings = { 'title': 'Blackbody Colours', 'x_label': 'Temperature K', 'y_label': '', 'x_tighten': True, 'y_ticker': False } settings.update(kwargs) return colour_parameters_plot([ ColourParameter(x=x[0], RGB=x[1]) for x in tuple(zip(temperatures, colours)) ], **settings)
def blackbody_colours_plot(shape=SpectralShape(150, 12500, 50), cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots blackbody colours. Parameters ---------- shape : SpectralShape, optional Spectral shape to use as plot boundaries. cmfs : unicode, optional Standard observer colour matching functions. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> blackbody_colours_plot() # doctest: +SKIP True """ cmfs = get_cmfs(cmfs) colours = [] temperatures = [] for temperature in shape: spd = blackbody_spd(temperature, cmfs.shape) XYZ = spectral_to_XYZ(spd, cmfs) RGB = normalise(XYZ_to_sRGB(XYZ / 100)) colours.append(RGB) temperatures.append(temperature) settings = { 'title': 'Blackbody Colours', 'x_label': 'Temperature K', 'y_label': '', 'x_tighten': True, 'y_ticker': False} settings.update(kwargs) return colour_parameters_plot([ColourParameter(x=x[0], RGB=x[1]) for x in tuple(zip(temperatures, colours))], **settings)
def single_illuminant_relative_spd_plot( illuminant='A', cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given single illuminant relative spectral power distribution. Parameters ---------- illuminant : unicode, optional Factory illuminant to plot. cmfs : unicode, optional Standard observer colour matching functions to plot. Other Parameters ---------------- \**kwargs : dict, optional {:func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definition. out_of_gamut_clipping : bool, optional {:func:`colour.plotting.single_spd_plot`}, Whether to clip out of gamut colours otherwise, the colours will be offset by the absolute minimal colour leading to a rendering on gray background, less saturated and smoother. Returns ------- Figure Current figure or None. References ---------- - :cite:`Spiker2015a` Examples -------- >>> single_illuminant_relative_spd_plot() # doctest: +SKIP """ cmfs = get_cmfs(cmfs) title = 'Illuminant {0} - {1}'.format(illuminant, cmfs.strict_name) illuminant = get_illuminant(illuminant) settings = {'title': title, 'y_label': 'Relative Power'} settings.update(kwargs) return single_spd_plot(illuminant, **settings)
def single_illuminant_relative_spd_plot( illuminant='A', cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given single illuminant relative spectral power distribution. Parameters ---------- illuminant : unicode, optional Factory illuminant to plot. cmfs : unicode, optional Standard observer colour matching functions to plot. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> single_illuminant_relative_spd_plot() # doctest: +SKIP True """ cmfs = get_cmfs(cmfs) title = 'Illuminant {0} - {1}'.format(illuminant, cmfs.title) illuminant = get_illuminant(illuminant) settings = { 'title': title, 'y_label': 'Relative Spectral Power Distribution'} settings.update(kwargs) return single_spd_plot(illuminant, **settings)
def RGB_colourspaces_CIE_1976_UCS_chromaticity_diagram_plot( colourspaces=None, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given *RGB* colourspaces in *CIE 1976 UCS Chromaticity Diagram*. Parameters ---------- colourspaces : array_like, optional *RGB* colourspaces to plot. cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> c = ['Rec. 709', 'ACEScg', 'S-Gamut'] >>> RGB_colourspaces_CIE_1976_UCS_chromaticity_diagram_plot( ... c) # doctest: +SKIP True """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) if colourspaces is None: colourspaces = ('Rec. 709', 'ACEScg', 'S-Gamut', 'Pointer Gamut') cmfs, name = get_cmfs(cmfs), cmfs illuminant = DEFAULT_PLOTTING_ILLUMINANT settings = { 'title': '{0} - {1} - CIE 1976 UCS Chromaticity Diagram'.format( ', '.join(colourspaces), name), 'standalone': False} settings.update(kwargs) CIE_1976_UCS_chromaticity_diagram_plot(**settings) x_limit_min, x_limit_max = [-0.1], [0.7] y_limit_min, y_limit_max = [-0.1], [0.7] settings = {'colour_cycle_map': 'rainbow', 'colour_cycle_count': len(colourspaces)} settings.update(kwargs) cycle = colour_cycle(**settings) for colourspace in colourspaces: if colourspace == 'Pointer Gamut': uv = Luv_to_uv(XYZ_to_Luv(xy_to_XYZ( POINTER_GAMUT_BOUNDARIES), illuminant), illuminant) alpha_p, colour_p = 0.85, '0.95' pylab.plot(uv[..., 0], uv[..., 1], label='Pointer\'s Gamut', color=colour_p, alpha=alpha_p, linewidth=2) pylab.plot((uv[-1][0], uv[0][0]), (uv[-1][1], uv[0][1]), color=colour_p, alpha=alpha_p, linewidth=2) XYZ = Lab_to_XYZ(LCHab_to_Lab(POINTER_GAMUT_DATA), POINTER_GAMUT_ILLUMINANT) uv = Luv_to_uv(XYZ_to_Luv(XYZ, illuminant), illuminant) pylab.scatter(uv[..., 0], uv[..., 1], alpha=alpha_p / 2, color=colour_p, marker='+') else: colourspace, name = get_RGB_colourspace(colourspace), colourspace 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. primaries = np.where(colourspace.primaries == 0, EPSILON, colourspace.primaries) primaries = Luv_to_uv(XYZ_to_Luv(xy_to_XYZ( primaries), illuminant), illuminant) whitepoint = Luv_to_uv(XYZ_to_Luv(xy_to_XYZ( colourspace.whitepoint), illuminant), illuminant) 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]) - 0.1) y_limit_min.append(np.amin(primaries[..., 1]) - 0.1) x_limit_max.append(np.amax(primaries[..., 0]) + 0.1) y_limit_max.append(np.amax(primaries[..., 1]) + 0.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)), 'standalone': True}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def CIE_1931_chromaticity_diagram_plot( cmfs='CIE 1931 2 Degree Standard Observer', show_diagram_colours=True, **kwargs): """ Plots the *CIE 1931 Chromaticity Diagram*. Parameters ---------- cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. show_diagram_colours : bool, optional Display the chromaticity diagram background colours. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> CIE_1931_chromaticity_diagram_plot() # doctest: +SKIP """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) cmfs = get_cmfs(cmfs) illuminant = DEFAULT_PLOTTING_ILLUMINANT if show_diagram_colours: image = matplotlib.image.imread( os.path.join(PLOTTING_RESOURCES_DIRECTORY, 'CIE_1931_Chromaticity_Diagram_{0}.png'.format( cmfs.name.replace(' ', '_')))) pylab.imshow(image, interpolation=None, 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) xy = XYZ_to_xy(cmfs.values, illuminant) wavelengths_chromaticity_coordinates = dict(tuple(zip(wavelengths, xy))) pylab.plot(xy[..., 0], xy[..., 1], color='black', linewidth=2) pylab.plot((xy[-1][0], xy[0][0]), (xy[-1][1], xy[0][1]), 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]) xy = np.array([x, y]) direction = np.array([-dy, dx]) normal = (np.array([-dy, dx]) if np.dot(normalise_vector(xy - equal_energy), normalise_vector(direction)) > 0 else np.array([dy, -dx])) normal = normalise_vector(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, color='black', clip_on=True, ha='left' if normal[0] >= 0 else 'right', va='center', fontdict={'size': 'small'}) ticks = np.arange(-10, 10, 0.1) pylab.xticks(ticks) pylab.yticks(ticks) settings.update({ 'title': 'CIE 1931 Chromaticity Diagram - {0}'.format(cmfs.title), 'x_label': 'CIE x', 'y_label': 'CIE y', 'grid': True, 'bounding_box': (0, 1, 0, 1)}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def CIE_1960_UCS_chromaticity_diagram_plot( cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots the *CIE 1960 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_1960_UCS_chromaticity_diagram_plot() # doctest: +SKIP True """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) cmfs = get_cmfs(cmfs) image = matplotlib.image.imread( os.path.join(PLOTTING_RESOURCES_DIRECTORY, 'CIE_1960_UCS_Chromaticity_Diagram_{0}_Large.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) uv = np.array([UCS_to_uv(XYZ_to_UCS(XYZ)) for XYZ in cmfs.values]) wavelengths_chromaticity_coordinates = dict(tuple(zip(wavelengths, uv))) pylab.plot(uv[:, 0], uv[:, 1], color='black', linewidth=2) pylab.plot((uv[-1][0], uv[0][0]), (uv[-1][1], uv[0][1]), 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.update({ 'title': 'CIE 1960 UCS Chromaticity Diagram - {0}'.format(cmfs.title), 'x_label': 'CIE u', 'y_label': 'CIE v', 'x_ticker': True, 'y_ticker': True, 'grid': True, 'bounding_box': [-0.075, 0.675, -0.15, 0.6], 'bbox_inches': 'tight', 'pad_inches': 0}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
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 """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) cmfs = get_cmfs(cmfs) illuminant = CHROMATICITY_DIAGRAM_DEFAULT_ILLUMINANT image = matplotlib.image.imread( os.path.join(PLOTTING_RESOURCES_DIRECTORY, 'CIE_1931_Chromaticity_Diagram_{0}.png'.format( cmfs.name.replace(' ', '_')))) pylab.imshow(image, interpolation=None, 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) xy = XYZ_to_xy(cmfs.values, illuminant) wavelengths_chromaticity_coordinates = dict(tuple(zip(wavelengths, xy))) pylab.plot(xy[..., 0], xy[..., 1], color='black', linewidth=2) pylab.plot((xy[-1][0], xy[0][0]), (xy[-1][1], xy[0][1]), 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'}) ticks = np.arange(-10, 10, 0.1) pylab.xticks(ticks) pylab.yticks(ticks) settings.update({ 'title': 'CIE 1931 Chromaticity Diagram - {0}'.format(cmfs.title), 'x_label': 'CIE x', 'y_label': 'CIE y', 'x_ticker': True, 'y_ticker': True, 'grid': True, 'bounding_box': (0, 1, 0, 1), 'bbox_inches': 'tight', 'pad_inches': 0}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def multi_cmfs_plot(cmfs=None, **kwargs): """ Plots given colour matching functions. Parameters ---------- cmfs : array_like, optional Colour matching functions to plot. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> cmfs = [ ... 'CIE 1931 2 Degree Standard Observer', ... 'CIE 1964 10 Degree Standard Observer'] >>> multi_cmfs_plot(cmfs) # doctest: +SKIP True """ canvas(**kwargs) if cmfs is None: cmfs = ('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_i in enumerate(cmfs): cmfs_i = get_cmfs(cmfs_i) rgb = [reduce(lambda y, _: y * 0.5, range(i), x) # noqa for x in rgb] wavelengths, values = tuple( zip(*[(key, value) for key, value in getattr(cmfs_i, axis)])) shape = cmfs_i.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_i.labels.get(axis), cmfs_i.title), linewidth=2) settings = { 'title': '{0} - Colour Matching Functions'.format(', '.join( [get_cmfs(c).title for c in cmfs])), 'x_label': 'Wavelength $\\lambda$ (nm)', 'y_label': 'Tristimulus Values', 'x_tighten': True, 'legend': True, 'legend_location': 'upper right', '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) boundaries(**settings) decorate(**settings) return display(**settings)
def blackbody_colours_plot(shape=SpectralShape(150, 12500, 50), cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots blackbody colours. Parameters ---------- shape : SpectralShape, optional Spectral shape to use as plot boundaries. cmfs : unicode, optional Standard observer colour matching functions. Other Parameters ---------------- \**kwargs : dict, optional {:func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definition. Returns ------- Figure Current figure or None. Examples -------- >>> blackbody_colours_plot() # doctest: +SKIP """ axes = canvas(**kwargs).gca() cmfs = get_cmfs(cmfs) colours = [] temperatures = [] with suppress_warnings(): for temperature in shape: spd = blackbody_spd(temperature, cmfs.shape) XYZ = spectral_to_XYZ(spd, cmfs) RGB = normalise_maximum(XYZ_to_sRGB(XYZ / 100)) colours.append(RGB) temperatures.append(temperature) x_min, x_max = min(temperatures), max(temperatures) y_min, y_max = 0, 1 axes.bar(x=temperatures, height=1, width=shape.interval, color=colours, align='edge') settings = { 'title': 'Blackbody Colours', 'x_label': 'Temperature K', 'y_label': None, 'limits': (x_min, x_max, y_min, y_max), 'x_tighten': True, 'y_tighten': True, 'y_ticker': False } settings.update(kwargs) return render(**settings)
def RGB_colourspaces_gamuts_plot(colourspaces=None, reference_colourspace='CIE xyY', segments=8, display_grid=True, grid_segments=10, spectral_locus=False, spectral_locus_colour=None, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given *RGB* colourspaces gamuts in given reference colourspace. Parameters ---------- colourspaces : array_like, optional *RGB* colourspaces to plot the gamuts. reference_colourspace : unicode, optional **{'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW', 'IPT'}**, Reference colourspace to plot the gamuts into. segments : int, optional Edge segments count for each *RGB* colourspace cubes. display_grid : bool, optional Display a grid at the bottom of the *RGB* colourspace cubes. grid_segments : bool, optional Edge segments count for the grid. spectral_locus : bool, optional Is spectral locus line plotted. spectral_locus_colour : array_like, optional Spectral locus line colour. cmfs : unicode, optional Standard observer colour matching functions used for spectral locus. \**kwargs : dict, optional **{'face_colours', 'edge_colours', 'edge_alpha', 'face_alpha'}**, Arguments for each given colourspace where each key has an array_like value such as: ``{ 'face_colours': (None, (0.5, 0.5, 1.0)), 'edge_colours': (None, (0.5, 0.5, 1.0)), 'edge_alpha': (0.5, 1.0), 'face_alpha': (0.0, 1.0)}`` **{'grid_face_colours', 'grid_edge_colours', 'grid_face_alpha', 'grid_edge_alpha', 'x_axis_colour', 'y_axis_colour', 'x_ticks_colour', 'y_ticks_colour', 'x_label_colour', 'y_label_colour', 'ticks_and_label_location'}**, Arguments for the nadir grid such as ``{'grid_face_colours': (0.25, 0.25, 0.25), 'grid_edge_colours': (0.50, 0.50, 0.50), 'grid_face_alpha': 0.1, 'grid_edge_alpha': 0.5, 'x_axis_colour': (0.0, 0.0, 0.0, 1.0), 'y_axis_colour': (0.0, 0.0, 0.0, 1.0), 'x_ticks_colour': (0.0, 0.0, 0.0, 0.85), 'y_ticks_colour': (0.0, 0.0, 0.0, 0.85), 'x_label_colour': (0.0, 0.0, 0.0, 0.85), 'y_label_colour': (0.0, 0.0, 0.0, 0.85), 'ticks_and_label_location': ('-x', '-y')}`` Returns ------- bool Definition success. Examples -------- >>> c = ['Rec. 709', 'ACEScg', 'S-Gamut'] >>> RGB_colourspaces_gamuts_plot(c) # doctest: +SKIP True """ if colourspaces is None: colourspaces = ('Rec. 709', 'ACEScg') count_c = len(colourspaces) settings = Structure( **{'face_colours': [None] * count_c, 'edge_colours': [None] * count_c, 'face_alpha': [1] * count_c, 'edge_alpha': [1] * count_c, 'title': '{0} - {1} Reference Colourspace'.format( ', '.join(colourspaces), reference_colourspace)}) settings.update(kwargs) figure = matplotlib.pyplot.figure() axes = figure.add_subplot(111, projection='3d') illuminant = DEFAULT_PLOTTING_ILLUMINANT points = np.zeros((4, 3)) if spectral_locus: cmfs = get_cmfs(cmfs) XYZ = cmfs.values points = XYZ_to_reference_colourspace(XYZ, illuminant, reference_colourspace) points[np.isnan(points)] = 0 c = ((0.0, 0.0, 0.0, 0.5) if spectral_locus_colour is None else spectral_locus_colour) pylab.plot(points[..., 0], points[..., 1], points[..., 2], color=c, linewidth=2, zorder=1) pylab.plot((points[-1][0], points[0][0]), (points[-1][1], points[0][1]), (points[-1][2], points[0][2]), color=c, linewidth=2, zorder=1) quads, RGB_f, RGB_e = [], [], [] for i, colourspace in enumerate(colourspaces): colourspace = get_RGB_colourspace(colourspace) quads_c, RGB = RGB_identity_cube(width_segments=segments, height_segments=segments, depth_segments=segments) XYZ = RGB_to_XYZ( quads_c, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix) quads.extend(XYZ_to_reference_colourspace(XYZ, colourspace.whitepoint, reference_colourspace)) if settings.face_colours[i] is not None: RGB = np.ones(RGB.shape) * settings.face_colours[i] RGB_f.extend(np.hstack( (RGB, np.full((RGB.shape[0], 1, np.float_), settings.face_alpha[i])))) if settings.edge_colours[i] is not None: RGB = np.ones(RGB.shape) * settings.edge_colours[i] RGB_e.extend(np.hstack( (RGB, np.full((RGB.shape[0], 1, np.float_), settings.edge_alpha[i])))) quads = np.asarray(quads) quads[np.isnan(quads)] = 0 if quads.size != 0: for i, axis in enumerate('xyz'): min_a = np.min(np.vstack((quads[..., i], points[..., i]))) max_a = np.max(np.vstack((quads[..., i], points[..., i]))) getattr(axes, 'set_{}lim'.format(axis))((min_a, max_a)) labels = REFERENCE_COLOURSPACES_TO_LABELS[reference_colourspace] for i, axis in enumerate('xyz'): getattr(axes, 'set_{}label'.format(axis))(labels[i]) if display_grid: if reference_colourspace == 'CIE Lab': limits = np.array([[-450, 450], [-450, 450]]) elif reference_colourspace == 'CIE Luv': limits = np.array([[-650, 650], [-650, 650]]) elif reference_colourspace == 'CIE UVW': limits = np.array([[-850, 850], [-850, 850]]) else: limits = np.array([[-1.5, 1.5], [-1.5, 1.5]]) quads_g, RGB_gf, RGB_ge = nadir_grid( limits, grid_segments, labels, axes, **settings) quads = np.vstack((quads_g, quads)) RGB_f = np.vstack((RGB_gf, RGB_f)) RGB_e = np.vstack((RGB_ge, RGB_e)) collection = Poly3DCollection(quads) collection.set_facecolors(RGB_f) collection.set_edgecolors(RGB_e) axes.add_collection3d(collection) settings.update({ 'camera_aspect': 'equal', 'no_axes3d': True}) settings.update(kwargs) camera(**settings) decorate(**settings) return display(**settings)
def multi_spd_plot(spds, cmfs='CIE 1931 2 Degree Standard Observer', use_spds_colours=False, normalise_spds_colours=False, **kwargs): """ Plots given spectral power distributions. Parameters ---------- spds : list Spectral power distributions to plot. cmfs : unicode, optional Standard observer colour matching functions used for spectrum creation. use_spds_colours : bool, optional Use spectral power distributions colours. normalise_spds_colours : bool Should spectral power distributions colours normalised. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> from colour import SpectralPowerDistribution >>> data1 = {400: 0.0641, 420: 0.0645, 440: 0.0562} >>> data2 = {400: 0.134, 420: 0.789, 440: 1.289} >>> spd1 = SpectralPowerDistribution('Custom1', data1) >>> spd2 = SpectralPowerDistribution('Custom2', data2) >>> multi_spd_plot([spd1, spd2]) # doctest: +SKIP True """ canvas(**kwargs) cmfs = get_cmfs(cmfs) if use_spds_colours: illuminant = ILLUMINANTS_RELATIVE_SPDS.get('D65') x_limit_min, x_limit_max, y_limit_min, y_limit_max = [], [], [], [] for spd in spds: wavelengths, values = tuple(zip(*spd.items)) shape = spd.shape x_limit_min.append(shape.start) x_limit_max.append(shape.end) y_limit_min.append(min(values)) y_limit_max.append(max(values)) if use_spds_colours: XYZ = spectral_to_XYZ(spd, cmfs, illuminant) / 100 if normalise_spds_colours: XYZ = normalise(XYZ, clip=False) RGB = np.clip(XYZ_to_sRGB(XYZ), 0, 1) pylab.plot(wavelengths, values, color=RGB, label=spd.title, linewidth=2) else: pylab.plot(wavelengths, values, label=spd.title, linewidth=2) settings = { 'x_label': 'Wavelength $\\lambda$ (nm)', 'y_label': 'Spectral Power Distribution', 'x_tighten': True, 'legend': True, 'legend_location': 'upper left', 'limits': (min(x_limit_min), max(x_limit_max), min(y_limit_min), max(y_limit_max))} settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def RGB_colourspaces_CIE_1976_UCS_chromaticity_diagram_plot( colourspaces=None, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given *RGB* colourspaces in *CIE 1976 UCS Chromaticity Diagram*. Parameters ---------- colourspaces : array_like, optional *RGB* colourspaces to plot. cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. Other Parameters ---------------- \**kwargs : dict, optional {:func:`boundaries`, :func:`canvas`, :func:`decorate`, :func:`display`}, Please refer to the documentation of the previously listed definitions. show_diagram_colours : bool, optional {:func:`CIE_1976_UCS_chromaticity_diagram_plot`}, Whether to display the chromaticity diagram background colours. Returns ------- Figure Current figure or None. Examples -------- >>> c = ['Rec. 709', 'ACEScg', 'S-Gamut'] >>> RGB_colourspaces_CIE_1976_UCS_chromaticity_diagram_plot( ... c) # doctest: +SKIP """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) if colourspaces is None: colourspaces = ('Rec. 709', 'ACEScg', 'S-Gamut', 'Pointer Gamut') cmfs, name = get_cmfs(cmfs), cmfs illuminant = DEFAULT_PLOTTING_ILLUMINANT settings = { 'title': '{0} - {1} - CIE 1976 UCS Chromaticity Diagram'.format( ', '.join(colourspaces), name), 'standalone': False } settings.update(kwargs) CIE_1976_UCS_chromaticity_diagram_plot(**settings) x_limit_min, x_limit_max = [-0.1], [0.7] y_limit_min, y_limit_max = [-0.1], [0.7] settings = { 'colour_cycle_map': 'rainbow', 'colour_cycle_count': len(colourspaces) } settings.update(kwargs) cycle = colour_cycle(**settings) for colourspace in colourspaces: if colourspace == 'Pointer Gamut': uv = Luv_to_uv( XYZ_to_Luv(xy_to_XYZ(POINTER_GAMUT_BOUNDARIES), illuminant), illuminant) alpha_p, colour_p = 0.85, '0.95' pylab.plot(uv[..., 0], uv[..., 1], label='Pointer\'s Gamut', color=colour_p, alpha=alpha_p, linewidth=2) pylab.plot((uv[-1][0], uv[0][0]), (uv[-1][1], uv[0][1]), color=colour_p, alpha=alpha_p, linewidth=2) XYZ = Lab_to_XYZ(LCHab_to_Lab(POINTER_GAMUT_DATA), POINTER_GAMUT_ILLUMINANT) uv = Luv_to_uv(XYZ_to_Luv(XYZ, illuminant), illuminant) pylab.scatter(uv[..., 0], uv[..., 1], alpha=alpha_p / 2, color=colour_p, marker='+') else: colourspace, name = get_RGB_colourspace(colourspace), colourspace 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 = Luv_to_uv(XYZ_to_Luv(xy_to_XYZ(P), illuminant), illuminant) W = Luv_to_uv( XYZ_to_Luv(xy_to_XYZ(colourspace.whitepoint), illuminant), illuminant) pylab.plot((W[0], W[0]), (W[1], W[1]), color=(r, g, b), label=colourspace.name, linewidth=2) pylab.plot((W[0], W[0]), (W[1], W[1]), 'o', color=(r, g, b), linewidth=2) pylab.plot((P[0, 0], P[1, 0]), (P[0, 1], P[1, 1]), 'o-', color=(r, g, b), linewidth=2) pylab.plot((P[1, 0], P[2, 0]), (P[1, 1], P[2, 1]), 'o-', color=(r, g, b), linewidth=2) pylab.plot((P[2, 0], P[0, 0]), (P[2, 1], P[0, 1]), 'o-', color=(r, g, b), linewidth=2) 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) 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)), 'standalone': True }) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def single_spd_plot(spd, cmfs='CIE 1931 2 Degree Standard Observer', out_of_gamut_clipping=True, **kwargs): """ Plots given spectral power distribution. Parameters ---------- spd : SpectralPowerDistribution Spectral power distribution to plot. out_of_gamut_clipping : bool, optional Out of gamut colours will be clipped if *True* otherwise, the colours will be offset by the absolute minimal colour leading to a rendering on gray background, less saturated and smoother. [1]_ cmfs : unicode Standard observer colour matching functions used for spectrum creation. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> from colour import SpectralPowerDistribution >>> data = {400: 0.0641, 420: 0.0645, 440: 0.0562} >>> spd = SpectralPowerDistribution('Custom', data) >>> single_spd_plot(spd) # doctest: +SKIP """ cmfs = get_cmfs(cmfs) shape = cmfs.shape spd = spd.clone().interpolate(shape, 'Linear') wavelengths = spd.wavelengths values = spd.values y1 = values colours = XYZ_to_sRGB( wavelength_to_XYZ(wavelengths, cmfs), ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['E'], apply_encoding_cctf=False) if not out_of_gamut_clipping: colours += np.abs(np.min(colours)) colours = DEFAULT_PLOTTING_ENCODING_CCTF(normalise_maximum(colours)) settings = { 'title': '{0} - {1}'.format(spd.title, cmfs.title), 'x_label': 'Wavelength $\\lambda$ (nm)', 'y_label': 'Spectral Power Distribution', 'x_tighten': True } settings.update(kwargs) return colour_parameters_plot([ ColourParameter(x=x[0], y1=x[1], RGB=x[2]) for x in tuple(zip(wavelengths, y1, colours)) ], **settings)
def RGB_colourspaces_CIE_1931_chromaticity_diagram_plot( colourspaces=None, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given *RGB* colourspaces in *CIE 1931 Chromaticity Diagram*. Parameters ---------- colourspaces : array_like, optional *RGB* colourspaces to plot. cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> c = ['Rec. 709', 'ACEScg', 'S-Gamut'] >>> RGB_colourspaces_CIE_1931_chromaticity_diagram_plot( ... c) # doctest: +SKIP """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) if colourspaces is None: colourspaces = ('Rec. 709', 'ACEScg', 'S-Gamut', 'Pointer Gamut') cmfs, name = get_cmfs(cmfs), cmfs settings = { 'title': '{0} - {1} - CIE 1931 Chromaticity Diagram'.format( ', '.join(colourspaces), name), 'standalone': False} settings.update(kwargs) CIE_1931_chromaticity_diagram_plot(**settings) x_limit_min, x_limit_max = [-0.1], [0.9] y_limit_min, y_limit_max = [-0.1], [0.9] settings = {'colour_cycle_map': 'rainbow', 'colour_cycle_count': len(colourspaces)} settings.update(kwargs) cycle = colour_cycle(**settings) for colourspace in colourspaces: if colourspace == 'Pointer Gamut': xy = np.asarray(POINTER_GAMUT_BOUNDARIES) alpha_p, colour_p = 0.85, '0.95' pylab.plot(xy[..., 0], xy[..., 1], label='Pointer\'s Gamut', color=colour_p, alpha=alpha_p, linewidth=2) pylab.plot((xy[-1][0], xy[0][0]), (xy[-1][1], xy[0][1]), color=colour_p, alpha=alpha_p, linewidth=2) XYZ = Lab_to_XYZ(LCHab_to_Lab(POINTER_GAMUT_DATA), POINTER_GAMUT_ILLUMINANT) xy = XYZ_to_xy(XYZ, POINTER_GAMUT_ILLUMINANT) pylab.scatter(xy[..., 0], xy[..., 1], alpha=alpha_p / 2, color=colour_p, marker='+') else: colourspace, name = get_RGB_colourspace(colourspace), colourspace r, g, b, _a = next(cycle) 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]) - 0.1) y_limit_min.append(np.amin(primaries[..., 1]) - 0.1) x_limit_max.append(np.amax(primaries[..., 0]) + 0.1) y_limit_max.append(np.amax(primaries[..., 1]) + 0.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)), 'standalone': True}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def single_spd_plot(spd, cmfs='CIE 1931 2 Degree Standard Observer', out_of_gamut_clipping=True, **kwargs): """ Plots given spectral power distribution. Parameters ---------- spd : SpectralPowerDistribution Spectral power distribution to plot. out_of_gamut_clipping : bool, optional Whether to clip out of gamut colours otherwise, the colours will be offset by the absolute minimal colour leading to a rendering on gray background, less saturated and smoother. cmfs : unicode Standard observer colour matching functions used for spectrum creation. Other Parameters ---------------- \**kwargs : dict, optional {:func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definition. Returns ------- Figure Current figure or None. References ---------- - :cite:`Spiker2015a` Examples -------- >>> from colour import SpectralPowerDistribution >>> data = { ... 500: 0.0651, ... 520: 0.0705, ... 540: 0.0772, ... 560: 0.0870, ... 580: 0.1128, ... 600: 0.1360 ... } >>> spd = SpectralPowerDistribution(data, name='Custom') >>> single_spd_plot(spd) # doctest: +SKIP """ axes = canvas(**kwargs).gca() cmfs = get_cmfs(cmfs) spd = spd.copy() spd.interpolator = LinearInterpolator wavelengths = cmfs.wavelengths[np.logical_and( cmfs.wavelengths >= max(min(cmfs.wavelengths), min(spd.wavelengths)), cmfs.wavelengths <= min(max(cmfs.wavelengths), max(spd.wavelengths)), )] values = spd[wavelengths] colours = XYZ_to_sRGB( wavelength_to_XYZ(wavelengths, cmfs), ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['E'], apply_encoding_cctf=False) if not out_of_gamut_clipping: colours += np.abs(np.min(colours)) colours = DEFAULT_PLOTTING_ENCODING_CCTF(normalise_maximum(colours)) x_min, x_max = min(wavelengths), max(wavelengths) y_min, y_max = 0, max(values) polygon = Polygon(np.vstack([ (x_min, 0), tstack((wavelengths, values)), (x_max, 0), ]), facecolor='none', edgecolor='none') axes.add_patch(polygon) axes.bar(x=wavelengths, height=max(values), width=1, color=colours, align='edge', clip_path=polygon) axes.plot(wavelengths, values, color='black', linewidth=1) settings = { 'title': '{0} - {1}'.format(spd.strict_name, cmfs.strict_name), 'x_label': 'Wavelength $\\lambda$ (nm)', 'y_label': 'Spectral Power Distribution', 'limits': (x_min, x_max, y_min, y_max), 'x_tighten': True, 'y_tighten': True } settings.update(kwargs) return render(**settings)
def spectral_locus_visual( reference_colourspace="CIE xyY", cmfs="CIE 1931 2 Degree Standard Observer", width=2.0, uniform_colour=None, uniform_opacity=1.0, method="gl", parent=None, ): """ Returns a :class:`vispy.scene.visuals.Line` class instance representing the spectral locus. Parameters ---------- reference_colourspace : unicode, optional {'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW', 'IPT'} Reference colourspace to use for colour conversions / transformations. cmfs : unicode, optional Standard observer colour matching functions used to draw the spectral locus. width : numeric, optional Line width. edge_size : numeric, optional Symbol edge size. uniform_colour : array_like, optional Uniform symbol colour. uniform_opacity : numeric, optional Uniform symbol opacity. method : unicode, optional {'gl', 'agg'} Line drawing method. parent : Node, optional Parent of the spectral locus visual in the `SceneGraph`. Returns ------- Line Spectral locus visual. """ cmfs = get_cmfs(cmfs) XYZ = cmfs.values XYZ = np.vstack((XYZ, XYZ[0, ...])) illuminant = DEFAULT_PLOTTING_ILLUMINANT points = XYZ_to_reference_colourspace(XYZ, illuminant, reference_colourspace) points[np.isnan(points)] = 0 if uniform_colour is None: RGB = normalise(XYZ_to_sRGB(XYZ, illuminant), axis=-1) RGB = np.hstack((RGB, np.full((RGB.shape[0], 1), uniform_opacity))) else: RGB = ColorArray(uniform_colour, alpha=uniform_opacity).rgba line = Line(points, np.clip(RGB, 0, 1), width=width, method=method, parent=parent) return line
def CIE_1976_UCS_chromaticity_diagram_plot( cmfs='CIE 1931 2 Degree Standard Observer', show_diagram_colours=True, **kwargs): """ Plots the *CIE 1976 UCS Chromaticity Diagram*. Parameters ---------- cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. show_diagram_colours : bool, optional Display the chromaticity diagram background colours. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> CIE_1976_UCS_chromaticity_diagram_plot() # doctest: +SKIP """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) cmfs = get_cmfs(cmfs) illuminant = DEFAULT_PLOTTING_ILLUMINANT if show_diagram_colours: image = matplotlib.image.imread( os.path.join(PLOTTING_RESOURCES_DIRECTORY, 'CIE_1976_UCS_Chromaticity_Diagram_{0}.png'.format( cmfs.name.replace(' ', '_')))) pylab.imshow(image, interpolation=None, 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) uv = Luv_to_uv(XYZ_to_Luv(cmfs.values, illuminant), illuminant) wavelengths_chromaticity_coordinates = dict(zip(wavelengths, uv)) pylab.plot(uv[..., 0], uv[..., 1], color='black', linewidth=2) pylab.plot((uv[-1][0], uv[0][0]), (uv[-1][1], uv[0][1]), 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]) uv = np.array([u, v]) direction = np.array([-dy, dx]) normal = (np.array([-dy, dx]) if np.dot(normalise_vector(uv - equal_energy), normalise_vector(direction)) > 0 else np.array([dy, -dx])) normal = normalise_vector(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, color='black', clip_on=True, ha='left' if normal[0] >= 0 else 'right', va='center', fontdict={'size': 'small'}) ticks = np.arange(-10, 10, 0.1) pylab.xticks(ticks) pylab.yticks(ticks) settings.update({ 'title': 'CIE 1976 UCS Chromaticity Diagram - {0}'.format(cmfs.title), 'x_label': 'CIE u\'', 'y_label': 'CIE v\'', 'grid': True, 'bounding_box': (0, 1, 0, 1)}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
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 : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> blackbody_spectral_radiance_plot() # doctest: +SKIP True """ canvas(**kwargs) cmfs = get_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': 'W / (sr m$^2$) / m', 'standalone': False} settings.update(kwargs) single_spd_plot(spd, cmfs.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(ColourParameter(name='', RGB=RGB), **settings) settings = { 'standalone': True} settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def CIE_1931_chromaticity_diagram_colours_plot( surface=1, samples=4096, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots the *CIE 1931 Chromaticity Diagram* colours. Parameters ---------- surface : numeric, optional Generated markers surface. samples : numeric, optional Samples count on one axis. cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> CIE_1931_chromaticity_diagram_colours_plot() # doctest: +SKIP """ settings = {'figure_size': (64, 64)} settings.update(kwargs) canvas(**settings) cmfs = get_cmfs(cmfs) illuminant = DEFAULT_PLOTTING_ILLUMINANT triangulation = Delaunay(XYZ_to_xy(cmfs.values, illuminant), qhull_options='QJ') xx, yy = np.meshgrid(np.linspace(0, 1, samples), np.linspace(0, 1, samples)) xy = tstack((xx, yy)) xy = xy[triangulation.find_simplex(xy) > 0] XYZ = xy_to_XYZ(xy) RGB = normalise_maximum(XYZ_to_sRGB(XYZ, illuminant), axis=-1) x_dot, y_dot = tsplit(xy) pylab.scatter(x_dot, y_dot, color=RGB, s=surface) settings.update({ 'x_ticker': False, 'y_ticker': False, 'bounding_box': (0, 1, 0, 1)}) settings.update(kwargs) ax = matplotlib.pyplot.gca() matplotlib.pyplot.setp(ax, frame_on=False) boundaries(**settings) decorate(**settings) return display(**settings)
def single_spd_plot(spd, cmfs='CIE 1931 2 Degree Standard Observer', out_of_gamut_clipping=True, **kwargs): """ Plots given spectral power distribution. Parameters ---------- spd : SpectralPowerDistribution Spectral power distribution to plot. out_of_gamut_clipping : bool, optional Out of gamut colours will be clipped if *True* otherwise, the colours will be offset by the absolute minimal colour leading to a rendering on gray background, less saturated and smoother. [1]_ cmfs : unicode Standard observer colour matching functions used for spectrum creation. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> from colour import SpectralPowerDistribution >>> data = {400: 0.0641, 420: 0.0645, 440: 0.0562} >>> spd = SpectralPowerDistribution('Custom', data) >>> single_spd_plot(spd) # doctest: +SKIP True """ cmfs = get_cmfs(cmfs) shape = cmfs.shape spd = spd.clone().interpolate(shape, 'Linear') wavelengths = spd.wavelengths values = spd.values y1 = values colours = XYZ_to_sRGB( wavelength_to_XYZ(wavelengths, cmfs), ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['E'], apply_OECF=False) if not out_of_gamut_clipping: colours += np.abs(np.min(colours)) colours = DEFAULT_PLOTTING_OECF(normalise(colours)) settings = { 'title': '{0} - {1}'.format(spd.title, cmfs.title), 'x_label': 'Wavelength $\\lambda$ (nm)', 'y_label': 'Spectral Power Distribution', 'x_tighten': True} settings.update(kwargs) return colour_parameters_plot( [ColourParameter(x=x[0], y1=x[1], RGB=x[2]) for x in tuple(zip(wavelengths, y1, colours))], **settings)
def multi_cmfs_plot(cmfs=None, **kwargs): """ Plots given colour matching functions. Parameters ---------- cmfs : array_like, optional Colour matching functions to plot. Other Parameters ---------------- \**kwargs : dict, optional {:func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definition. Returns ------- Figure Current figure or None. Examples -------- >>> cmfs = [ ... 'CIE 1931 2 Degree Standard Observer', ... 'CIE 1964 10 Degree Standard Observer'] >>> multi_cmfs_plot(cmfs) # doctest: +SKIP """ canvas(**kwargs) if cmfs is None: cmfs = ('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 i, rgb in enumerate([(1, 0, 0), (0, 1, 0), (0, 0, 1)]): for j, cmfs_i in enumerate(cmfs): cmfs_i = get_cmfs(cmfs_i) rgb = [reduce(lambda y, _: y * 0.5, range(j), x) for x in rgb] values = cmfs_i.values[:, i] shape = cmfs_i.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(cmfs_i.wavelengths, values, color=rgb, label=u'{0} - {1}'.format(cmfs_i.labels[i], cmfs_i.strict_name), linewidth=1) settings = { 'title': '{0} - Colour Matching Functions'.format(', '.join( [get_cmfs(c).strict_name for c in cmfs])), 'x_label': 'Wavelength $\\lambda$ (nm)', 'y_label': 'Tristimulus Values', 'x_tighten': True, 'y_tighten': True, 'legend': True, 'legend_location': 'upper right', '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) return render(**settings)
def RGB_colourspaces_CIE_1960_UCS_chromaticity_diagram_plot( colourspaces=None, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given *RGB* colourspaces in *CIE 1960 UCS Chromaticity Diagram*. Parameters ---------- colourspaces : array_like, optional *RGB* colourspaces to plot. cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> c = ['Rec. 709', 'ACEScg', 'S-Gamut'] >>> RGB_colourspaces_CIE_1960_UCS_chromaticity_diagram_plot( ... c) # doctest: +SKIP True """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) if colourspaces is None: colourspaces = ('Rec. 709', 'ACEScg', 'S-Gamut', 'Pointer Gamut') cmfs, name = get_cmfs(cmfs), cmfs settings = { 'title': '{0} - {1} - CIE 1960 UCS Chromaticity Diagram'.format( ', '.join(colourspaces), name), 'standalone': False} settings.update(kwargs) CIE_1960_UCS_chromaticity_diagram_plot(**settings) x_limit_min, x_limit_max = [-0.1], [0.7] y_limit_min, y_limit_max = [-0.2], [0.6] settings = {'colour_cycle_map': 'rainbow', 'colour_cycle_count': len(colourspaces)} settings.update(kwargs) cycle = colour_cycle(**settings) for colourspace in colourspaces: if colourspace == 'Pointer Gamut': uv = UCS_to_uv(XYZ_to_UCS(xy_to_XYZ(POINTER_GAMUT_BOUNDARIES))) alpha_p, colour_p = 0.85, '0.95' pylab.plot(uv[..., 0], uv[..., 1], label='Pointer\'s Gamut', color=colour_p, alpha=alpha_p, linewidth=2) pylab.plot((uv[-1][0], uv[0][0]), (uv[-1][1], uv[0][1]), color=colour_p, alpha=alpha_p, linewidth=2) XYZ = Lab_to_XYZ(LCHab_to_Lab(POINTER_GAMUT_DATA), POINTER_GAMUT_ILLUMINANT) uv = UCS_to_uv(XYZ_to_UCS(XYZ)) pylab.scatter(uv[..., 0], uv[..., 1], alpha=alpha_p / 2, color=colour_p, marker='+') else: colourspace, name = get_RGB_colourspace(colourspace), colourspace 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. primaries = np.where(colourspace.primaries == 0, EPSILON, colourspace.primaries) primaries = UCS_to_uv(XYZ_to_UCS(xy_to_XYZ(primaries))) whitepoint = UCS_to_uv(XYZ_to_UCS(xy_to_XYZ( 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]) - 0.1) y_limit_min.append(np.amin(primaries[..., 1]) - 0.1) x_limit_max.append(np.amax(primaries[..., 0]) + 0.1) y_limit_max.append(np.amax(primaries[..., 1]) + 0.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)), 'standalone': True}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def CIE_1976_UCS_chromaticity_diagram_plot( cmfs='CIE 1931 2 Degree Standard Observer', show_diagram_colours=True, **kwargs): """ Plots the *CIE 1976 UCS Chromaticity Diagram*. Parameters ---------- cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. show_diagram_colours : bool, optional Whether to display the chromaticity diagram background colours. Other Parameters ---------------- \**kwargs : dict, optional {:func:`boundaries`, :func:`canvas`, :func:`decorate`, :func:`display`}, Please refer to the documentation of the previously listed definitions. Returns ------- Figure Current figure or None. Examples -------- >>> CIE_1976_UCS_chromaticity_diagram_plot() # doctest: +SKIP """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) cmfs = get_cmfs(cmfs) illuminant = DEFAULT_PLOTTING_ILLUMINANT if show_diagram_colours: image = matplotlib.image.imread( os.path.join( PLOTTING_RESOURCES_DIRECTORY, 'CIE_1976_UCS_Chromaticity_Diagram_{0}.png'.format( cmfs.name.replace(' ', '_')))) pylab.imshow(image, interpolation=None, 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) uv = Luv_to_uv(XYZ_to_Luv(cmfs.values, illuminant), illuminant) wavelengths_chromaticity_coordinates = dict(zip(wavelengths, uv)) pylab.plot(uv[..., 0], uv[..., 1], color='black', linewidth=2) pylab.plot((uv[-1][0], uv[0][0]), (uv[-1][1], uv[0][1]), color='black', linewidth=2) for label in labels: u, v = wavelengths_chromaticity_coordinates[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[right][0] - wavelengths_chromaticity_coordinates[left][0]) dy = (wavelengths_chromaticity_coordinates[right][1] - wavelengths_chromaticity_coordinates[left][1]) uv = np.array([u, v]) direction = np.array([-dy, dx]) normal = (np.array([ -dy, dx ]) if np.dot(normalise_vector(uv - equal_energy), normalise_vector(direction)) > 0 else np.array([dy, -dx])) normal = normalise_vector(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, color='black', clip_on=True, ha='left' if normal[0] >= 0 else 'right', va='center', fontdict={'size': 'small'}) ticks = np.arange(-10, 10, 0.1) pylab.xticks(ticks) pylab.yticks(ticks) settings.update({ 'title': 'CIE 1976 UCS Chromaticity Diagram - {0}'.format(cmfs.title), 'x_label': 'CIE u\'', 'y_label': 'CIE v\'', 'grid': True, 'bounding_box': (0, 1, 0, 1) }) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def CIE_1976_UCS_chromaticity_diagram_colours_plot( surface=1.25, spacing=0.00075, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots the *CIE 1976 UCS 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_1976_UCS_chromaticity_diagram_colours_plot() # doctest: +SKIP True """ settings = {'figure_size': (32, 32)} settings.update(kwargs) canvas(**settings) cmfs = get_cmfs(cmfs) illuminant = ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50') uv = np.array([Luv_to_uv(XYZ_to_Luv(XYZ, illuminant)) for XYZ in cmfs.values]) path = matplotlib.path.Path(uv) 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(Luv_uv_to_xy((i, j))) RGB = normalise(XYZ_to_sRGB(XYZ, illuminant)) colours.append(RGB) pylab.scatter(x_dot, y_dot, color=colours, s=surface) settings.update({ 'no_ticks': True, 'bounding_box': [0, 1, 0, 1], 'bbox_inches': 'tight', 'pad_inches': 0}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def multi_spd_plot(spds, cmfs='CIE 1931 2 Degree Standard Observer', use_spds_colours=False, normalise_spds_colours=False, **kwargs): """ Plots given spectral power distributions. Parameters ---------- spds : list Spectral power distributions to plot. cmfs : unicode, optional Standard observer colour matching functions used for spectrum creation. use_spds_colours : bool, optional Use spectral power distributions colours. normalise_spds_colours : bool Should spectral power distributions colours normalised. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> from colour import SpectralPowerDistribution >>> data1 = {400: 0.0641, 420: 0.0645, 440: 0.0562} >>> data2 = {400: 0.134, 420: 0.789, 440: 1.289} >>> spd1 = SpectralPowerDistribution('Custom1', data1) >>> spd2 = SpectralPowerDistribution('Custom2', data2) >>> multi_spd_plot([spd1, spd2]) # doctest: +SKIP """ canvas(**kwargs) cmfs = get_cmfs(cmfs) if use_spds_colours: illuminant = ILLUMINANTS_RELATIVE_SPDS.get('D65') x_limit_min, x_limit_max, y_limit_min, y_limit_max = [], [], [], [] for spd in spds: wavelengths, values = tuple(zip(*spd.items)) shape = spd.shape x_limit_min.append(shape.start) x_limit_max.append(shape.end) y_limit_min.append(min(values)) y_limit_max.append(max(values)) if use_spds_colours: XYZ = spectral_to_XYZ(spd, cmfs, illuminant) / 100 if normalise_spds_colours: XYZ = normalise_maximum(XYZ, clip=False) RGB = np.clip(XYZ_to_sRGB(XYZ), 0, 1) pylab.plot(wavelengths, values, color=RGB, label=spd.title, linewidth=2) else: pylab.plot(wavelengths, values, label=spd.title, linewidth=2) settings = { 'x_label': 'Wavelength $\\lambda$ (nm)', 'y_label': 'Spectral Power Distribution', 'x_tighten': True, 'legend': True, 'legend_location': 'upper left', 'limits': (min(x_limit_min), max(x_limit_max), min(y_limit_min), max(y_limit_max)) } settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def multi_cmfs_plot(cmfs=None, **kwargs): """ Plots given colour matching functions. Parameters ---------- cmfs : array_like, optional Colour matching functions to plot. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> cmfs = [ ... 'CIE 1931 2 Degree Standard Observer', ... 'CIE 1964 10 Degree Standard Observer'] >>> multi_cmfs_plot(cmfs) # doctest: +SKIP """ canvas(**kwargs) if cmfs is None: cmfs = ('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_i in enumerate(cmfs): cmfs_i = get_cmfs(cmfs_i) rgb = [ reduce(lambda y, _: y * 0.5, range(i), x) # noqa for x in rgb ] wavelengths, values = tuple( zip(*[(key, value) for key, value in getattr(cmfs_i, axis)])) shape = cmfs_i.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_i.labels.get(axis), cmfs_i.title), linewidth=2) settings = { 'title': '{0} - Colour Matching Functions'.format(', '.join( [get_cmfs(c).title for c in cmfs])), 'x_label': 'Wavelength $\\lambda$ (nm)', 'y_label': 'Tristimulus Values', 'x_tighten': True, 'legend': True, 'legend_location': 'upper right', '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) boundaries(**settings) decorate(**settings) return display(**settings)
def RGB_colourspaces_gamuts_plot(colourspaces=None, reference_colourspace='CIE xyY', segments=8, display_grid=True, grid_segments=10, spectral_locus=False, spectral_locus_colour=None, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given *RGB* colourspaces gamuts in given reference colourspace. Parameters ---------- colourspaces : array_like, optional *RGB* colourspaces to plot the gamuts. reference_colourspace : unicode, optional **{'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW', 'IPT', 'Hunter Lab', 'Hunter Rdab'}**, Reference colourspace to plot the gamuts into. segments : int, optional Edge segments count for each *RGB* colourspace cubes. display_grid : bool, optional Display a grid at the bottom of the *RGB* colourspace cubes. grid_segments : bool, optional Edge segments count for the grid. spectral_locus : bool, optional Is spectral locus line plotted. spectral_locus_colour : array_like, optional Spectral locus line colour. cmfs : unicode, optional Standard observer colour matching functions used for spectral locus. Other Parameters ---------------- \**kwargs : dict, optional {:func:`nadir_grid`}, Please refer to the documentation of the previously listed definitions. face_colours : array_like, optional Face colours array such as `face_colours = (None, (0.5, 0.5, 1.0))`. edge_colours : array_like, optional Edge colours array such as `edge_colours = (None, (0.5, 0.5, 1.0))`. face_alpha : numeric, optional Face opacity value such as `face_alpha = (0.5, 1.0)`. edge_alpha : numeric, optional Edge opacity value such as `edge_alpha = (0.0, 1.0)`. Returns ------- Figure Current figure or None. Examples -------- >>> c = ['Rec. 709', 'ACEScg', 'S-Gamut'] >>> RGB_colourspaces_gamuts_plot(c) # doctest: +SKIP """ if colourspaces is None: colourspaces = ('Rec. 709', 'ACEScg') count_c = len(colourspaces) settings = Structure( **{ 'face_colours': [None] * count_c, 'edge_colours': [None] * count_c, 'face_alpha': [1] * count_c, 'edge_alpha': [1] * count_c, 'title': '{0} - {1} Reference Colourspace'.format(', '.join(colourspaces), reference_colourspace) }) settings.update(kwargs) figure = matplotlib.pyplot.figure() axes = figure.add_subplot(111, projection='3d') illuminant = DEFAULT_PLOTTING_ILLUMINANT points = np.zeros((4, 3)) if spectral_locus: cmfs = get_cmfs(cmfs) XYZ = cmfs.values points = common_colourspace_model_axis_reorder( XYZ_to_colourspace_model(XYZ, illuminant, reference_colourspace), reference_colourspace) points[np.isnan(points)] = 0 c = ((0.0, 0.0, 0.0, 0.5) if spectral_locus_colour is None else spectral_locus_colour) pylab.plot(points[..., 0], points[..., 1], points[..., 2], color=c, linewidth=2, zorder=1) pylab.plot((points[-1][0], points[0][0]), (points[-1][1], points[0][1]), (points[-1][2], points[0][2]), color=c, linewidth=2, zorder=1) quads, RGB_f, RGB_e = [], [], [] for i, colourspace in enumerate(colourspaces): colourspace = get_RGB_colourspace(colourspace) quads_c, RGB = RGB_identity_cube(width_segments=segments, height_segments=segments, depth_segments=segments) XYZ = RGB_to_XYZ(quads_c, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix) quads.extend( common_colourspace_model_axis_reorder( XYZ_to_colourspace_model(XYZ, colourspace.whitepoint, reference_colourspace), reference_colourspace)) if settings.face_colours[i] is not None: RGB = np.ones(RGB.shape) * settings.face_colours[i] RGB_f.extend( np.hstack((RGB, np.full((RGB.shape[0], 1), settings.face_alpha[i], np.float_)))) if settings.edge_colours[i] is not None: RGB = np.ones(RGB.shape) * settings.edge_colours[i] RGB_e.extend( np.hstack((RGB, np.full((RGB.shape[0], 1), settings.edge_alpha[i], np.float_)))) quads = np.asarray(quads) quads[np.isnan(quads)] = 0 if quads.size != 0: for i, axis in enumerate('xyz'): min_a = np.min(np.vstack((quads[..., i], points[..., i]))) max_a = np.max(np.vstack((quads[..., i], points[..., i]))) getattr(axes, 'set_{}lim'.format(axis))((min_a, max_a)) labels = COLOURSPACE_MODELS_LABELS[reference_colourspace] for i, axis in enumerate('xyz'): getattr(axes, 'set_{}label'.format(axis))(labels[i]) if display_grid: if reference_colourspace == 'CIE Lab': limits = np.array([[-450, 450], [-450, 450]]) elif reference_colourspace == 'CIE Luv': limits = np.array([[-650, 650], [-650, 650]]) elif reference_colourspace == 'CIE UVW': limits = np.array([[-850, 850], [-850, 850]]) elif reference_colourspace in ('Hunter Lab', 'Hunter Rdab'): limits = np.array([[-250, 250], [-250, 250]]) else: limits = np.array([[-1.5, 1.5], [-1.5, 1.5]]) quads_g, RGB_gf, RGB_ge = nadir_grid(limits, grid_segments, labels, axes, **settings) quads = np.vstack((quads_g, quads)) RGB_f = np.vstack((RGB_gf, RGB_f)) RGB_e = np.vstack((RGB_ge, RGB_e)) collection = Poly3DCollection(quads) collection.set_facecolors(RGB_f) collection.set_edgecolors(RGB_e) axes.add_collection3d(collection) settings.update({'camera_aspect': 'equal', 'no_axes': True}) settings.update(kwargs) camera(**settings) decorate(**settings) return display(**settings)
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. Other Parameters ---------------- \**kwargs : dict, optional {:func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definition. Returns ------- Figure Current figure or None. Examples -------- >>> the_blue_sky_plot() # doctest: +SKIP """ canvas(**kwargs) cmfs, name = get_cmfs(cmfs), cmfs ASTM_G_173_spd = ASTM_G_173_ETR.copy() 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_swatch_plot( ColourSwatch('', normalise_maximum(blue_sky_color)), **settings) settings = {'standalone': True} settings.update(kwargs) return render(**settings)
def multi_spd_plot(spds, cmfs='CIE 1931 2 Degree Standard Observer', use_spds_colours=False, normalise_spds_colours=False, **kwargs): """ Plots given spectral power distributions. Parameters ---------- spds : list Spectral power distributions to plot. cmfs : unicode, optional Standard observer colour matching functions used for spectrum creation. use_spds_colours : bool, optional Whether to use spectral power distributions colours. normalise_spds_colours : bool Whether to normalise spectral power distributions colours. Other Parameters ---------------- \**kwargs : dict, optional {:func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definition. Returns ------- Figure Current figure or None. Examples -------- >>> from colour import SpectralPowerDistribution >>> data_1 = { ... 500: 0.004900, ... 510: 0.009300, ... 520: 0.063270, ... 530: 0.165500, ... 540: 0.290400, ... 550: 0.433450, ... 560: 0.594500 ... } >>> data_2 = { ... 500: 0.323000, ... 510: 0.503000, ... 520: 0.710000, ... 530: 0.862000, ... 540: 0.954000, ... 550: 0.994950, ... 560: 0.995000 ... } >>> spd1 = SpectralPowerDistribution(data_1, name='Custom 1') >>> spd2 = SpectralPowerDistribution(data_2, name='Custom 2') >>> multi_spd_plot([spd1, spd2]) # doctest: +SKIP """ canvas(**kwargs) cmfs = get_cmfs(cmfs) if use_spds_colours: illuminant = ILLUMINANTS_RELATIVE_SPDS['D65'] x_limit_min, x_limit_max, y_limit_min, y_limit_max = [], [], [], [] for spd in spds: wavelengths, values = spd.wavelengths, spd.values shape = spd.shape x_limit_min.append(shape.start) x_limit_max.append(shape.end) y_limit_min.append(min(values)) y_limit_max.append(max(values)) if use_spds_colours: XYZ = spectral_to_XYZ(spd, cmfs, illuminant) / 100 if normalise_spds_colours: XYZ = normalise_maximum(XYZ, clip=False) RGB = np.clip(XYZ_to_sRGB(XYZ), 0, 1) pylab.plot(wavelengths, values, color=RGB, label=spd.strict_name, linewidth=1) else: pylab.plot(wavelengths, values, label=spd.strict_name, linewidth=1) settings = { 'x_label': 'Wavelength $\\lambda$ (nm)', 'y_label': 'Spectral Power Distribution', 'x_tighten': True, 'y_tighten': True, 'legend': True, 'legend_location': 'upper left', 'limits': (min(x_limit_min), max(x_limit_max), min(y_limit_min), max(y_limit_max)) } settings.update(kwargs) return render(**settings)
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)
def spds_CIE_1960_UCS_chromaticity_diagram_plot( spds, cmfs='CIE 1931 2 Degree Standard Observer', annotate=True, **kwargs): """ Plots given spectral power distribution chromaticity coordinates into the *CIE 1960 UCS Chromaticity Diagram*. Parameters ---------- spds : array_like, optional Spectral power distributions to plot. cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. annotate : bool Should resulting chromaticity coordinates annotated with their respective spectral power distribution names. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> from colour import ILLUMINANTS_RELATIVE_SPDS >>> A = ILLUMINANTS_RELATIVE_SPDS['A'] >>> D65 = ILLUMINANTS_RELATIVE_SPDS['D65'] >>> spds_CIE_1960_UCS_chromaticity_diagram_plot([A, D65]) # doctest: +SKIP True """ settings = {} settings.update(kwargs) settings.update({'standalone': False}) CIE_1960_UCS_chromaticity_diagram_plot(**settings) cmfs = get_cmfs(cmfs) cmfs_shape = cmfs.shape for spd in spds: spd = spd.clone().align(cmfs_shape) XYZ = spectral_to_XYZ(spd) / 100 uv = UCS_to_uv(XYZ_to_UCS(XYZ)) pylab.plot(uv[0], uv[1], 'o', color='white') if spd.name is not None and annotate: pylab.annotate(spd.name, xy=uv, xytext=(50, 30), textcoords='offset points', arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=0.2')) settings.update({ 'x_tighten': True, 'y_tighten': True, 'limits': (-0.1, 0.7, -0.2, 0.6), 'standalone': True}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def RGB_colourspaces_CIE_1931_chromaticity_diagram_plot( colourspaces=None, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given *RGB* colourspaces in *CIE 1931 Chromaticity Diagram*. Parameters ---------- colourspaces : array_like, optional *RGB* colourspaces to plot. cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. Other Parameters ---------------- \**kwargs : dict, optional {:func:`boundaries`, :func:`canvas`, :func:`decorate`, :func:`display`}, Please refer to the documentation of the previously listed definitions. show_diagram_colours : bool, optional {:func:`CIE_1931_chromaticity_diagram_plot`}, Whether to display the chromaticity diagram background colours. Returns ------- Figure Current figure or None. Examples -------- >>> c = ['Rec. 709', 'ACEScg', 'S-Gamut'] >>> RGB_colourspaces_CIE_1931_chromaticity_diagram_plot( ... c) # doctest: +SKIP """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) if colourspaces is None: colourspaces = ('Rec. 709', 'ACEScg', 'S-Gamut', 'Pointer Gamut') cmfs, name = get_cmfs(cmfs), cmfs settings = { 'title': '{0} - {1} - CIE 1931 Chromaticity Diagram'.format( ', '.join(colourspaces), name), 'standalone': False } settings.update(kwargs) CIE_1931_chromaticity_diagram_plot(**settings) x_limit_min, x_limit_max = [-0.1], [0.9] y_limit_min, y_limit_max = [-0.1], [0.9] settings = { 'colour_cycle_map': 'rainbow', 'colour_cycle_count': len(colourspaces) } settings.update(kwargs) cycle = colour_cycle(**settings) for colourspace in colourspaces: if colourspace == 'Pointer Gamut': xy = np.asarray(POINTER_GAMUT_BOUNDARIES) alpha_p, colour_p = 0.85, '0.95' pylab.plot(xy[..., 0], xy[..., 1], label='Pointer\'s Gamut', color=colour_p, alpha=alpha_p, linewidth=2) pylab.plot((xy[-1][0], xy[0][0]), (xy[-1][1], xy[0][1]), color=colour_p, alpha=alpha_p, linewidth=2) XYZ = Lab_to_XYZ(LCHab_to_Lab(POINTER_GAMUT_DATA), POINTER_GAMUT_ILLUMINANT) xy = XYZ_to_xy(XYZ, POINTER_GAMUT_ILLUMINANT) pylab.scatter(xy[..., 0], xy[..., 1], alpha=alpha_p / 2, color=colour_p, marker='+') else: colourspace, name = get_RGB_colourspace(colourspace), colourspace r, g, b, _a = next(cycle) 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]) - 0.1) y_limit_min.append(np.amin(primaries[..., 1]) - 0.1) x_limit_max.append(np.amax(primaries[..., 0]) + 0.1) y_limit_max.append(np.amax(primaries[..., 1]) + 0.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)), 'standalone': True }) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
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 : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> blackbody_spectral_radiance_plot() # doctest: +SKIP """ canvas(**kwargs) cmfs = get_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': 'W / (sr m$^2$) / m', 'standalone': False } settings.update(kwargs) single_spd_plot(spd, cmfs.name, **settings) XYZ = spectral_to_XYZ(spd, cmfs) RGB = normalise_maximum(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(ColourParameter(name='', RGB=RGB), **settings) settings = {'standalone': True} settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def CIE_1931_chromaticity_diagram_colours_plot( surface=1, samples=4096, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots the *CIE 1931 Chromaticity Diagram* colours. Parameters ---------- surface : numeric, optional Generated markers surface. samples : numeric, optional Samples count on one axis. 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 """ if is_scipy_installed(raise_exception=True): from scipy.spatial import Delaunay settings = {'figure_size': (64, 64)} settings.update(kwargs) canvas(**settings) cmfs = get_cmfs(cmfs) illuminant = CHROMATICITY_DIAGRAM_DEFAULT_ILLUMINANT triangulation = Delaunay(XYZ_to_xy(cmfs.values, illuminant), qhull_options='QJ') xx, yy = np.meshgrid(np.linspace(0, 1, samples), np.linspace(0, 1, samples)) xy = tstack((xx, yy)) xy = xy[triangulation.find_simplex(xy) > 0] XYZ = xy_to_XYZ(xy) RGB = normalise(XYZ_to_sRGB(XYZ, illuminant), axis=-1) x_dot, y_dot = tsplit(xy) pylab.scatter(x_dot, y_dot, color=RGB, s=surface) settings.update({ 'no_ticks': True, 'bounding_box': (0, 1, 0, 1), 'bbox_inches': 'tight', 'pad_inches': 0}) settings.update(kwargs) ax = matplotlib.pyplot.gca() matplotlib.pyplot.setp(ax, frame_on=False) boundaries(**settings) decorate(**settings) return display(**settings)
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 """ canvas(**kwargs) 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) boundaries(**settings) decorate(**settings) return display(**settings)
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)
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 : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> the_blue_sky_plot() # doctest: +SKIP True """ canvas(**kwargs) 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(ColourParameter('', normalise(blue_sky_color)), **settings) settings = {'standalone': True} settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
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)
def CIE_1931_chromaticity_diagram_colours_plot( surface=1, samples=4096, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots the *CIE 1931 Chromaticity Diagram* colours. Parameters ---------- surface : numeric, optional Generated markers surface. samples : numeric, optional Samples count on one axis. cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. Other Parameters ---------------- \**kwargs : dict, optional {:func:`boundaries`, :func:`canvas`, :func:`decorate`, :func:`display`}, Please refer to the documentation of the previously listed definitions. Returns ------- Figure Current figure or None. Examples -------- >>> CIE_1931_chromaticity_diagram_colours_plot() # doctest: +SKIP """ settings = {'figure_size': (64, 64)} settings.update(kwargs) canvas(**settings) cmfs = get_cmfs(cmfs) illuminant = DEFAULT_PLOTTING_ILLUMINANT triangulation = Delaunay(XYZ_to_xy(cmfs.values, illuminant), qhull_options='QJ') xx, yy = np.meshgrid(np.linspace(0, 1, samples), np.linspace(0, 1, samples)) xy = tstack((xx, yy)) xy = xy[triangulation.find_simplex(xy) > 0] XYZ = xy_to_XYZ(xy) RGB = normalise_maximum(XYZ_to_sRGB(XYZ, illuminant), axis=-1) x_dot, y_dot = tsplit(xy) pylab.scatter(x_dot, y_dot, color=RGB, s=surface) settings.update({ 'x_ticker': False, 'y_ticker': False, 'bounding_box': (0, 1, 0, 1) }) settings.update(kwargs) ax = matplotlib.pyplot.gca() matplotlib.pyplot.setp(ax, frame_on=False) boundaries(**settings) decorate(**settings) return display(**settings)
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)