Source code for colour.colorimetry.uniformity

"""
Spectral Uniformity
===================

Define the objects to compute the *spectral uniformity*
(or *spectral flatness*) of spectral distributions.

References
----------
-   :cite:`David2015` : David, A., Fini, P. T., Houser, K. W., Ohno, Y.,
    Royer, M. P., Smet, K. A. G., Wei, M., & Whitehead, L. (2015). Development
    of the IES method for evaluating the color rendition of light sources.
    Optics Express, 23(12), 15888. doi:10.1364/OE.23.015888
"""

from __future__ import annotations

import numpy as np

from colour.colorimetry import (
    MultiSpectralDistributions,
    SpectralDistribution,
    sds_and_msds_to_msds,
)
from colour.hints import NDArrayFloat, Sequence

__author__ = "Colour Developers"
__copyright__ = "Copyright 2013 Colour Developers"
__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
__maintainer__ = "Colour Developers"
__email__ = "colour-developers@colour-science.org"
__status__ = "Production"

__all__ = [
    "spectral_uniformity",
]


[docs] def spectral_uniformity( sds: ( Sequence[SpectralDistribution | MultiSpectralDistributions] | SpectralDistribution | MultiSpectralDistributions ), use_second_order_derivatives: bool = False, ) -> NDArrayFloat: """ Compute the *spectral uniformity* (or *spectral flatness*) of given spectral distributions. Spectral uniformity :math:`(r')^2` is computed as follows: :math:`mean((r'_1)^2, (r'_2)^2, ..., (r'_n)^2)` where :math:`(r'_i)^2` is the first-order derivative, squared, of the reflectance :math:`r_i` of a test sample. Parameters ---------- sds Spectral distributions or multi-spectral distributions to compute the spectral uniformity of. `sds` can be a single :class:`colour.MultiSpectralDistributions` class instance, a list of :class:`colour.MultiSpectralDistributions` class instances or a List of :class:`colour.SpectralDistribution` class instances. use_second_order_derivatives Whether to use the second-order derivatives in the computations. Returns ------- :class:`numpy.ndarray` Spectral uniformity. Warnings -------- The spectral distributions must have the same spectral shape. References ---------- :cite:`David2015` Examples -------- >>> from colour.quality.datasets import SDS_TCS >>> spectral_uniformity(SDS_TCS.values()) # doctest: +ELLIPSIS array([ 9.5514285...e-06, 1.1482142...e-05, 1.8784285...e-05, 2.8711428...e-05, 3.1971428...e-05, 3.2342857...e-05, 3.3850000...e-05, 3.9925714...e-05, 4.1333571...e-05, 2.4002142...e-05, 5.7621428...e-06, 1.4757142...e-06, 9.7928571...e-07, 2.0057142...e-06, 3.7157142...e-06, 5.7678571...e-06, 7.5557142...e-06, 7.4635714...e-06, 5.7492857...e-06, 3.8692857...e-06, 3.5407142...e-06, 4.4742857...e-06, 5.6435714...e-06, 7.6371428...e-06, 1.0171428...e-05, 1.2254285...e-05, 1.4810000...e-05, 1.6517142...e-05, 1.5430714...e-05, 1.4536428...e-05, 1.4037857...e-05, 1.1587857...e-05, 1.0743571...e-05, 1.0979285...e-05, 1.0398571...e-05, 8.2971428...e-06, 6.3057142...e-06, 5.0942857...e-06, 4.8500000...e-06, 5.5371428...e-06, 6.4128571...e-06, 7.2592857...e-06, 7.7750000...e-06, 7.1607142...e-06, 6.6635714...e-06, 6.7328571...e-06, 7.5307142...e-06, 1.0733571...e-05, 1.6234285...e-05, 2.2570714...e-05, 2.7056428...e-05, 2.7781428...e-05, 2.5025714...e-05, 1.7966428...e-05, 1.0505000...e-05, 5.9657142...e-06, 3.6421428...e-06, 2.1664285...e-06, 1.2935714...e-06, 8.3642857...e-07, 7.2500000...e-07, 6.3928571...e-07, 6.6285714...e-07, 8.5571428...e-07, 1.4507142...e-06, 2.2542857...e-06, 3.4142857...e-06, 4.9864285...e-06, 6.4907142...e-06, 7.8928571...e-06, 9.1664285...e-06, 9.9521428...e-06, 9.7664285...e-06, 9.3150000...e-06, 8.9092857...e-06, 8.1578571...e-06, 6.8935714...e-06, 5.5721428...e-06, 4.4592857...e-06, 3.4778571...e-06, 2.7650000...e-06, 2.3114285...e-06, 1.7092857...e-06, 1.1771428...e-06, 9.8428571...e-07, 8.8285714...e-07, 7.4142857...e-07, 7.0142857...e-07, 7.0857142...e-07, 6.6642857...e-07, 7.5928571...e-07, 8.7000000...e-07, 8.2714285...e-07, 7.1714285...e-07, 6.6000000...e-07]) """ msds = sds_and_msds_to_msds(sds) interval = msds.shape.interval r_i = np.gradient(np.transpose(msds.values), axis=1) / interval if use_second_order_derivatives: r_i = np.gradient(r_i, axis=1) / interval return np.mean(r_i**2, axis=0)