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 multi_spd_colour_rendering_index_bars_plot(spds, **kwargs): """ Plots the *colour rendering index* of given illuminants or light sources spectral power distributions. Parameters ---------- spds : array_like Array of illuminants or light sources spectral power distributions to plot the *colour rendering index*. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> from colour import ( ... ILLUMINANTS_RELATIVE_SPDS, ... LIGHT_SOURCES_RELATIVE_SPDS) >>> illuminant = ILLUMINANTS_RELATIVE_SPDS.get('F2') >>> light_source = LIGHT_SOURCES_RELATIVE_SPDS.get('Kinoton 75P') >>> multi_spd_colour_rendering_index_bars_plot( # doctest: +SKIP ... [illuminant, light_source]) """ settings = {} settings.update(kwargs) settings.update({'standalone': False}) specifications = [ colour_rendering_index(spd, additional_data=True) for spd in spds ] # *colour rendering index* colorimetry data tristimulus values are # computed in [0, 100] domain however `colour_quality_bars_plot` expects # [0, 1] domain. As we want to keep `colour_quality_bars_plot` definition # agnostic from the colour quality data, we update the test spd # colorimetry data tristimulus values domain. for specification in specifications: colorimetry_data = specification.colorimetry_data for i, c_d in enumerate(colorimetry_data[0]): colorimetry_data[0][i] = TCS_ColorimetryData( c_d.name, c_d.XYZ / 100, c_d.uv, c_d.UVW) colour_quality_bars_plot(specifications, **settings) settings = { 'title': 'Colour Rendering Index - {0}'.format(', '.join( [spd.title for spd in spds])) } settings.update(kwargs) decorate(**settings) return display(**settings)
def RGB_chromaticity_coordinates_CIE_1931_chromaticity_diagram_plot( RGB, colourspace, **kwargs): """ Plots given *RGB* colourspace array in *CIE 1931 Chromaticity Diagram*. Parameters ---------- RGB : array_like *RGB* colourspace array. colourspace : unicode *RGB* colourspace of the *RGB* array. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> RGB = np.random.random((10, 10, 3)) >>> c = 'Rec. 709' >>> RGB_chromaticity_coordinates_CIE_1931_chromaticity_diagram_plot( ... RGB, c) # doctest: +SKIP """ settings = {} settings.update(kwargs) settings.update({'standalone': False}) colourspace, name = get_RGB_colourspace(colourspace), colourspace settings['colourspaces'] = ( [name] + settings.get('colourspaces', [])) RGB_colourspaces_CIE_1931_chromaticity_diagram_plot(**settings) alpha_p, colour_p = 0.85, 'black' xy = XYZ_to_xy(RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix), colourspace.whitepoint) pylab.scatter(xy[..., 0], xy[..., 1], alpha=alpha_p / 2, color=colour_p, marker='+') settings.update({'standalone': True}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def colour_quality_scale_bars_plot(spd, **kwargs): """ Plots the *colour quality scale* of given illuminant or light source. Parameters ---------- spd : SpectralPowerDistribution Illuminant or light source to plot the *colour quality scale*. \*\*kwargs : \*\* Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> from colour import ILLUMINANTS_RELATIVE_SPDS >>> illuminant = ILLUMINANTS_RELATIVE_SPDS.get('F2') >>> colour_quality_scale_bars_plot(illuminant) # doctest: +SKIP True """ if colour_quality_bars_plot( colour_quality_scale( spd, additional_data=True), standalone=False): settings = { 'title': 'Colour Quality Scale - {0}'.format(spd.title)} decorate(**settings) return display(**settings)
def RGB_chromaticity_coordinates_CIE_1976_UCS_chromaticity_diagram_plot( RGB, colourspace, **kwargs): """ Plots given *RGB* colourspace array in *CIE 1976 UCS Chromaticity Diagram*. Parameters ---------- RGB : array_like *RGB* colourspace array. colourspace : RGB_Colourspace *RGB* colourspace of the *RGB* array. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> RGB = np.random.random((10, 10, 3)) >>> c = 'Rec. 709' >>> RGB_chromaticity_coordinates_CIE_1976_UCS_chromaticity_diagram_plot( ... RGB, c) # doctest: +SKIP True """ settings = {} settings.update(kwargs) settings.update({'standalone': False}) settings['colourspaces'] = ( [colourspace.name] + settings.get('colourspaces', [])) RGB_colourspaces_CIE_1976_UCS_chromaticity_diagram_plot(**settings) alpha_p, colour_p = 0.85, 'black' uv = Luv_to_uv(XYZ_to_Luv(RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix), colourspace.whitepoint), colourspace.whitepoint) pylab.scatter(uv[..., 0], uv[..., 1], alpha=alpha_p / 2, color=colour_p, marker='+') settings.update({'standalone': True}) boundaries(**settings) decorate(**settings) return display(**settings)
def multi_spd_colour_rendering_index_bars_plot(spds, **kwargs): """ Plots the *colour rendering index* of given illuminants or light sources spectral power distributions. Parameters ---------- spds : array_like Array of illuminants or light sources spectral power distributions to plot the *colour rendering index*. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> from colour import ( ... ILLUMINANTS_RELATIVE_SPDS, ... LIGHT_SOURCES_RELATIVE_SPDS) >>> illuminant = ILLUMINANTS_RELATIVE_SPDS.get('F2') >>> light_source = LIGHT_SOURCES_RELATIVE_SPDS.get('Kinoton 75P') >>> multi_spd_colour_rendering_index_bars_plot( # doctest: +SKIP ... [illuminant, light_source]) True """ settings = {} settings.update(kwargs) settings.update({'standalone': False}) specifications = [colour_rendering_index(spd, additional_data=True) for spd in spds] # *colour rendering index* colorimetry data tristimulus values are # computed in [0, 100] domain however `colour_quality_bars_plot` expects # [0, 1] domain. As we want to keep `colour_quality_bars_plot` definition # agnostic from the colour quality data, we update the test spd # colorimetry data tristimulus values domain. for specification in specifications: colorimetry_data = specification.colorimetry_data for i, c_d in enumerate(colorimetry_data[0]): colorimetry_data[0][i] = TCS_ColorimetryData(c_d.name, c_d.XYZ / 100, c_d.uv, c_d.UVW) colour_quality_bars_plot(specifications, **settings) settings = {'title': 'Colour Rendering Index - {0}'.format(', '.join( [spd.title for spd in spds]))} settings.update(kwargs) decorate(**settings) return display(**settings)
def multi_transfer_function_plot(colourspaces=None, inverse=False, **kwargs): """ Plots given colourspaces transfer functions. Parameters ---------- colourspaces : list, optional Colourspaces transfer functions to plot. inverse : bool Plot inverse transfer functions. \*\*kwargs : \*\* Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> multi_transfer_function_plot(['sRGB', 'Rec. 709']) # doctest: +SKIP True """ if colourspaces is None: colourspaces = ['sRGB', 'Rec. 709'] samples = np.linspace(0, 1, 1000) for i, colourspace in enumerate(colourspaces): colourspace, name = get_RGB_colourspace(colourspace), colourspace RGBs = np.array([colourspace.inverse_transfer_function(x) if inverse else colourspace.transfer_function(x) for x in samples]) pylab.plot(samples, RGBs, label=u'{0}'.format(colourspace.name), linewidth=2) settings = { 'title': '{0} - Transfer Functions'.format( ', '.join(colourspaces)), 'x_tighten': True, 'legend': True, 'legend_location': 'upper left', 'x_ticker': True, 'y_ticker': True, 'grid': True, 'limits': [0, 1, 0, 1]} settings.update(kwargs) bounding_box(**settings) aspect(**settings) return display(**settings)
def RGB_chromaticity_coordinates_CIE_1931_chromaticity_diagram_plot( RGB, colourspace, **kwargs): """ Plots given *RGB* colourspace array in *CIE 1931 Chromaticity Diagram*. Parameters ---------- RGB : array_like *RGB* colourspace array. colourspace : unicode *RGB* colourspace of the *RGB* array. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Examples -------- >>> RGB = np.random.random((10, 10, 3)) >>> c = 'Rec. 709' >>> RGB_chromaticity_coordinates_CIE_1931_chromaticity_diagram_plot( ... RGB, c) # doctest: +SKIP """ settings = {} settings.update(kwargs) settings.update({'standalone': False}) colourspace, name = get_RGB_colourspace(colourspace), colourspace settings['colourspaces'] = ([name] + settings.get('colourspaces', [])) RGB_colourspaces_CIE_1931_chromaticity_diagram_plot(**settings) alpha_p, colour_p = 0.85, 'black' xy = XYZ_to_xy( RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix), colourspace.whitepoint) pylab.scatter(xy[..., 0], xy[..., 1], alpha=alpha_p / 2, color=colour_p, marker='+') settings.update({'standalone': True}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def RGB_chromaticity_coordinates_CIE_1931_chromaticity_diagram_plot( RGB, colourspace, **kwargs): """ Plots given *RGB* colourspace array in *CIE 1931 Chromaticity Diagram*. Parameters ---------- RGB : array_like *RGB* colourspace array. colourspace : RGB_Colourspace *RGB* colourspace of the *RGB* array. \*\*kwargs : \*\* Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> RGB = np.random.random((10, 10, 3)) >>> RGB_chromaticity_coordinates_CIE_1931_chromaticity_diagram_plot(RGB) # noqa # doctest: +SKIP True """ settings = {} settings.update(kwargs) settings['colourspaces'] = ( [colourspace.name] + settings.get('colourspaces', [])) RGB_colourspaces_CIE_1931_chromaticity_diagram_plot( standalone=False, **settings) alpha_p, colour_p = 0.85, 'black' xy = XYZ_to_xy(RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix), colourspace.whitepoint) pylab.scatter(xy[..., 0], xy[..., 1], alpha=alpha_p / 2, color=colour_p, marker='+') boundaries(**settings) decorate(**settings) return display(**settings)
def radiance_image_strip_plot(image, count=5, ev_steps=-2, encoding_cctf=DEFAULT_PLOTTING_ENCODING_CCTF, **kwargs): """ Plots given HDRI / radiance image as strip of images of varying exposure. Parameters ---------- image : array_like HDRI / radiance image to plot. count : int, optional Strip images count. ev_steps : numeric, optional Exposure variation for each image of the strip. encoding_cctf : callable, optional Encoding colour component transfer function / opto-electronic transfer function used for plotting. Other Parameters ---------------- \**kwargs : dict, optional {:func:`colour.plotting.display`}, Please refer to the documentation of the previously listed definition. Returns ------- Figure Current figure or None. """ image = np.asarray(image) grid = matplotlib.gridspec.GridSpec(1, count) grid.update(wspace=0, hspace=0) height, width, _channel = image.shape for i in range(count): ev = i * ev_steps axis = matplotlib.pyplot.subplot(grid[i]) axis.imshow(np.clip(encoding_cctf(adjust_exposure(image, ev)), 0, 1)) axis.text(width * 0.05, height - height * 0.05, 'EV {0}'.format(ev), color=(1, 1, 1)) axis.set_xticks([]) axis.set_yticks([]) axis.set_aspect('equal') return display(**kwargs)
def multi_spd_colour_quality_scale_bars_plot(spds, **kwargs): """ Plots the *colour quality scale* of given illuminants or light sources spectral power distributions. Parameters ---------- spds : array_like Array of illuminants or light sources spectral power distributions to plot the *colour quality scale*. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> from colour import ( ... ILLUMINANTS_RELATIVE_SPDS, ... LIGHT_SOURCES_RELATIVE_SPDS) >>> illuminant = ILLUMINANTS_RELATIVE_SPDS.get('F2') >>> light_source = LIGHT_SOURCES_RELATIVE_SPDS.get('Kinoton 75P') >>> multi_spd_colour_quality_scale_bars_plot( # doctest: +SKIP ... [illuminant, light_source]) True """ settings = {} settings.update(kwargs) settings.update({'standalone': False}) specifications = [ colour_quality_scale(spd, additional_data=True) for spd in spds ] colour_quality_bars_plot(specifications, **settings) settings = { 'title': 'Colour Quality Scale - {0}'.format(', '.join( [spd.title for spd in spds])) } settings.update(kwargs) decorate(**settings) return display(**settings)
def radiance_image_strip_plot(image, count=5, ev_steps=-2, encoding_cctf=DEFAULT_PLOTTING_ENCODING_CCTF, **kwargs): """ Plots given HDRI / radiance image as strip of images of varying exposure. Parameters ---------- image : array_like HDRI / radiance image to plot. count : int, optional Strip images count. ev_steps : numeric, optional Exposure variation for each image of the strip. encoding_cctf : callable, optional Encoding colour component transfer function / opto-electronic transfer function used for plotting. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. """ image = np.asarray(image) grid = matplotlib.gridspec.GridSpec(1, count) grid.update(wspace=0, hspace=0) height, width, _channel = image.shape for i in range(count): ev = i * ev_steps axis = matplotlib.pyplot.subplot(grid[i]) axis.imshow( np.clip(encoding_cctf(adjust_exposure(image, ev)), 0, 1)) axis.text(width * 0.05, height - height * 0.05, 'EV {0}'.format(ev), color=(1, 1, 1)) axis.set_xticks([]) axis.set_yticks([]) axis.set_aspect('equal') return display(**kwargs)
def multi_spd_colour_quality_scale_bars_plot(spds, **kwargs): """ Plots the *colour quality scale* of given illuminants or light sources spectral power distributions. Parameters ---------- spds : array_like Array of illuminants or light sources spectral power distributions to plot the *colour quality scale*. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> from colour import ( ... ILLUMINANTS_RELATIVE_SPDS, ... LIGHT_SOURCES_RELATIVE_SPDS) >>> illuminant = ILLUMINANTS_RELATIVE_SPDS.get('F2') >>> light_source = LIGHT_SOURCES_RELATIVE_SPDS.get('Kinoton 75P') >>> multi_spd_colour_quality_scale_bars_plot( # doctest: +SKIP ... [illuminant, light_source]) True """ settings = {} settings.update(kwargs) settings.update({'standalone': False}) specifications = [colour_quality_scale(spd, additional_data=True) for spd in spds] colour_quality_bars_plot(specifications, **settings) settings = {'title': 'Colour Quality Scale - {0}'.format(', '.join( [spd.title for spd in spds]))} settings.update(kwargs) decorate(**settings) return display(**settings)
def fraunhofer_lines_plot(image=SUN_SPECTRUM_IMAGE): """ Plots the Fraunhofer lines of given image. Parameters ---------- image : unicode Path to read the image from. Returns ------- bool Definition success. """ spectrum = RGB_spectrum(read_image(image), FRAUNHOFER_LINES_PUBLISHED, FRAUNHOFER_LINES_MEASURED) height = len(spectrum.R.values) / 8 spd = luminance_spd(spectrum).normalise(height) pylab.title('The Solar Spectrum - Fraunhofer Lines') wavelengths = spectrum.wavelengths input, output = min(wavelengths), max(wavelengths) pylab.imshow(sRGB_COLOURSPACE.OECF( np.dstack([spectrum.R.values, spectrum.G.values, spectrum.B.values])), extent=[input, output, 0, height]) pylab.plot(spd.wavelengths, spd.values, color='black', linewidth=1) fraunhofer_wavelengths = np.array( sorted(FRAUNHOFER_LINES_PUBLISHED.values())) fraunhofer_wavelengths = fraunhofer_wavelengths[ np.where(np.logical_and(fraunhofer_wavelengths >= input, fraunhofer_wavelengths <= output))] fraunhofer_lines_labels = [ tuple(FRAUNHOFER_LINES_PUBLISHED.keys())[ tuple(FRAUNHOFER_LINES_PUBLISHED.values()).index(i)] for i in fraunhofer_wavelengths] y0, y1 = 0, height * .5 for i, label in enumerate(fraunhofer_lines_labels): # Trick to cluster siblings fraunhofer lines. from_siblings = False for pattern, (first, siblings, specific_label) in FRAUNHOFER_LINES_CLUSTERED.items(): if re.match(pattern, label): if label in siblings: from_siblings = True label = specific_label break power = bisect.bisect_left(wavelengths, fraunhofer_wavelengths[i]) scale = (spd.get(wavelengths[power]) / height) is_large_line = label in FRAUNHOFER_LINES_NOTABLE pylab.vlines(fraunhofer_wavelengths[i], y0, y1 * scale, linewidth=2 if is_large_line else 1) pylab.vlines(fraunhofer_wavelengths[i], y0, height, linewidth=2 if is_large_line else 1, alpha=0.075) if not from_siblings: pylab.text(fraunhofer_wavelengths[i], y1 * scale + (y1 * 0.025), label, clip_on=True, ha='center', va='bottom', fontdict={'size': 'large' if is_large_line else'small'}) r = lambda x: int(x / 100) * 100 matplotlib.pyplot.xticks(np.arange(r(input), r(output * 1.5), 20)) settings = {'x_tighten': True, 'y_tighten': True, 'x_label': u'Wavelength λ (nm)', 'y_label': False, 'legend': False, 'limits': [input, output, 0, height], 'y_ticker': True, 'grid': True} boundaries(**settings) decorate(**settings) return display(**settings)
def planckian_locus_CIE_1931_chromaticity_diagram_plot( illuminants=None, **kwargs): """ Plots the planckian locus and given illuminants in *CIE 1931 Chromaticity Diagram*. Parameters ---------- illuminants : array_like, optional Factory illuminants to plot. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Raises ------ KeyError If one of the given illuminant is not found in the factory illuminants. Examples -------- >>> ils = ['A', 'B', 'C'] >>> planckian_locus_CIE_1931_chromaticity_diagram_plot( ... ils) # doctest: +SKIP """ if illuminants is None: illuminants = ('A', 'B', 'C') cmfs = CMFS.get('CIE 1931 2 Degree Standard Observer') settings = { 'title': ('{0} Illuminants - Planckian Locus\n' 'CIE 1931 Chromaticity Diagram - ' 'CIE 1931 2 Degree Standard Observer').format( ', '.join(illuminants)) if illuminants else ('Planckian Locus\nCIE 1931 Chromaticity Diagram - ' 'CIE 1931 2 Degree Standard Observer'), 'standalone': False} settings.update(kwargs) CIE_1931_chromaticity_diagram_plot(**settings) start, end = 1667, 100000 xy = np.array([UCS_uv_to_xy(CCT_to_uv(x, 0, method='Robertson 1968')) for x in np.arange(start, end + 250, 250)]) pylab.plot(xy[..., 0], xy[..., 1], color='black', linewidth=2) for i in (1667, 2000, 2500, 3000, 4000, 6000, 10000): x0, y0 = UCS_uv_to_xy(CCT_to_uv(i, -0.025, method='Robertson 1968')) x1, y1 = UCS_uv_to_xy(CCT_to_uv(i, 0.025, method='Robertson 1968')) pylab.plot((x0, x1), (y0, y1), color='black', linewidth=2) pylab.annotate('{0}K'.format(i), xy=(x0, y0), xytext=(0, -10), color='black', textcoords='offset points', size='x-small') for illuminant in illuminants: xy = ILLUMINANTS.get(cmfs.name).get(illuminant) if xy is None: raise KeyError( ('Illuminant "{0}" not found in factory illuminants: ' '"{1}".').format(illuminant, sorted(ILLUMINANTS.get(cmfs.name).keys()))) pylab.plot(xy[0], xy[1], 'o', color='white', linewidth=2) pylab.annotate(illuminant, xy=(xy[0], xy[1]), xytext=(-50, 30), color='black', textcoords='offset points', arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=-0.2')) settings.update({ 'x_tighten': True, 'y_tighten': True, 'limits': (-0.1, 0.9, -0.1, 0.9), 'standalone': True}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def colour_quality_bars_plot(specifications, labels=True, hatching=None, hatching_repeat=1, **kwargs): """ Plots the colour quality data of given illuminants or light sources colour quality specifications. Parameters ---------- specifications : array_like Array of illuminants or light sources colour quality specifications. labels : bool, optional Add labels above bars. hatching : bool or None, optional Use hatching for the bars. hatching_repeat : int, optional Hatching pattern repeat. 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 -------- >>> from colour import ( ... ILLUMINANTS_RELATIVE_SPDS, ... LIGHT_SOURCES_RELATIVE_SPDS, ... SpectralShape) >>> illuminant = ILLUMINANTS_RELATIVE_SPDS['F2'] >>> light_source = LIGHT_SOURCES_RELATIVE_SPDS['Kinoton 75P'] >>> light_source = light_source.clone().align(SpectralShape(360, 830, 1)) >>> cqs_i = colour_quality_scale(illuminant, additional_data=True) >>> cqs_l = colour_quality_scale(light_source, additional_data=True) >>> colour_quality_bars_plot([cqs_i, cqs_l]) # doctest: +SKIP """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) bar_width = 0.5 y_ticks_interval = 10 count_s, count_Q_as = len(specifications), 0 patterns = cycle(DEFAULT_HATCH_PATTERNS) if hatching is None: hatching = False if count_s == 1 else True for i, specification in enumerate(specifications): Q_a, Q_as, colorimetry_data = (specification.Q_a, specification.Q_as, specification.colorimetry_data) count_Q_as = len(Q_as) colours = ( [[1] * 3] + [np.clip(XYZ_to_sRGB(x.XYZ), 0, 1) for x in colorimetry_data[0]]) x = (i + np.arange(0, (count_Q_as + 1) * (count_s + 1), (count_s + 1), dtype=np.float_)) * bar_width y = [s[1].Q_a for s in sorted(Q_as.items(), key=lambda s: s[0])] y = np.array([Q_a] + list(y)) if np.sign(np.min(y)) < 0: warning( ('"{0}" spectral distribution has negative "Q_a" value(s), ' 'using absolute value(s) ' 'for plotting purpose!'.format(specification.name))) y = np.abs(y) bars = pylab.bar(x, y, color=colours, width=bar_width, hatch=(next(patterns) * hatching_repeat if hatching else None), label=specification.name) if labels: label_rectangles( bars, rotation='horizontal' if count_s == 1 else 'vertical', offset=(0 if count_s == 1 else 3 / 100 * count_s + 65 / 1000, 0.025), text_size=-5 / 7 * count_s + 12.5) pylab.axhline(y=100, color='black', linestyle='--') pylab.xticks( (np.arange(0, (count_Q_as + 1) * (count_s + 1), (count_s + 1), dtype=np.float_) * bar_width + (count_s * bar_width / 2)), ['Qa'] + ['Q{0}'.format(index + 1) for index in range(0, count_Q_as + 1, 1)]) pylab.yticks(range(0, 100 + y_ticks_interval, y_ticks_interval)) settings.update({ 'title': 'Colour Quality', 'legend': hatching, 'x_tighten': True, 'y_tighten': True, 'limits': (-bar_width, ((count_Q_as + 1) * (count_s + 1)) / 2, 0, 120), 'aspect': 1 / (120 / (bar_width + len(Q_as) + bar_width * 2)) }) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def colour_quality_bars_plot(specifications, labels=True, hatching=None, hatching_repeat=1, **kwargs): """ Plots the colour quality data of given illuminants or light sources colour quality specifications. Parameters ---------- specifications : array_like Array of illuminants or light sources colour quality specifications. labels : bool, optional Add labels above bars. hatching : bool or None, optional Use hatching for the bars. hatching_repeat : int, optional Hatching pattern repeat. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> from colour import ( ... ILLUMINANTS_RELATIVE_SPDS, ... LIGHT_SOURCES_RELATIVE_SPDS) >>> illuminant = ILLUMINANTS_RELATIVE_SPDS.get('F2') >>> light_source = LIGHT_SOURCES_RELATIVE_SPDS.get('Kinoton 75P') >>> cqs_i = colour_quality_scale(illuminant, additional_data=True) >>> cqs_l = colour_quality_scale(light_source, additional_data=True) >>> colour_quality_bars_plot([cqs_i, cqs_l]) # doctest: +SKIP True """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) bar_width = 0.5 y_ticks_steps = 10 count_s, count_Q_as = len(specifications), 0 patterns = cycle(DEFAULT_HATCH_PATTERNS) if hatching is None: hatching = False if count_s == 1 else True for i, specification in enumerate(specifications): Q_a, Q_as, colorimetry_data = (specification.Q_a, specification.Q_as, specification.colorimetry_data) count_Q_as = len(Q_as) colours = ([[1] * 3] + [np.clip(XYZ_to_sRGB(x.XYZ), 0, 1) for x in colorimetry_data[0]]) x = (i + np.arange(0, (count_Q_as + 1) * (count_s + 1), (count_s + 1), dtype=np.float)) * bar_width y = [s[1].Q_a for s in sorted(Q_as.items(), key=lambda s: s[0])] y = np.array([Q_a] + list(y)) if np.sign(np.min(y)) < 0: warning( ('"{0}" spectral distribution has negative "Q_a" value(s), ' 'using absolute value(s) ' 'for plotting purpose!'.format(specification.name))) y = np.abs(y) bars = pylab.bar(x, y, color=colours, width=bar_width, hatch=(next(patterns) * hatching_repeat if hatching else None), label=specification.name) if labels: label_rectangles( bars, rotation='horizontal' if count_s == 1 else 'vertical', offset=(0 if count_s == 1 else 3 / 100 * count_s + 65 / 1000, 0.025), text_size=-5 / 7 * count_s + 12.5) pylab.axhline(y=100, color='black', linestyle='--') pylab.xticks((np.arange(0, (count_Q_as + 1) * (count_s + 1), (count_s + 1), dtype=np.float) * bar_width + (count_s * bar_width / 2)), ['Qa'] + ['Q{0}'.format(index + 1) for index in range(0, count_Q_as + 1, 1)]) pylab.yticks(range(0, 100 + y_ticks_steps, y_ticks_steps)) settings.update({ 'title': 'Colour Quality', 'legend': hatching, 'x_tighten': True, 'y_tighten': True, 'limits': (-bar_width, ((count_Q_as + 1) * (count_s + 1)) / 2, 0, 120), 'aspect': 1 / (120 / (bar_width + len(Q_as) + bar_width * 2))}) 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 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 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 corresponding_chromaticities_prediction_plot(experiment=1, model='Von Kries', transform='CAT02', **kwargs): """ Plots given chromatic adaptation model corresponding chromaticities prediction. Parameters ---------- experiment : int, optional Corresponding chromaticities prediction experiment number. model : unicode, optional Corresponding chromaticities prediction model name. transform : unicode, optional Transformation to use with *Von Kries* chromatic adaptation model. 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 -------- >>> corresponding_chromaticities_prediction_plot() # doctest: +SKIP """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) settings.update({ 'title': (('Corresponding Chromaticities Prediction\n{0} ({1}) - ' 'Experiment {2}\nCIE 1976 UCS Chromaticity Diagram').format( model, transform, experiment) if model.lower() in ('von kries', 'vonkries') else ('Corresponding Chromaticities Prediction\n{0} - ' 'Experiment {1}\nCIE 1976 UCS Chromaticity Diagram').format( model, experiment)), 'standalone': False }) settings.update(kwargs) CIE_1976_UCS_chromaticity_diagram_plot(**settings) results = corresponding_chromaticities_prediction(experiment, transform=transform) for result in results: name, uvp_t, uvp_m, uvp_p = result pylab.arrow(uvp_t[0], uvp_t[1], uvp_p[0] - uvp_t[0] - 0.1 * (uvp_p[0] - uvp_t[0]), uvp_p[1] - uvp_t[1] - 0.1 * (uvp_p[1] - uvp_t[1]), head_width=0.005, head_length=0.005, linewidth=0.5, color='black') pylab.plot(uvp_t[0], uvp_t[1], 'o', color='white') pylab.plot(uvp_m[0], uvp_m[1], '^', color='white') pylab.plot(uvp_p[0], uvp_p[1], '^', color='black') settings.update({ 'x_tighten': True, 'y_tighten': True, 'limits': (-0.1, 0.7, -0.1, 0.7), 'standalone': True }) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def tonemapping_operator_image_plot(image, luminance_function, log_scale=False, OECF=DEFAULT_PLOTTING_OECF, **kwargs): """ Plots given tonemapped image with superimposed luminance mapping function. Parameters ---------- image : array_like Tonemapped image to plot. luminance_function : callable Luminance mapping function. log_scale : bool, optional Use a log scale for plotting the luminance mapping function. OECF : callable, optional OECF / opto-electronic conversion function used for plotting. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. """ shape = image.shape limits = [0, 1, 0, 1] image = np.clip(OECF(image), 0, 1) pylab.imshow(image, aspect=shape[0] / shape[1], extent=limits, interpolation='nearest') pylab.plot(np.linspace(0, 1, len(luminance_function)), luminance_function, color='red') settings = { 'figure_size': (8, 8), 'x_label': 'Input Luminance', 'y_label': 'Output Luminance', 'x_ticker': True, 'y_ticker': True, 'grid': True, 'x_tighten': True, 'y_tighten': True, 'limits': limits} settings.update(kwargs) if log_scale: settings.update({ 'x_label': '$log_2$ Input Luminance', 'x_ticker_locator': matplotlib.ticker.AutoMinorLocator(0.5)}) matplotlib.pyplot.gca().set_xscale('log', basex=2) matplotlib.pyplot.gca().xaxis.set_major_formatter( matplotlib.ticker.ScalarFormatter()) canvas(**settings) decorate(**settings) boundaries(**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)
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_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_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 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 multi_lightness_function_plot(functions=None, **kwargs): """ Plots given *Lightness* functions. Parameters ---------- functions : array_like, optional *Lightness* functions to plot. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Raises ------ KeyError If one of the given *Lightness* function is not found in the factory *Lightness* functions. Examples -------- >>> fs = ('CIE 1976', 'Wyszecki 1963') >>> multi_lightness_function_plot(fs) # doctest: +SKIP True """ settings = { 'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) if functions is None: functions = ('CIE 1976', 'Wyszecki 1963') samples = np.linspace(0, 100, 1000) for function in functions: function, name = LIGHTNESS_METHODS.get(function), function if function is None: raise KeyError( ('"{0}" "Lightness" function not found in factory ' '"Lightness" functions: "{1}".').format( name, sorted(LIGHTNESS_METHODS.keys()))) pylab.plot(samples, [function(x) for x in samples], label='{0}'.format(name), linewidth=2) settings.update({ 'title': '{0} - Lightness Functions'.format(', '.join(functions)), 'x_label': 'Luminance Y', 'y_label': 'Lightness L*', 'x_tighten': True, 'legend': True, 'legend_location': 'upper left', 'grid': True, 'limits': (0, 100, 0, 100), 'aspect': 'equal'}) settings.update(kwargs) 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 colour_rendering_index_bars_plot(illuminant, **kwargs): """ Plots the *colour rendering index* of given illuminant. Parameters ---------- illuminant : SpectralPowerDistribution Illuminant to plot the *colour rendering index*. \*\*kwargs : \*\* Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> from colour import ILLUMINANTS_RELATIVE_SPDS >>> illuminant = ILLUMINANTS_RELATIVE_SPDS.get('F2') >>> colour_rendering_index_bars_plot(illuminant) # doctest: +SKIP True """ figure, axis = matplotlib.pyplot.subplots() cri, colour_rendering_indexes, additional_data = \ colour_rendering_index(illuminant, additional_data=True) colours = ([[1] * 3] + [normalise(XYZ_to_sRGB(x.XYZ / 100)) for x in additional_data[0]]) x, y = tuple(zip(*sorted(colour_rendering_indexes.items(), key=lambda x: x[0]))) x, y = np.array([0] + list(x)), np.array( [cri] + list(y)) positive = True if np.sign(min(y)) in (0, 1) else False width = 0.5 bars = pylab.bar(x, y, color=colours, width=width) y_ticks_steps = 10 pylab.yticks(range(0 if positive else -100, 100 + y_ticks_steps, y_ticks_steps)) pylab.xticks(x + width / 2, ['Ra'] + ['R{0}'.format(index) for index in x[1:]]) def label_bars(bars): """ Add labels above given bars. """ for bar in bars: y = bar.get_y() height = bar.get_height() value = height if np.sign(y) in (0, 1) else -height axis.text(bar.get_x() + bar.get_width() / 2, 0.025 * height + height + y, '{0:.1f}'.format(value), ha='center', va='bottom') label_bars(bars) settings = { 'title': 'Colour Rendering Index - {0}'.format(illuminant.name), 'grid': True, 'x_tighten': True, 'y_tighten': True, 'limits': [-width, 14 + width * 2, -10 if positive else -110, 110]} settings.update(kwargs) bounding_box(**settings) aspect(**settings) return display(**settings)
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 RGB_scatter_plot(RGB, colourspace, reference_colourspace='CIE xyY', colourspaces=None, segments=8, display_grid=True, grid_segments=10, spectral_locus=False, spectral_locus_colour=None, points_size=12, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given *RGB* colourspace array in a scatter plot. Parameters ---------- RGB : array_like *RGB* colourspace array. colourspace : RGB_Colourspace *RGB* colourspace of the *RGB* array. reference_colourspace : unicode, optional **{'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW', 'IPT', 'Hunter Lab', 'Hunter Rdab'}**, Reference colourspace for colour conversion. colourspaces : array_like, optional *RGB* colourspaces to plot the gamuts. 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. points_size : numeric, optional Scatter points size. cmfs : unicode, optional Standard observer colour matching functions used for spectral locus. Other Parameters ---------------- \**kwargs : dict, optional {:func:`RGB_colourspaces_gamuts_plot`}, Please refer to the documentation of the previously listed definitions. Returns ------- Figure Current figure or None. Examples -------- >>> c = 'Rec. 709' >>> RGB_scatter_plot(c) # doctest: +SKIP """ colourspace = get_RGB_colourspace(colourspace) if colourspaces is None: colourspaces = (colourspace.name, ) count_c = len(colourspaces) settings = Structure( **{ 'face_colours': [None] * count_c, 'edge_colours': [(0.25, 0.25, 0.25)] * count_c, 'face_alpha': [0.0] * count_c, 'edge_alpha': [0.1] * count_c, 'standalone': False }) settings.update(kwargs) RGB_colourspaces_gamuts_plot(colourspaces=colourspaces, reference_colourspace=reference_colourspace, segments=segments, display_grid=display_grid, grid_segments=grid_segments, spectral_locus=spectral_locus, spectral_locus_colour=spectral_locus_colour, cmfs=cmfs, **settings) XYZ = RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix) points = common_colourspace_model_axis_reorder( XYZ_to_colourspace_model(XYZ, colourspace.whitepoint, reference_colourspace), reference_colourspace) axes = matplotlib.pyplot.gca() axes.scatter(points[..., 0], points[..., 1], points[..., 2], color=np.reshape(RGB, (-1, 3)), s=points_size) settings.update({'standalone': True}) settings.update(kwargs) camera(**settings) decorate(**settings) return display(**settings)
def multi_spd_colour_rendering_index_bars_plot(spds, **kwargs): """ Plots the *Colour Rendering Index* (CRI) of given illuminants or light sources spectral power distributions. Parameters ---------- spds : array_like Array of illuminants or light sources spectral power distributions to plot the *Colour Rendering Index* (CRI). Other Parameters ---------------- \**kwargs : dict, optional {:func:`boundaries`, :func:`canvas`, :func:`decorate`, :func:`display`}, Please refer to the documentation of the previously listed definitions. labels : bool, optional {:func:`colour_quality_bars_plot`}, Add labels above bars. hatching : bool or None, optional {:func:`colour_quality_bars_plot`}, Use hatching for the bars. hatching_repeat : int, optional {:func:`colour_quality_bars_plot`}, Hatching pattern repeat. Returns ------- Figure Current figure or None. Examples -------- >>> from colour import ( ... ILLUMINANTS_RELATIVE_SPDS, ... LIGHT_SOURCES_RELATIVE_SPDS) >>> illuminant = ILLUMINANTS_RELATIVE_SPDS['F2'] >>> light_source = LIGHT_SOURCES_RELATIVE_SPDS['Kinoton 75P'] >>> multi_spd_colour_rendering_index_bars_plot( # doctest: +SKIP ... [illuminant, light_source]) """ settings = {} settings.update(kwargs) settings.update({'standalone': False}) specifications = [ colour_rendering_index(spd, additional_data=True) for spd in spds ] # *colour rendering index* colorimetry data tristimulus values are # computed in [0, 100] domain however `colour_quality_bars_plot` expects # [0, 1] domain. As we want to keep `colour_quality_bars_plot` definition # agnostic from the colour quality data, we update the test spd # colorimetry data tristimulus values domain. for specification in specifications: colorimetry_data = specification.colorimetry_data for i, c_d in enumerate(colorimetry_data[0]): colorimetry_data[0][i] = TCS_ColorimetryData( c_d.name, c_d.XYZ / 100, c_d.uv, c_d.UVW) colour_quality_bars_plot(specifications, **settings) settings = { 'title': 'Colour Rendering Index - {0}'.format(', '.join( [spd.title for spd in spds])) } settings.update(kwargs) decorate(**settings) return display(**settings)
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 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 multi_lightness_function_plot(functions=None, **kwargs): """ Plots given *Lightness* functions. Parameters ---------- functions : array_like, optional *Lightness* functions to plot. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Raises ------ KeyError If one of the given *Lightness* function is not found in the factory *Lightness* functions. Examples -------- >>> fs = ('CIE 1976', 'Wyszecki 1963') >>> multi_lightness_function_plot(fs) # doctest: +SKIP """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) if functions is None: functions = ('CIE 1976', 'Wyszecki 1963') samples = np.linspace(0, 100, 1000) for function in functions: function, name = LIGHTNESS_METHODS.get(function), function if function is None: raise KeyError(('"{0}" "Lightness" function not found in factory ' '"Lightness" functions: "{1}".').format( name, sorted(LIGHTNESS_METHODS.keys()))) pylab.plot(samples, [function(x) for x in samples], label='{0}'.format(name), linewidth=2) settings.update({ 'title': '{0} - Lightness Functions'.format(', '.join(functions)), 'x_label': 'Relative Luminance Y', 'y_label': 'Lightness', 'x_tighten': True, 'legend': True, 'legend_location': 'upper left', 'grid': True, 'limits': (0, 100, 0, 100), 'aspect': 'equal' }) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def multi_cctf_plot(colourspaces=None, decoding_cctf=False, **kwargs): """ Plots given colourspaces colour component transfer functions. Parameters ---------- colourspaces : array_like, optional Colourspaces colour component transfer function to plot. decoding_cctf : bool Plot decoding colour component transfer function instead. 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 -------- >>> multi_cctf_plot(['Rec. 709', 'sRGB']) # doctest: +SKIP """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) if colourspaces is None: colourspaces = ('Rec. 709', 'sRGB') samples = np.linspace(0, 1, 1000) for colourspace in colourspaces: colourspace = get_RGB_colourspace(colourspace) RGBs = (colourspace.decoding_cctf(samples) if decoding_cctf else colourspace.encoding_cctf(samples)) pylab.plot(samples, RGBs, label=u'{0}'.format(colourspace.name), linewidth=2) settings.update({ 'title': '{0} - {1} CCTFs'.format(', '.join(colourspaces), 'Decoding' if decoding_cctf else 'Encoding'), 'x_tighten': True, 'x_label': 'Signal Value' if decoding_cctf else 'Tristimulus Value', 'y_label': 'Tristimulus Value' if decoding_cctf else 'Signal Value', 'legend': True, 'legend_location': 'upper left', 'grid': True, 'limits': (0, 1, 0, 1), 'aspect': 'equal' }) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def colour_checker_plot(colour_checker='ColorChecker 2005', **kwargs): """ Plots given colour checker. Parameters ---------- colour_checker : unicode, optional Color checker name. Other Parameters ---------------- \**kwargs : dict, optional {:func:`boundaries`, :func:`canvas`, :func:`decorate`, :func:`display`}, Please refer to the documentation of the previously listed definitions. width : numeric, optional {:func:`multi_colour_plot`}, Colour polygon width. height : numeric, optional {:func:`multi_colour_plot`}, Colour polygon height. spacing : numeric, optional {:func:`multi_colour_plot`}, Colour polygons spacing. across : int, optional {:func:`multi_colour_plot`}, Colour polygons count per row. text_display : bool, optional {:func:`multi_colour_plot`}, Display colour text. text_size : numeric, optional {:func:`multi_colour_plot`}, Colour text size. text_offset : numeric, optional {:func:`multi_colour_plot`}, Colour text offset. Returns ------- Figure Current figure or None. Raises ------ KeyError If the given colour rendition chart is not found in the factory colour rendition charts. Examples -------- >>> colour_checker_plot() # doctest: +SKIP """ canvas(**kwargs) colour_checker, name = COLOURCHECKERS.get(colour_checker), colour_checker if colour_checker is None: raise KeyError(('Colour checker "{0}" not found in ' 'factory colour checkers: "{1}".').format( name, sorted(COLOURCHECKERS.keys()))) _name, data, illuminant = colour_checker colour_parameters = [] for _index, label, xyY in data: XYZ = xyY_to_XYZ(xyY) RGB = XYZ_to_sRGB(XYZ, illuminant) colour_parameters.append( ColourParameter(label.title(), np.clip(np.ravel(RGB), 0, 1))) background_colour = '0.1' width = height = 1.0 spacing = 0.25 across = 6 settings = { 'standalone': False, 'width': width, 'height': height, 'spacing': spacing, 'across': across, 'text_size': 8, 'background_colour': background_colour, 'margins': (-0.125, 0.125, -0.5, 0.125) } settings.update(kwargs) multi_colour_plot(colour_parameters, **settings) text_x = width * (across / 2) + (across * (spacing / 2)) - spacing / 2 text_y = -(len(colour_parameters) / across + spacing / 2) pylab.text( text_x, text_y, '{0} - {1} - Colour Rendition Chart'.format( name, RGB_COLOURSPACES['sRGB'].name), color='0.95', clip_on=True, ha='center') settings.update({ 'title': name, 'facecolor': background_colour, 'edgecolor': None, 'standalone': True }) boundaries(**settings) decorate(**settings) return display(**settings)
def RGB_scatter_plot(RGB, colourspace, reference_colourspace='CIE xyY', colourspaces=None, segments=8, display_grid=True, grid_segments=10, spectral_locus=False, spectral_locus_colour=None, points_size=12, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given *RGB* colourspace array in a scatter plot. Parameters ---------- RGB : array_like *RGB* colourspace array. colourspace : RGB_Colourspace *RGB* colourspace of the *RGB* array. reference_colourspace : unicode, optional **{'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW', 'IPT'}**, Reference colourspace for colour conversion. colourspaces : array_like, optional *RGB* colourspaces to plot the gamuts. 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. points_size : numeric, optional Scatter points size. 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' >>> RGB_scatter_plot(c) # doctest: +SKIP True """ colourspace = get_RGB_colourspace(colourspace) if colourspaces is None: colourspaces = (colourspace.name, ) count_c = len(colourspaces) settings = Structure( **{ 'face_colours': [None] * count_c, 'edge_colours': [(0.25, 0.25, 0.25)] * count_c, 'face_alpha': [0.0] * count_c, 'edge_alpha': [0.1] * count_c, 'standalone': False }) settings.update(kwargs) RGB_colourspaces_gamuts_plot(colourspaces=colourspaces, reference_colourspace=reference_colourspace, segments=segments, display_grid=display_grid, grid_segments=grid_segments, spectral_locus=spectral_locus, spectral_locus_colour=spectral_locus_colour, cmfs=cmfs, **settings) XYZ = RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix) points = XYZ_to_reference_colourspace(XYZ, colourspace.whitepoint, reference_colourspace) axes = matplotlib.pyplot.gca() axes.scatter(points[..., 0], points[..., 1], points[..., 2], color=np.reshape(RGB, (-1, 3)), s=points_size) settings.update({'standalone': True}) settings.update(kwargs) camera(**settings) decorate(**settings) return display(**settings)
def corresponding_chromaticities_prediction_plot(experiment=1, model='Von Kries', transform='CAT02', **kwargs): """ Plots given chromatic adaptation model corresponding chromaticities prediction. Parameters ---------- experiment : int, optional Corresponding chromaticities prediction experiment number. model : unicode, optional Corresponding chromaticities prediction model name. transform : unicode, optional Transformation to use with Von Kries chromatic adaptation model. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> corresponding_chromaticities_prediction_plot() # doctest: +SKIP True """ settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)} settings.update(kwargs) canvas(**settings) model, name = (get_corresponding_chromaticities_prediction_model(model), model) settings.update({ 'title': (('Corresponding Chromaticities Prediction\n{0} ({1}) - ' 'Experiment {2}\nCIE 1976 UCS Chromaticity Diagram').format( name, transform, experiment) if name.lower() in ('von kries', 'vonkries') else ('Corresponding Chromaticities Prediction\n{0} - ' 'Experiment {1}\nCIE 1976 UCS Chromaticity Diagram').format( name, experiment)), 'standalone': False }) settings.update(kwargs) CIE_1976_UCS_chromaticity_diagram_plot(**settings) results = model(experiment, transform=transform) for result in results: name, uvp_t, uvp_m, uvp_p = result pylab.arrow(uvp_t[0], uvp_t[1], uvp_p[0] - uvp_t[0] - 0.1 * (uvp_p[0] - uvp_t[0]), uvp_p[1] - uvp_t[1] - 0.1 * (uvp_p[1] - uvp_t[1]), head_width=0.005, head_length=0.005, linewidth=0.5, color='black') pylab.plot(uvp_t[0], uvp_t[1], 'o', color='white') pylab.plot(uvp_m[0], uvp_m[1], '^', color='white') pylab.plot(uvp_p[0], uvp_p[1], '^', color='black') settings.update({ 'x_tighten': True, 'y_tighten': True, 'limits': (-0.1, 0.7, -0.1, 0.7), 'standalone': True }) boundaries(**settings) decorate(**settings) return display(**settings)
def planckian_locus_CIE_1960_UCS_chromaticity_diagram_plot( illuminants=None, **kwargs): """ Plots the planckian locus and given illuminants in *CIE 1960 UCS Chromaticity Diagram*. Parameters ---------- illuminants : array_like, optional Factory illuminants to plot. 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_1960_UCS_chromaticity_diagram_plot`}, Whether to display the chromaticity diagram background colours. Returns ------- Figure Current figure or None. Raises ------ KeyError If one of the given illuminant is not found in the factory illuminants. Examples -------- >>> ils = ['A', 'C', 'E'] >>> planckian_locus_CIE_1960_UCS_chromaticity_diagram_plot( ... ils) # doctest: +SKIP """ if illuminants is None: illuminants = ('A', 'C', 'E') cmfs = CMFS['CIE 1931 2 Degree Standard Observer'] settings = { 'title': ('{0} Illuminants - Planckian Locus\n' 'CIE 1960 UCS Chromaticity Diagram - ' 'CIE 1931 2 Degree Standard Observer' ).format(', '.join(illuminants)) if illuminants else ('Planckian Locus\nCIE 1960 UCS Chromaticity Diagram - ' 'CIE 1931 2 Degree Standard Observer'), 'standalone': False } settings.update(kwargs) CIE_1960_UCS_chromaticity_diagram_plot(**settings) start, end = 1667, 100000 uv = np.array( [CCT_to_uv(x, 'Robertson 1968', D_uv=0) for x in np.arange(start, end + 250, 250)]) # yapf: disable pylab.plot(uv[..., 0], uv[..., 1], color='black', linewidth=2) for i in (1667, 2000, 2500, 3000, 4000, 6000, 10000): u0, v0 = CCT_to_uv(i, 'Robertson 1968', D_uv=-0.05) u1, v1 = CCT_to_uv(i, 'Robertson 1968', D_uv=0.05) pylab.plot((u0, u1), (v0, v1), color='black', linewidth=2) pylab.annotate( '{0}K'.format(i), xy=(u0, v0), xytext=(0, -10), color='black', textcoords='offset points', size='x-small') for illuminant in illuminants: xy = ILLUMINANTS.get(cmfs.name).get(illuminant) if xy is None: raise KeyError( ('Illuminant "{0}" not found in factory illuminants: ' '"{1}".').format(illuminant, sorted(ILLUMINANTS[cmfs.name].keys()))) uv = UCS_to_uv(XYZ_to_UCS(xy_to_XYZ(xy))) pylab.plot(uv[0], uv[1], 'o', color='white', linewidth=2) pylab.annotate( illuminant, xy=(uv[0], uv[1]), xytext=(-50, 30), color='black', 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_scatter_plot(RGB, colourspace, reference_colourspace='CIE xyY', colourspaces=None, segments=8, display_grid=True, grid_segments=10, spectral_locus=False, spectral_locus_colour=None, points_size=12, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots given *RGB* colourspace array in a scatter plot. Parameters ---------- RGB : array_like *RGB* colourspace array. colourspace : RGB_Colourspace *RGB* colourspace of the *RGB* array. reference_colourspace : unicode, optional **{'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW', 'IPT'}**, Reference colourspace for colour conversion. colourspaces : array_like, optional *RGB* colourspaces to plot the gamuts. 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. points_size : numeric, optional Scatter points size. 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' >>> RGB_scatter_plot(c) # doctest: +SKIP True """ colourspace = get_RGB_colourspace(colourspace) if colourspaces is None: colourspaces = (colourspace.name,) count_c = len(colourspaces) settings = Structure( **{'face_colours': [None] * count_c, 'edge_colours': [(0.25, 0.25, 0.25)] * count_c, 'face_alpha': [0.0] * count_c, 'edge_alpha': [0.1] * count_c, 'standalone': False}) settings.update(kwargs) RGB_colourspaces_gamuts_plot( colourspaces=colourspaces, reference_colourspace=reference_colourspace, segments=segments, display_grid=display_grid, grid_segments=grid_segments, spectral_locus=spectral_locus, spectral_locus_colour=spectral_locus_colour, cmfs=cmfs, **settings) XYZ = RGB_to_XYZ( RGB, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix) points = XYZ_to_reference_colourspace(XYZ, colourspace.whitepoint, reference_colourspace) axes = matplotlib.pyplot.gca() axes.scatter(points[..., 0], points[..., 1], points[..., 2], color=np.reshape(RGB, (-1, 3)), s=points_size) settings.update({'standalone': True}) settings.update(kwargs) camera(**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 multi_spd_colour_quality_scale_bars_plot(spds, **kwargs): """ Plots the *Colour Quality Scale* (CQS) of given illuminants or light sources spectral power distributions. Parameters ---------- spds : array_like Array of illuminants or light sources spectral power distributions to plot the *Colour Quality Scale* (CQS). Other Parameters ---------------- \**kwargs : dict, optional {:func:`boundaries`, :func:`canvas`, :func:`decorate`, :func:`display`}, Please refer to the documentation of the previously listed definitions. labels : bool, optional {:func:`colour_quality_bars_plot`}, Add labels above bars. hatching : bool or None, optional {:func:`colour_quality_bars_plot`}, Use hatching for the bars. hatching_repeat : int, optional {:func:`colour_quality_bars_plot`}, Hatching pattern repeat. Returns ------- Figure Current figure or None. Examples -------- >>> from colour import ( ... ILLUMINANTS_RELATIVE_SPDS, ... LIGHT_SOURCES_RELATIVE_SPDS) >>> illuminant = ILLUMINANTS_RELATIVE_SPDS['F2'] >>> light_source = LIGHT_SOURCES_RELATIVE_SPDS['Kinoton 75P'] >>> multi_spd_colour_quality_scale_bars_plot( # doctest: +SKIP ... [illuminant, light_source]) """ settings = {} settings.update(kwargs) settings.update({'standalone': False}) specifications = [ colour_quality_scale(spd, additional_data=True) for spd in spds ] colour_quality_bars_plot(specifications, **settings) settings = { 'title': 'Colour Quality Scale - {0}'.format(', '.join( [spd.title for spd in spds])) } settings.update(kwargs) 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 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 planckian_locus_CIE_1960_UCS_chromaticity_diagram_plot( illuminants=None, **kwargs): """ Plots the planckian locus and given illuminants in *CIE 1960 UCS Chromaticity Diagram*. Parameters ---------- illuminants : array_like, optional Factory illuminants to plot. \*\*kwargs : \*\* Keywords arguments. Returns ------- bool Definition success. Raises ------ KeyError If one of the given illuminant is not found in the factory illuminants. Examples -------- >>> ils = ['A', 'C', 'E'] >>> planckian_locus_CIE_1960_UCS_chromaticity_diagram_plot(ils) # noqa # doctest: +SKIP True """ if illuminants is None: illuminants = ('A', 'C', 'E') cmfs = CMFS.get('CIE 1931 2 Degree Standard Observer') settings = { 'title': ('{0} Illuminants - Planckian Locus\n' 'CIE 1960 UCS Chromaticity Diagram - ' 'CIE 1931 2 Degree Standard Observer').format( ', '.join(illuminants)) if illuminants else ('Planckian Locus\nCIE 1960 UCS Chromaticity Diagram - ' 'CIE 1931 2 Degree Standard Observer'), 'standalone': False} settings.update(kwargs) if not CIE_1960_UCS_chromaticity_diagram_plot(**settings): return xy_to_uv = lambda x: UCS_to_uv(XYZ_to_UCS(xy_to_XYZ(x))) start, end = 1667, 100000 uv = np.array([CCT_to_uv(x, 0, cmfs=cmfs) for x in np.arange(start, end + 250, 250)]) pylab.plot(uv[:, 0], uv[:, 1], color='black', linewidth=2) for i in [1667, 2000, 2500, 3000, 4000, 6000, 10000]: u0, v0 = CCT_to_uv(i, -0.05) u1, v1 = CCT_to_uv(i, 0.05) pylab.plot([u0, u1], [v0, v1], color='black', linewidth=2) pylab.annotate('{0}K'.format(i), xy=(u0, v0), xytext=(0, -10), textcoords='offset points', size='x-small') for illuminant in illuminants: uv = xy_to_uv(ILLUMINANTS.get(cmfs.name).get(illuminant)) if uv is None: raise KeyError( ('Illuminant "{0}" not found in factory illuminants: ' '"{1}".').format(illuminant, sorted(ILLUMINANTS.get(cmfs.name).keys()))) pylab.plot(uv[0], uv[1], 'o', color='white', linewidth=2) pylab.annotate(illuminant, xy=(uv[0], uv[1]), xytext=(-50, 30), textcoords='offset points', arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=-0.2')) settings.update({'standalone': True}) settings.update(kwargs) return display(**settings)
def spds_CIE_1931_chromaticity_diagram_plot( spds, cmfs='CIE 1931 2 Degree Standard Observer', annotate=True, **kwargs): """ Plots given spectral power distribution chromaticity coordinates into the *CIE 1931 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 ------- Figure Current figure or None. Examples -------- >>> from colour import ILLUMINANTS_RELATIVE_SPDS >>> A = ILLUMINANTS_RELATIVE_SPDS['A'] >>> D65 = ILLUMINANTS_RELATIVE_SPDS['D65'] >>> spds_CIE_1931_chromaticity_diagram_plot([A, D65]) # doctest: +SKIP """ settings = {} settings.update(kwargs) settings.update({'standalone': False}) CIE_1931_chromaticity_diagram_plot(cmfs=cmfs, **settings) for spd in spds: XYZ = spectral_to_XYZ(spd) / 100 xy = XYZ_to_xy(XYZ) pylab.plot(xy[0], xy[1], 'o', color='white') if spd.name is not None and annotate: pylab.annotate(spd.name, xy=xy, xytext=(50, 30), color='black', textcoords='offset points', arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=0.2')) settings.update({ 'x_tighten': True, 'y_tighten': True, 'limits': (-0.1, 0.9, -0.1, 0.9), 'standalone': True}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def colour_checker_plot(colour_checker='ColorChecker 2005', **kwargs): """ Plots given colour checker. Parameters ---------- colour_checker : unicode, optional Color checker name. \**kwargs : dict, optional Keywords arguments. Returns ------- bool Definition success. Raises ------ KeyError If the given colour rendition chart is not found in the factory colour rendition charts. Examples -------- >>> colour_checker_plot() # doctest: +SKIP True """ canvas(**kwargs) colour_checker, name = COLOURCHECKERS.get(colour_checker), colour_checker if colour_checker is None: raise KeyError( ('Colour checker "{0}" not found in ' 'factory colour checkers: "{1}".').format( name, sorted(COLOURCHECKERS.keys()))) _name, data, illuminant = colour_checker colour_parameters = [] for _index, label, x, y, Y in data: XYZ = xyY_to_XYZ((x, y, Y)) RGB = XYZ_to_sRGB(XYZ, illuminant) colour_parameters.append( ColourParameter(label.title(), np.clip(np.ravel(RGB), 0, 1))) background_colour = '0.1' matplotlib.pyplot.gca().patch.set_facecolor(background_colour) width = height = 1.0 spacing = 0.25 across = 6 settings = { 'standalone': False, 'width': width, 'height': height, 'spacing': spacing, 'across': across, 'text_size': 8, 'margins': (-0.125, 0.125, -0.5, 0.125)} settings.update(kwargs) multi_colour_plot(colour_parameters, **settings) text_x = width * (across / 2) + (across * (spacing / 2)) - spacing / 2 text_y = -(len(colour_parameters) / across + spacing / 2) pylab.text(text_x, text_y, '{0} - {1} - Colour Rendition Chart'.format( name, RGB_COLOURSPACES.get('sRGB').name), color='0.95', clip_on=True, ha='center') settings.update({ 'title': name, 'facecolor': background_colour, 'edgecolor': None, 'standalone': True}) 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)
s = [i[1] for i in data.values] data_formated = dict(zip(w, s)) print(data) print(data.values) print(data_formated) spd = SpectralPowerDistribution('Sample', data_formated) illuminant = ILLUMINANTS_RELATIVE_SPDS['D50'] XYZ = spectral_to_XYZ(spd, cmfs, illuminant) print(XYZ) xy = XYZ_to_xy(XYZ) print(xy) CIE_1931_chromaticity_diagram_plot(standalone=False) x, y = xy pylab.plot(x, y, 'o-', color='white') pylab.annotate('test', xy=xy, xytext=(-50, 30), textcoords='offset points', arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=-0.2')) a = display(standalone=False) print(type(a)) figfile = BytesIO() a.savefig(figfile, format='svg') figfile.seek(0) figdata_svg = '<svg' + str(figfile.getvalue()).split('<svg')[1] #figdata_svg = figdata_svg.encode('utf-8') print(figdata_svg)
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 : 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 ------- Figure Current figure or None. 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 """ settings = {} settings.update(kwargs) settings.update({'standalone': False}) CIE_1976_UCS_chromaticity_diagram_plot(cmfs=cmfs, **settings) for spd in spds: 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), color='black', 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.1, 0.7), '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 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 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 : 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. 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 -------- >>> 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 """ settings = {} settings.update(kwargs) settings.update({'standalone': False}) CIE_1976_UCS_chromaticity_diagram_plot(cmfs=cmfs, **settings) for spd in spds: 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), color='black', 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.1, 0.7), 'standalone': True }) 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)