Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
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
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
0
    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)
Exemple #8
0
    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)
Exemple #9
0
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
Exemple #10
0
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)
Exemple #11
0
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)