def RGB_colourspace_volume_coverage_MonteCarlo( colourspace, coverage_sampler, samples=10e6, random_generator=random_triplet_generator, random_state=None ): """ Returns given *RGB* colourspace percentage coverage of an arbitrary volume. Parameters ---------- colourspace : RGB_Colourspace *RGB* colourspace to compute the volume coverage percentage. coverage_sampler : object Python object responsible for checking the volume coverage. samples : numeric, optional Samples count. random_generator : generator, optional Random triplet generator providing the random samples. random_state : RandomState, optional Mersenne Twister pseudo-random number generator to use in the random number generator. Returns ------- float Percentage coverage of volume. Notes ----- - This definition requires *scipy* to be installed. Examples -------- >>> from colour import sRGB_COLOURSPACE as sRGB >>> prng = np.random.RandomState(2) >>> RGB_colourspace_volume_coverage_MonteCarlo( # doctest: +ELLIPSIS ... sRGB, ... is_within_pointer_gamut, ... 10e3, ... random_state=prng) 83... """ if is_scipy_installed(raise_exception=True): random_state = random_state if random_state is not None else np.random.RandomState() # TODO: Investigate for generator yielding directly a ndarray. XYZ = np.asarray(list(random_generator(samples, random_state=random_state))) XYZ_vs = XYZ[coverage_sampler(XYZ)] RGB = XYZ_to_RGB(XYZ_vs, colourspace.whitepoint, colourspace.whitepoint, colourspace.XYZ_to_RGB_matrix) RGB_c = RGB[np.logical_and(np.min(RGB, axis=-1) >= 0, np.max(RGB, axis=-1) <= 1)] return 100 * RGB_c.size / XYZ_vs.size
def is_within_macadam_limits(xyY, illuminant, tolerance=None): """ Returns if given *CIE xyY* colourspace array is within MacAdam limits of given illuminant. Parameters ---------- xyY : array_like *CIE xyY* colourspace array. illuminant : unicode Illuminant. tolerance : numeric, optional Tolerance allowed in the inside-triangle check. Returns ------- bool Is within MacAdam limits. Notes ----- - Input *CIE xyY* colourspace array is in domain [0, 1]. - This definition requires *scipy* to be installed. Examples -------- >>> is_within_macadam_limits(np.array([0.3205, 0.4131, 0.51]), 'A') array(True, dtype=bool) >>> a = np.array([[0.3205, 0.4131, 0.51], ... [0.0005, 0.0031, 0.001]]) >>> is_within_macadam_limits(a, 'A') array([ True, False], dtype=bool) """ if is_scipy_installed(raise_exception=True): from scipy.spatial import Delaunay optimal_colour_stimuli = _XYZ_optimal_colour_stimuli(illuminant) triangulation = _XYZ_OPTIMAL_COLOUR_STIMULI_TRIANGULATIONS_CACHE.get( illuminant) if triangulation is None: _XYZ_OPTIMAL_COLOUR_STIMULI_TRIANGULATIONS_CACHE[illuminant] = \ triangulation = Delaunay(optimal_colour_stimuli) simplex = triangulation.find_simplex(xyY_to_XYZ(xyY), tol=tolerance) simplex = np.where(simplex >= 0, True, False) return simplex
def is_within_mesh_volume(points, mesh, tolerance=None): """ Returns if given points are within given mesh volume using Delaunay triangulation. Parameters ---------- points : array_like Points to check if they are within `mesh` volume. mesh : array_like Points of the volume used to generate the Delaunay triangulation. tolerance : numeric, optional Tolerance allowed in the inside-triangle check. Returns ------- bool Is within mesh volume. Notes ----- - This definition requires *scipy* to be installed. Examples -------- >>> mesh = np.array([[-1.0, -1.0, 1.0], ... [1.0, -1.0, 1.0], ... [1.0, -1.0, -1.0], ... [-1.0, -1.0, -1.0], ... [0.0, 1.0, 0.0]]) >>> is_within_mesh_volume(np.array([0.0005, 0.0031, 0.0010]), mesh) array(True, dtype=bool) >>> a = np.array([[0.0005, 0.0031, 0.0010], ... [0.3205, 0.4131, 0.5100]]) >>> is_within_mesh_volume(a, mesh) array([ True, False], dtype=bool) """ if is_scipy_installed(raise_exception=True): from scipy.spatial import Delaunay triangulation = Delaunay(mesh) simplex = triangulation.find_simplex(points, tol=tolerance) simplex = np.where(simplex >= 0, True, False) return simplex
def is_within_macadam_limits(xyY, illuminant): """ Returns if given *CIE xyY* colourspace matrix is within *MacAdam* limits of given illuminant. Parameters ---------- xyY : array_like, (3,) *CIE xyY* colourspace matrix. illuminant : unicode Illuminant. Returns ------- bool Is within *MacAdam* limits. Notes ----- - Input *CIE xyY* colourspace matrix is in domain [0, 1]. - This definition requires *scipy* to be installed. Examples -------- >>> is_within_macadam_limits((0.3205, 0.4131, 0.51), 'A') True >>> is_within_macadam_limits((0.0005, 0.0031, 0.001), 'A') False """ if is_scipy_installed(raise_exception=True): from scipy.spatial import Delaunay optimal_colour_stimuli = _XYZ_optimal_colour_stimuli(illuminant) triangulation = _XYZ_OPTIMAL_COLOUR_STIMULI_TRIANGULATIONS_CACHE.get( illuminant) if triangulation is None: _XYZ_OPTIMAL_COLOUR_STIMULI_TRIANGULATIONS_CACHE[illuminant] = \ triangulation = Delaunay(optimal_colour_stimuli) simplex = triangulation.find_simplex(np.ravel(xyY_to_XYZ(xyY))) return True if simplex != -1 else False
def __validate_interpolation_range(self, x): """ Validates given point to be in interpolation range. """ below_interpolation_range = x < self.__x[0] above_interpolation_range = x > self.__x[-1] if below_interpolation_range.any(): raise ValueError('"{0}" is below interpolation range.'.format(x)) if above_interpolation_range.any(): raise ValueError('"{0}" is above interpolation range.'.format(x)) if is_scipy_installed(): import scipy.interpolate class CubicSplineInterpolator(scipy.interpolate.interp1d): """ Interpolates a 1-D function using cubic spline interpolation. Notes ----- This class is a wrapper around *scipy.interpolate.interp1d* class. """ def __init__(self, *args, **kwargs): super(CubicSplineInterpolator, self).__init__(kind='cubic', *args, **kwargs)
def __validate_interpolation_range(self, x): """ Validates given point to be in interpolation range. """ below_interpolation_range = x < self.__x[0] above_interpolation_range = x > self.__x[-1] if below_interpolation_range.any(): raise ValueError('"{0}" is below interpolation range.'.format(x)) if above_interpolation_range.any(): raise ValueError('"{0}" is above interpolation range.'.format(x)) if is_scipy_installed(): import scipy.interpolate class CubicSplineInterpolator(scipy.interpolate.interp1d): """ Interpolates a 1-D function using cubic spline interpolation. Notes ----- This class is a wrapper around *scipy.interpolate.interp1d* class. """ def __init__(self, *args, **kwargs): super(CubicSplineInterpolator, self).__init__( kind='cubic', *args, **kwargs)
def RGB_colourspace_volume_coverage_MonteCarlo( colourspace, coverage_sampler, samples=10e6, random_generator=random_triplet_generator, random_state=None): """ Returns given *RGB* colourspace percentage coverage of an arbitrary volume. Parameters ---------- colourspace : RGB_Colourspace *RGB* colourspace to compute the volume coverage percentage. coverage_sampler : object Python object responsible for checking the volume coverage. samples : numeric, optional Samples count. random_generator : generator, optional Random triplet generator providing the random samples. random_state : RandomState, optional Mersenne Twister pseudo-random number generator to use in the random number generator. Returns ------- float Percentage coverage of volume. Notes ----- - This definition requires *scipy* to be installed. Examples -------- >>> from colour import sRGB_COLOURSPACE as sRGB >>> prng = np.random.RandomState(2) >>> RGB_colourspace_volume_coverage_MonteCarlo( # doctest: +ELLIPSIS ... sRGB, ... is_within_pointer_gamut, ... 10e3, ... random_state=prng) 83... """ if is_scipy_installed(raise_exception=True): random_state = (random_state if random_state is not None else np.random.RandomState()) # TODO: Investigate for generator yielding directly a ndarray. XYZ = np.asarray( list(random_generator(samples, random_state=random_state))) XYZ_vs = XYZ[coverage_sampler(XYZ)] RGB = XYZ_to_RGB(XYZ_vs, colourspace.whitepoint, colourspace.whitepoint, colourspace.XYZ_to_RGB_matrix) RGB_c = RGB[np.logical_and( np.min(RGB, axis=-1) >= 0, np.max(RGB, axis=-1) <= 1)] return 100 * RGB_c.size / XYZ_vs.size
def CIE_1931_chromaticity_diagram_colours_plot( surface=1, samples=4096, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots the *CIE 1931 Chromaticity Diagram* colours. Parameters ---------- surface : numeric, optional Generated markers surface. samples : numeric, optional Samples count on one axis. cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. \*\*kwargs : \*\* Keywords arguments. Returns ------- bool Definition success. Examples -------- >>> CIE_1931_chromaticity_diagram_colours_plot() # doctest: +SKIP True """ if is_scipy_installed(raise_exception=True): from scipy.spatial import Delaunay settings = {'figure_size': (64, 64)} settings.update(kwargs) canvas(**settings) cmfs = get_cmfs(cmfs) illuminant = CHROMATICITY_DIAGRAM_DEFAULT_ILLUMINANT triangulation = Delaunay(XYZ_to_xy(cmfs.values, illuminant), qhull_options='QJ') xx, yy = np.meshgrid(np.linspace(0, 1, samples), np.linspace(0, 1, samples)) xy = tstack((xx, yy)) xy = xy[triangulation.find_simplex(xy) > 0] XYZ = xy_to_XYZ(xy) RGB = normalise(XYZ_to_sRGB(XYZ, illuminant), axis=-1) x_dot, y_dot = tsplit(xy) pylab.scatter(x_dot, y_dot, color=RGB, s=surface) settings.update({ 'no_ticks': True, 'bounding_box': (0, 1, 0, 1), 'bbox_inches': 'tight', 'pad_inches': 0}) settings.update(kwargs) ax = matplotlib.pyplot.gca() matplotlib.pyplot.setp(ax, frame_on=False) boundaries(**settings) decorate(**settings) return display(**settings)
def 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 ------- bool Definition success. Examples -------- >>> CIE_1931_chromaticity_diagram_colours_plot() # doctest: +SKIP True """ if is_scipy_installed(raise_exception=True): from scipy.spatial import Delaunay settings = {'figure_size': (64, 64)} settings.update(kwargs) canvas(**settings) cmfs = get_cmfs(cmfs) illuminant = 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(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), 'bbox_inches': 'tight', 'pad_inches': 0 }) settings.update(kwargs) ax = matplotlib.pyplot.gca() matplotlib.pyplot.setp(ax, frame_on=False) boundaries(**settings) decorate(**settings) return display(**settings)