Example #1
0
    def test_closest(self):
        """
        Tests :func:`colour.utilities.array.closest` definition.
        """

        a = np.array([
            24.31357115, 63.62396289, 55.71528816, 62.70988028, 46.84480573,
            25.40026416
        ])

        self.assertEqual(closest(a, 63.05), 62.70988028)

        self.assertEqual(closest(a, 24.90), 25.40026416)

        self.assertEqual(closest(a, 51.15), 46.84480573)
Example #2
0
    def test_closest(self):
        """
        Tests :func:`colour.utilities.array.closest` definition.
        """

        a = np.array([24.31357115,
                      63.62396289,
                      55.71528816,
                      62.70988028,
                      46.84480573,
                      25.40026416])

        self.assertEqual(closest(a, 63.05), 62.70988028)

        self.assertEqual(closest(a, 24.90), 25.40026416)

        self.assertEqual(closest(a, 51.15), 46.84480573)
Example #3
0
def mesopic_weighting_function(
        wavelength,
        Lp,
        source='Blue Heavy',
        method='MOVE',
        photopic_lef=SDS_LEFS_PHOTOPIC['CIE 1924 Photopic Standard Observer'],
        scotopic_lef=SDS_LEFS_SCOTOPIC['CIE 1951 Scotopic Standard Observer']):
    """
    Calculates the mesopic weighting function factor at given wavelength
    :math:`\\lambda` using the photopic luminance :math:`L_p`.

    Parameters
    ----------
    wavelength : numeric or array_like
        Wavelength :math:`\\lambda` to calculate the mesopic weighting function
        factor.
    Lp : numeric
        Photopic luminance :math:`L_p`.
    source : unicode, optional
        **{'Blue Heavy', 'Red Heavy'}**,
        Light source colour temperature.
    method : unicode, optional
        **{'MOVE', 'LRC'}**,
        Method to calculate the weighting factor.
    photopic_lef : SpectralDistribution, optional
        :math:`V(\\lambda)` photopic luminous efficiency function.
    scotopic_lef : SpectralDistribution, optional
        :math:`V^\\prime(\\lambda)` scotopic luminous efficiency function.

    Returns
    -------
    numeric or ndarray
        Mesopic weighting function factor.

    References
    ----------
    :cite:`Wikipedia2005d`

    Examples
    --------
    >>> mesopic_weighting_function(500, 0.2)  # doctest: +ELLIPSIS
    0.7052200...
    """

    mesopic_x_luminance_values = sorted(DATA_MESOPIC_X.keys())
    index = mesopic_x_luminance_values.index(
        closest(mesopic_x_luminance_values, Lp))
    x = DATA_MESOPIC_X[mesopic_x_luminance_values[index]][source][method]

    Vm = (1 - x) * scotopic_lef[wavelength] + x * photopic_lef[wavelength]

    return Vm
Example #4
0
def mesopic_weighting_function(
        wavelength,
        Lp,
        source='Blue Heavy',
        method='MOVE',
        photopic_lef=PHOTOPIC_LEFS['CIE 1924 Photopic Standard Observer'],
        scotopic_lef=SCOTOPIC_LEFS['CIE 1951 Scotopic Standard Observer']):
    """
    Calculates the mesopic weighting function factor at given wavelength
    :math:`\\lambda` using the photopic luminance :math:`L_p`.

    Parameters
    ----------
    wavelength : numeric or array_like
        Wavelength :math:`\\lambda` to calculate the mesopic weighting function
        factor.
    Lp : numeric
        Photopic luminance :math:`L_p`.
    source : unicode, optional
        **{'Blue Heavy', 'Red Heavy'}**,
        Light source colour temperature.
    method : unicode, optional
        **{'MOVE', 'LRC'}**,
        Method to calculate the weighting factor.
    photopic_lef : SpectralDistribution, optional
        :math:`V(\\lambda)` photopic luminous efficiency function.
    scotopic_lef : SpectralDistribution, optional
        :math:`V^\\prime(\\lambda)` scotopic luminous efficiency function.

    Returns
    -------
    numeric or ndarray
        Mesopic weighting function factor.

    References
    ----------
    :cite:`Wikipedia2005d`

    Examples
    --------
    >>> mesopic_weighting_function(500, 0.2)  # doctest: +ELLIPSIS
    0.7052200...
    """

    mesopic_x_luminance_values = sorted(MESOPIC_X_DATA.keys())
    index = mesopic_x_luminance_values.index(
        closest(mesopic_x_luminance_values, Lp))
    x = MESOPIC_X_DATA[mesopic_x_luminance_values[index]][source][method]

    Vm = (1 - x) * scotopic_lef[wavelength] + x * photopic_lef[wavelength]

    return Vm
Example #5
0
def mesopic_weighting_function(wavelength,
                               Lp,
                               source='Blue Heavy',
                               method='MOVE',
                               photopic_lef=PHOTOPIC_LEFS.get(
                                   'CIE 1924 Photopic Standard Observer'),
                               scotopic_lef=SCOTOPIC_LEFS.get(
                                   'CIE 1951 Scotopic Standard Observer')):
    """
    Calculates the mesopic weighting function factor at given wavelength
    :math:`\lambda` using the photopic luminance :math:`L_p`.

    Parameters
    ----------
    wavelength : numeric or array_like
        Wavelength :math:`\lambda` to calculate the mesopic weighting function
        factor.
    Lp : numeric
        Photopic luminance :math:`L_p`.
    source : unicode, optional
        **{'Blue Heavy', 'Red Heavy'}**,
        Light source colour temperature.
    method : unicode, optional
        **{'MOVE', 'LRC'}**,
        Method to calculate the weighting factor.
    photopic_lef : SpectralPowerDistribution, optional
        :math:`V(\lambda)` photopic luminous efficiency function.
    scotopic_lef : SpectralPowerDistribution, optional
        :math:`V^\prime(\lambda)` scotopic luminous efficiency function.

    Returns
    -------
    numeric or ndarray
        Mesopic weighting function factor.

    Examples
    --------
    >>> mesopic_weighting_function(500, 0.2)  # doctest: +ELLIPSIS
    0.7052200...
    """

    mesopic_x_luminance_values = sorted(MESOPIC_X_DATA.keys())
    index = mesopic_x_luminance_values.index(
        closest(mesopic_x_luminance_values, Lp))
    x = MESOPIC_X_DATA.get(
        mesopic_x_luminance_values[index]).get(source).get(method)

    Vm = ((1 - x) *
          scotopic_lef.get(wavelength) + x * photopic_lef.get(wavelength))

    return Vm
Example #6
0
    def test_closest(self):
        """Test :func:`colour.utilities.array.closest` definition."""

        a = np.array([
            24.31357115,
            63.62396289,
            55.71528816,
            62.70988028,
            46.84480573,
            25.40026416,
        ])

        self.assertEqual(closest(a, 63.05), 62.70988028)

        self.assertEqual(closest(a, 51.15), 46.84480573)

        self.assertEqual(closest(a, 24.90), 25.40026416)

        np.testing.assert_almost_equal(
            closest(a, np.array([63.05, 51.15, 24.90])),
            np.array([62.70988028, 46.84480573, 25.40026416]),
            decimal=7,
        )
Example #7
0
    def domain_distance(self, a):
        """
        Returns the euclidean distance between given array and independent
        domain :math:`x` closest element.

        Parameters
        ----------
        a : numeric or array_like
            :math:`a` variable to compute the euclidean distance with
            independent domain :math:`x` variable.

        Returns
        -------
        numeric or array_like
            Euclidean distance between independent domain :math:`x` variable
            and given :math:`a` variable.
        """

        n = closest(self.domain, a)

        return as_numeric(np.abs(a - n))
Example #8
0
    def domain_distance(self, a: FloatingOrArrayLike) -> FloatingOrNDArray:
        """
        Return the euclidean distance between given array and independent
        domain :math:`x` closest element.

        Parameters
        ----------
        a
            Variable :math:`a` to compute the euclidean distance with
            independent domain variable :math:`x`.

        Returns
        -------
        :class:`numpy.floating` or :class:`numpy.ndarray`
            Euclidean distance between independent domain variable :math:`x`
            and given variable :math:`a`.
        """

        n = closest(self.domain, a)

        return as_float(np.abs(a - n))
Example #9
0
    def domain_distance(self, a):
        """
        Returns the euclidean distance between given array and independent
        domain :math:`x` closest element.

        Parameters
        ----------
        a : numeric or array_like
            :math:`a` variable to compute the euclidean distance with
            independent domain :math:`x` variable.

        Returns
        -------
        numeric or array_like
            Euclidean distance between independent domain :math:`x` variable
            and given :math:`a` variable.
        """

        n = closest(self.domain, a)

        return as_float(np.abs(a - n))
Example #10
0
def matrix_augmented_Cheung2004(RGB, terms=3):
    """
    Performs polynomial expansion of given *RGB* colourspace array using
    *Cheung et al. (2004)* method.

    Parameters
    ----------
    RGB : array_like
        *RGB* colourspace array to expand.
    terms : int, optional
        Number of terms of the expanded polynomial, must be one of
        *[3, 5, 7, 8, 10, 11, 14, 16, 17, 19, 20, 22]*.

    Returns
    -------
    ndarray
        Expanded *RGB* colourspace array.

    Notes
    -----
    -   This definition combines the augmented matrices given in
        :cite:`Cheung2004` and :cite:`Westland2004`.

    References
    ----------
    :cite:`Cheung2004`, :cite:`Westland2004`

    Examples
    --------
    >>> RGB = np.array([0.17224810, 0.09170660, 0.06416938])
    >>> matrix_augmented_Cheung2004(RGB, terms=5)  # doctest: +ELLIPSIS
    array([ 0.1722481...,  0.0917066...,  0.0641693...,  0.0010136...,  1...])
    """

    R, G, B = tsplit(RGB)
    tail = ones(R.shape)

    existing_terms = np.array([3, 5, 7, 8, 10, 11, 14, 16, 17, 19, 20, 22])
    closest_terms = as_int(closest(existing_terms, terms))
    if closest_terms != terms:
        raise ValueError('"Cheung et al. (2004)" method does not define '
                         'an augmented matrix with {0} terms, '
                         'closest augmented matrix has {1} terms!'.format(
                             terms, closest_terms))

    if terms == 3:
        return RGB
    elif terms == 5:
        return tstack([
            R,
            G,
            B,
            R * G * B,
            tail,
        ])
    elif terms == 7:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            tail,
        ])
    elif terms == 8:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R * G * B,
            tail,
        ])
    elif terms == 10:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            tail,
        ])
    elif terms == 11:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            tail,
        ])
    elif terms == 14:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            R**3,
            G**3,
            B**3,
            tail,
        ])
    elif terms == 16:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            R**2 * G,
            G**2 * B,
            B**2 * R,
            R**3,
            G**3,
            B**3,
        ])
    elif terms == 17:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            R**2 * G,
            G**2 * B,
            B**2 * R,
            R**3,
            G**3,
            B**3,
            tail,
        ])
    elif terms == 19:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            R**2 * G,
            G**2 * B,
            B**2 * R,
            R**2 * B,
            G**2 * R,
            B**2 * G,
            R**3,
            G**3,
            B**3,
        ])
    elif terms == 20:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            R**2 * G,
            G**2 * B,
            B**2 * R,
            R**2 * B,
            G**2 * R,
            B**2 * G,
            R**3,
            G**3,
            B**3,
            tail,
        ])
    elif terms == 22:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            R**2 * G,
            G**2 * B,
            B**2 * R,
            R**2 * B,
            G**2 * R,
            B**2 * G,
            R**3,
            G**3,
            B**3,
            R**2 * G * B,
            R * G**2 * B,
            R * G * B**2,
        ])
Example #11
0
def polynomial_expansion_Finlayson2015(RGB,
                                       degree=1,
                                       root_polynomial_expansion=True):
    """
    Performs polynomial expansion of given *RGB* colourspace array using
    *Finlayson et al. (2015)* method.

    Parameters
    ----------
    RGB : array_like
        *RGB* colourspace array to expand.
    degree : int, optional
        Expanded polynomial degree.
    root_polynomial_expansion : bool
        Whether to use the root-polynomials set for the expansion.

    Returns
    -------
    ndarray
        Expanded *RGB* colourspace array.

    References
    ----------
    :cite:`Finlayson2015`

    Examples
    --------
    >>> RGB = np.array([0.17224810, 0.09170660, 0.06416938])
    >>> polynomial_expansion_Finlayson2015(RGB, degree=2)  # doctest: +ELLIPSIS
    array([ 0.1722481...,  0.0917066...,  0.0641693...,  0.1256832...,  \
0.0767121...,
            0.1051335...])
    """

    R, G, B = tsplit(RGB)

    # TODO: Generalise polynomial expansion.
    existing_degrees = np.array([1, 2, 3, 4])
    closest_degree = as_int(closest(existing_degrees, degree))
    if closest_degree != degree:
        raise ValueError('"Finlayson et al. (2015)" method does not define '
                         'a polynomial expansion for {0} degree, '
                         'closest polynomial expansion is {1} degree!'.format(
                             degree, closest_degree))

    if degree == 1:
        return RGB
    elif degree == 2:
        if root_polynomial_expansion:
            return tstack([
                R,
                G,
                B,
                spow(R * G, 1 / 2),
                spow(G * B, 1 / 2),
                spow(R * B, 1 / 2),
            ])

        else:
            return tstack([
                R,
                G,
                B,
                R**2,
                G**2,
                B**2,
                R * G,
                G * B,
                R * B,
            ])
    elif degree == 3:
        if root_polynomial_expansion:
            return tstack([
                R,
                G,
                B,
                spow(R * G, 1 / 2),
                spow(G * B, 1 / 2),
                spow(R * B, 1 / 2),
                spow(R * G**2, 1 / 3),
                spow(G * B**2, 1 / 3),
                spow(R * B**2, 1 / 3),
                spow(G * R**2, 1 / 3),
                spow(B * G**2, 1 / 3),
                spow(B * R**2, 1 / 3),
                spow(R * G * B, 1 / 3),
            ])
        else:
            return tstack([
                R,
                G,
                B,
                R**2,
                G**2,
                B**2,
                R * G,
                G * B,
                R * B,
                R**3,
                G**3,
                B**3,
                R * G**2,
                G * B**2,
                R * B**2,
                G * R**2,
                B * G**2,
                B * R**2,
                R * G * B,
            ])
    elif degree == 4:
        if root_polynomial_expansion:
            return tstack([
                R,
                G,
                B,
                spow(R * G, 1 / 2),
                spow(G * B, 1 / 2),
                spow(R * B, 1 / 2),
                spow(R * G**2, 1 / 3),
                spow(G * B**2, 1 / 3),
                spow(R * B**2, 1 / 3),
                spow(G * R**2, 1 / 3),
                spow(B * G**2, 1 / 3),
                spow(B * R**2, 1 / 3),
                spow(R * G * B, 1 / 3),
                spow(R**3 * G, 1 / 4),
                spow(R**3 * B, 1 / 4),
                spow(G**3 * R, 1 / 4),
                spow(G**3 * B, 1 / 4),
                spow(B**3 * R, 1 / 4),
                spow(B**3 * G, 1 / 4),
                spow(R**2 * G * B, 1 / 4),
                spow(G**2 * R * B, 1 / 4),
                spow(B**2 * R * G, 1 / 4),
            ])
        else:
            return tstack([
                R,
                G,
                B,
                R**2,
                G**2,
                B**2,
                R * G,
                G * B,
                R * B,
                R**3,
                G**3,
                B**3,
                R * G**2,
                G * B**2,
                R * B**2,
                G * R**2,
                B * G**2,
                B * R**2,
                R * G * B,
                R**4,
                G**4,
                B**4,
                R**3 * G,
                R**3 * B,
                G**3 * R,
                G**3 * B,
                B**3 * R,
                B**3 * G,
                R**2 * G**2,
                G**2 * B**2,
                R**2 * B**2,
                R**2 * G * B,
                G**2 * R * B,
                B**2 * R * G,
            ])
Example #12
0
def mesopic_weighting_function(
    wavelength: FloatingOrArrayLike,
    L_p: Floating,
    source: Union[Literal["Blue Heavy", "Red Heavy"], str] = "Blue Heavy",
    method: Union[Literal["MOVE", "LRC"], str] = "MOVE",
    photopic_lef: Optional[SpectralDistribution] = None,
    scotopic_lef: Optional[SpectralDistribution] = None,
) -> FloatingOrNDArray:
    """
    Calculate the mesopic weighting function factor :math:`V_m` at given
    wavelength :math:`\\lambda` using the photopic luminance :math:`L_p`.

    Parameters
    ----------
    wavelength
        Wavelength :math:`\\lambda` to calculate the mesopic weighting function
        factor.
    L_p
        Photopic luminance :math:`L_p`.
    source
        Light source colour temperature.
    method
        Method to calculate the weighting factor.
    photopic_lef
        :math:`V(\\lambda)` photopic luminous efficiency function, default to
        the *CIE 1924 Photopic Standard Observer*.
    scotopic_lef
        :math:`V^\\prime(\\lambda)` scotopic luminous efficiency function,
        default to the *CIE 1951 Scotopic Standard Observer*.

    Returns
    -------
    :class:`numpy.floating` or :class:`numpy.ndarray`
        Mesopic weighting function factor :math:`V_m`.

    References
    ----------
    :cite:`Wikipedia2005d`

    Examples
    --------
    >>> mesopic_weighting_function(500, 0.2)  # doctest: +ELLIPSIS
    0.7052200...
    """

    photopic_lef = cast(
        SpectralDistribution,
        optional(
            photopic_lef,
            SDS_LEFS_PHOTOPIC["CIE 1924 Photopic Standard Observer"],
        ),
    )

    scotopic_lef = cast(
        SpectralDistribution,
        optional(
            scotopic_lef,
            SDS_LEFS_SCOTOPIC["CIE 1951 Scotopic Standard Observer"],
        ),
    )

    source = validate_method(
        source,
        ["Blue Heavy", "Red Heavy"],
        '"{0}" light source colour temperature is invalid, '
        "it must be one of {1}!",
    )
    method = validate_method(method, ["MOVE", "LRC"])

    mesopic_x_luminance_values = sorted(DATA_MESOPIC_X.keys())
    index = mesopic_x_luminance_values.index(
        closest(mesopic_x_luminance_values, L_p))
    x = DATA_MESOPIC_X[mesopic_x_luminance_values[index]][source][method]

    V_m = (1 - x) * scotopic_lef[wavelength] + x * photopic_lef[wavelength]

    return V_m
Example #13
0
def augmented_matrix_Cheung2004(RGB, terms=3):
    """
    Performs polynomial expansion of given *RGB* colourspace array using
    *Cheung et al. (2004)* method.

    Parameters
    ----------
    RGB : array_like
        *RGB* colourspace array to expand.
    terms : int, optional
        Number of terms of the expanded polynomial, must be one of
        *[3, 5, 7, 8, 10, 11, 14, 16, 17, 19, 20, 22]*.

    Returns
    -------
    ndarray
        Expanded *RGB* colourspace array.

    Notes
    -----
    -   This definition combines the augmented matrices given in
        :cite:`Cheung2004` and :cite:`Westland2004`.

    References
    ----------
    :cite:`Cheung2004`, :cite:`Westland2004`

    Examples
    --------
    >>> RGB = np.array([0.17224810, 0.09170660, 0.06416938])
    >>> augmented_matrix_Cheung2004(RGB, terms=5)  # doctest: +ELLIPSIS
    array([ 0.1722481...,  0.0917066...,  0.0641693...,  0.0010136...,  1...])
    """

    R, G, B = tsplit(RGB)
    ones = np.ones(R.shape)

    existing_terms = np.array([3, 5, 7, 8, 10, 11, 14, 16, 17, 19, 20, 22])
    closest_terms = as_int(closest(existing_terms, terms))
    if closest_terms != terms:
        raise ValueError('"Cheung et al. (2004)" method does not define '
                         'an augmented matrix with {0} terms, '
                         'closest augmented matrix has {1} terms!'.format(
                             terms, closest_terms))

    if terms == 3:
        return RGB
    elif terms == 5:
        return tstack([R, G, B, R * G * B, ones])
    elif terms == 7:
        return tstack([R, G, B, R * G, R * B, G * B, ones])
    elif terms == 8:
        return tstack([R, G, B, R * G, R * B, G * B, R * G * B, ones])
    elif terms == 10:
        return tstack(
            [R, G, B, R * G, R * B, G * B, R ** 2, G ** 2, B ** 2, ones])
    elif terms == 11:
        return tstack([
            R, G, B, R * G, R * B, G * B, R ** 2, G ** 2, B ** 2, R * G * B,
            ones
        ])
    elif terms == 14:
        return tstack([
            R, G, B, R * G, R * B, G * B, R ** 2, G ** 2, B ** 2, R * G * B, R
            ** 3, G ** 3, B ** 3, ones
        ])
    elif terms == 16:
        return tstack([
            R, G, B, R * G, R * B, G * B, R ** 2, G ** 2, B ** 2, R * G * B,
            R ** 2 * G, G ** 2 * B, B ** 2 * R, R ** 3, G ** 3, B ** 3
        ])
    elif terms == 17:
        return tstack([
            R, G, B, R * G, R * B, G * B, R ** 2, G ** 2, B ** 2, R * G * B,
            R ** 2 * G, G ** 2 * B, B ** 2 * R, R ** 3, G ** 3, B ** 3, ones
        ])
    elif terms == 19:
        return tstack([
            R, G, B, R * G, R * B, G * B, R ** 2, G ** 2, B ** 2, R * G * B,
            R ** 2 * G, G ** 2 * B, B ** 2 * R, R ** 2 * B, G ** 2 * R,
            B ** 2 * G, R ** 3, G ** 3, B ** 3
        ])
    elif terms == 20:
        return tstack([
            R, G, B, R * G, R * B, G * B, R ** 2, G ** 2, B ** 2, R * G * B,
            R ** 2 * G, G ** 2 * B, B ** 2 * R, R ** 2 * B, G ** 2 * R,
            B ** 2 * G, R ** 3, G ** 3, B ** 3, ones
        ])
    elif terms == 22:
        return tstack([
            R, G, B, R * G, R * B, G * B, R ** 2, G ** 2, B ** 2, R * G * B,
            R ** 2 * G, G ** 2 * B, B ** 2 * R, R ** 2 * B, G ** 2 * R,
            B ** 2 * G, R ** 3, G ** 3, B ** 3, R ** 2 * G * B, R * G ** 2 * B,
            R * G * B ** 2
        ])
Example #14
0
def polynomial_expansion_Finlayson2015(RGB,
                                       degree=1,
                                       root_polynomial_expansion=True):
    """
    Performs polynomial expansion of given *RGB* colourspace array using
    *Finlayson et al. (2015)* method.

    Parameters
    ----------
    RGB : array_like
        *RGB* colourspace array to expand.
    degree : int, optional
        Expanded polynomial degree.
    root_polynomial_expansion : bool
        Whether to use the root-polynomials set for the expansion.

    Returns
    -------
    ndarray
        Expanded *RGB* colourspace array.

    References
    ----------
    :cite:`Finlayson2015`

    Examples
    --------
    >>> RGB = np.array([0.17224810, 0.09170660, 0.06416938])
    >>> polynomial_expansion_Finlayson2015(RGB, degree=2)  # doctest: +ELLIPSIS
    array([ 0.1722481...,  0.0917066...,  0.06416938...\
,  0.0078981...,  0.0029423...,
            0.0055265...])
    """

    R, G, B = tsplit(RGB)

    # TODO: Generalise polynomial expansion.
    existing_degrees = np.array([1, 2, 3, 4])
    closest_degree = as_int(closest(existing_degrees, degree))
    if closest_degree != degree:
        raise ValueError('"Finlayson et al. (2015)" method does not define '
                         'a polynomial expansion for {0} degree, '
                         'closest polynomial expansion is {1} degree!'.format(
                             degree, closest_degree))

    if degree == 1:
        return RGB
    elif degree == 2:
        if root_polynomial_expansion:
            return tstack([
                R, G, B, (R * G) ** 1 / 2, (G * B) ** 1 / 2, (R * B) ** 1 / 2
            ])

        else:
            return tstack(
                [R, G, B, R ** 2, G ** 2, B ** 2, R * G, G * B, R * B])
    elif degree == 3:
        if root_polynomial_expansion:
            return tstack([
                R, G, B, (R * G) ** 1 / 2, (G * B) ** 1 / 2, (R * B) ** 1 / 2,
                (R * G ** 2) ** 1 / 3, (G * B ** 2) ** 1 / 3,
                (R * B ** 2) ** 1 / 3, (G * R ** 2) ** 1 / 3,
                (B * G ** 2) ** 1 / 3, (B * R ** 2) ** 1 / 3,
                (R * G * B) ** 1 / 3
            ])
        else:
            return tstack([
                R, G, B, R ** 2, G ** 2, B ** 2, R * G, G * B, R * B, R ** 3, G
                ** 3, B ** 3, R * G ** 2, G * B ** 2, R * B ** 2, G * R ** 2,
                B * G ** 2, B * R ** 2, R * G * B
            ])
    elif degree == 4:
        if root_polynomial_expansion:
            return tstack([
                R, G, B, (R * G) ** 1 / 2, (G * B) ** 1 / 2, (R * B) ** 1 / 2,
                (R * G ** 2) ** 1 / 3, (G * B ** 2) ** 1 / 3,
                (R * B ** 2) ** 1 / 3, (G * R ** 2) ** 1 / 3,
                (B * G ** 2) ** 1 / 3, (B * R ** 2) ** 1 / 3,
                (R * G * B) ** 1 / 3, (R ** 3 * G) ** 1 / 4,
                (R ** 3 * B) ** 1 / 4, (G ** 3 * R) ** 1 / 4,
                (G ** 3 * B) ** 1 / 4, (B ** 3 * R) ** 1 / 4,
                (B ** 3 * G) ** 1 / 4, (R ** 2 * G * B) ** 1 / 4,
                (G ** 2 * R * B) ** 1 / 4, (B ** 2 * R * G) ** 1 / 4
            ])
        else:
            return tstack([
                R, G, B, R ** 2, G ** 2, B ** 2, R * G, G * B, R * B, R ** 3, G
                ** 3, B ** 3, R * G ** 2, G * B ** 2, R * B ** 2, G * R ** 2,
                B * G ** 2, B * R ** 2, R * G * B, R ** 4, G ** 4, B ** 4,
                R ** 3 * G, R ** 3 * B, G ** 3 * R, G ** 3 * B, B ** 3 * R,
                B ** 3 * G, R ** 2 * G ** 2, G ** 2 * B ** 2, R ** 2 * B ** 2,
                R ** 2 * G * B, G ** 2 * R * B, B ** 2 * R * G
            ])
Example #15
0
def polynomial_expansion_Finlayson2015(
    RGB: ArrayLike,
    degree: Literal[1, 2, 3, 4] = 1,
    root_polynomial_expansion: Boolean = True,
) -> NDArray:
    """
    Perform polynomial expansion of given *RGB* colourspace array using
    *Finlayson et al. (2015)* method.

    Parameters
    ----------
    RGB
        *RGB* colourspace array to expand.
    degree
        Expanded polynomial degree.
    root_polynomial_expansion
        Whether to use the root-polynomials set for the expansion.

    Returns
    -------
    :class:`numpy.ndarray`
        Expanded *RGB* colourspace array.

    References
    ----------
    :cite:`Finlayson2015`

    Examples
    --------
    >>> RGB = np.array([0.17224810, 0.09170660, 0.06416938])
    >>> polynomial_expansion_Finlayson2015(RGB, degree=2)  # doctest: +ELLIPSIS
    array([ 0.1722481...,  0.0917066...,  0.0641693...,  0.1256832...,  \
0.0767121...,
            0.1051335...])
    """

    RGB = as_float_array(RGB)

    R, G, B = tsplit(RGB)

    # TODO: Generalise polynomial expansion.
    existing_degrees = np.array([1, 2, 3, 4])
    closest_degree = as_int(closest(existing_degrees, degree))
    if closest_degree != degree:
        raise ValueError(
            f'"Finlayson et al. (2015)" method does not define a polynomial '
            f"expansion for {degree} degree, closest polynomial expansion is "
            f"{closest_degree} degree!")

    if degree == 1:
        return RGB
    elif degree == 2:
        if root_polynomial_expansion:
            return tstack([
                R,
                G,
                B,
                spow(R * G, 1 / 2),
                spow(G * B, 1 / 2),
                spow(R * B, 1 / 2),
            ])

        else:
            return tstack([
                R,
                G,
                B,
                R**2,
                G**2,
                B**2,
                R * G,
                G * B,
                R * B,
            ])
    elif degree == 3:
        if root_polynomial_expansion:
            return tstack([
                R,
                G,
                B,
                spow(R * G, 1 / 2),
                spow(G * B, 1 / 2),
                spow(R * B, 1 / 2),
                spow(R * G**2, 1 / 3),
                spow(G * B**2, 1 / 3),
                spow(R * B**2, 1 / 3),
                spow(G * R**2, 1 / 3),
                spow(B * G**2, 1 / 3),
                spow(B * R**2, 1 / 3),
                spow(R * G * B, 1 / 3),
            ])
        else:
            return tstack([
                R,
                G,
                B,
                R**2,
                G**2,
                B**2,
                R * G,
                G * B,
                R * B,
                R**3,
                G**3,
                B**3,
                R * G**2,
                G * B**2,
                R * B**2,
                G * R**2,
                B * G**2,
                B * R**2,
                R * G * B,
            ])
    elif degree == 4:
        if root_polynomial_expansion:
            return tstack([
                R,
                G,
                B,
                spow(R * G, 1 / 2),
                spow(G * B, 1 / 2),
                spow(R * B, 1 / 2),
                spow(R * G**2, 1 / 3),
                spow(G * B**2, 1 / 3),
                spow(R * B**2, 1 / 3),
                spow(G * R**2, 1 / 3),
                spow(B * G**2, 1 / 3),
                spow(B * R**2, 1 / 3),
                spow(R * G * B, 1 / 3),
                spow(R**3 * G, 1 / 4),
                spow(R**3 * B, 1 / 4),
                spow(G**3 * R, 1 / 4),
                spow(G**3 * B, 1 / 4),
                spow(B**3 * R, 1 / 4),
                spow(B**3 * G, 1 / 4),
                spow(R**2 * G * B, 1 / 4),
                spow(G**2 * R * B, 1 / 4),
                spow(B**2 * R * G, 1 / 4),
            ])
        else:
            return tstack([
                R,
                G,
                B,
                R**2,
                G**2,
                B**2,
                R * G,
                G * B,
                R * B,
                R**3,
                G**3,
                B**3,
                R * G**2,
                G * B**2,
                R * B**2,
                G * R**2,
                B * G**2,
                B * R**2,
                R * G * B,
                R**4,
                G**4,
                B**4,
                R**3 * G,
                R**3 * B,
                G**3 * R,
                G**3 * B,
                B**3 * R,
                B**3 * G,
                R**2 * G**2,
                G**2 * B**2,
                R**2 * B**2,
                R**2 * G * B,
                G**2 * R * B,
                B**2 * R * G,
            ])
Example #16
0
def matrix_augmented_Cheung2004(
    RGB: ArrayLike,
    terms: Literal[3, 5, 7, 8, 10, 11, 14, 16, 17, 19, 20, 22] = 3,
) -> NDArray:
    """
    Perform polynomial expansion of given *RGB* colourspace array using
    *Cheung et al. (2004)* method.

    Parameters
    ----------
    RGB
        *RGB* colourspace array to expand.
    terms
        Number of terms of the expanded polynomial.

    Returns
    -------
    :class:`numpy.ndarray`
        Expanded *RGB* colourspace array.

    Notes
    -----
    -   This definition combines the augmented matrices given in
        :cite:`Cheung2004` and :cite:`Westland2004`.

    References
    ----------
    :cite:`Cheung2004`, :cite:`Westland2004`

    Examples
    --------
    >>> RGB = np.array([0.17224810, 0.09170660, 0.06416938])
    >>> matrix_augmented_Cheung2004(RGB, terms=5)  # doctest: +ELLIPSIS
    array([ 0.1722481...,  0.0917066...,  0.0641693...,  0.0010136...,  1...])
    """

    RGB = as_float_array(RGB)

    R, G, B = tsplit(RGB)
    tail = ones(R.shape)

    existing_terms = np.array([3, 5, 7, 8, 10, 11, 14, 16, 17, 19, 20, 22])
    closest_terms = as_int(closest(existing_terms, terms))
    if closest_terms != terms:
        raise ValueError(
            f'"Cheung et al. (2004)" method does not define an augmented '
            f"matrix with {terms} terms, closest augmented matrix has "
            f"{closest_terms} terms!")

    if terms == 3:
        return RGB
    elif terms == 5:
        return tstack([
            R,
            G,
            B,
            R * G * B,
            tail,
        ])
    elif terms == 7:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            tail,
        ])
    elif terms == 8:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R * G * B,
            tail,
        ])
    elif terms == 10:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            tail,
        ])
    elif terms == 11:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            tail,
        ])
    elif terms == 14:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            R**3,
            G**3,
            B**3,
            tail,
        ])
    elif terms == 16:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            R**2 * G,
            G**2 * B,
            B**2 * R,
            R**3,
            G**3,
            B**3,
        ])
    elif terms == 17:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            R**2 * G,
            G**2 * B,
            B**2 * R,
            R**3,
            G**3,
            B**3,
            tail,
        ])
    elif terms == 19:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            R**2 * G,
            G**2 * B,
            B**2 * R,
            R**2 * B,
            G**2 * R,
            B**2 * G,
            R**3,
            G**3,
            B**3,
        ])
    elif terms == 20:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            R**2 * G,
            G**2 * B,
            B**2 * R,
            R**2 * B,
            G**2 * R,
            B**2 * G,
            R**3,
            G**3,
            B**3,
            tail,
        ])
    elif terms == 22:
        return tstack([
            R,
            G,
            B,
            R * G,
            R * B,
            G * B,
            R**2,
            G**2,
            B**2,
            R * G * B,
            R**2 * G,
            G**2 * B,
            B**2 * R,
            R**2 * B,
            G**2 * R,
            B**2 * G,
            R**3,
            G**3,
            B**3,
            R**2 * G * B,
            R * G**2 * B,
            R * G * B**2,
        ])