Source code for colour.phenomena.sky.cie2003

"""
CIE Standard General Sky
========================

Implement the *CIE Standard General Sky* luminance distribution model as
defined in *CIE S 011/E:2003* and *ISO 15469:2004(E)*.

-   :func:`colour.phenomena.sky_luminance_gradation_CIE2003`
-   :func:`colour.phenomena.sky_scattering_indicatrix_CIE2003`
-   :func:`colour.phenomena.sky_luminance_distribution_CIE2003`

References
----------
-   :cite:`CIE2003` : CIE. (2003). International Organization for
    Standardization. (2004). INTERNATIONAL STANDARD ISO 15469 CIE S 011/E -
    Spatial distribution of daylight - CIE standard general sky.
"""

from __future__ import annotations

import typing
from dataclasses import dataclass

import numpy as np

if typing.TYPE_CHECKING:
    from colour.hints import ArrayLike, NDArrayFloat

from colour.utilities import MixinDataclassIterable, as_float, as_float_array

__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__ = [
    "SkyType_CIE2003",
    "CIE_STANDARD_SKY_PARAMETERS",
    "sky_luminance_gradation_CIE2003",
    "sky_scattering_indicatrix_CIE2003",
    "sky_luminance_distribution_CIE2003",
    "sky_luminance_distribution_overcast_CIE2003",
]


[docs] @dataclass(frozen=True) class SkyType_CIE2003(MixinDataclassIterable): """ Define parameters for a *CIE Standard General Sky* type. Parameters ---------- gradation_group Gradation function group (I-VI). indicatrix_group Indicatrix function group (1-6). a Gradation parameter :math:`a`. b Gradation parameter :math:`b`. c Indicatrix parameter :math:`c`. d Indicatrix parameter :math:`d`. e Indicatrix parameter :math:`e`. description Description of luminance distribution. References ---------- :cite:`CIE2003` """ gradation_group: int indicatrix_group: int a: float b: float c: float d: float e: float description: str
CIE_STANDARD_SKY_PARAMETERS: dict[int, SkyType_CIE2003] = { 1: SkyType_CIE2003( 1, 1, 4.0, -0.70, 0, -1.0, 0, "CIE Standard Overcast Sky, " "steep luminance gradation towards zenith, azimuthal uniformity", ), 2: SkyType_CIE2003( 1, 2, 4.0, -0.70, 2, -1.5, 0.15, "Overcast, with steep luminance gradation " "and slight brightening towards the sun", ), 3: SkyType_CIE2003( 2, 1, 1.1, -0.8, 0, -1.0, 0, "Overcast, moderately graded with azimuthal uniformity", ), 4: SkyType_CIE2003( 2, 2, 1.1, -0.8, 2, -1.5, 0.15, "Overcast, moderately graded and slight brightening towards the sun", ), 5: SkyType_CIE2003( 3, 1, 0, -1.0, 0, -1.0, 0, "Sky of uniform luminance", ), 6: SkyType_CIE2003( 3, 2, 0, -1.0, 2, -1.5, 0.15, "Partly cloudy sky, no gradation towards zenith, " "slight brightening towards the sun", ), 7: SkyType_CIE2003( 3, 3, 0, -1.0, 5, -2.5, 0.30, "Partly cloudy sky, no gradation towards zenith, brighter circumsolar region", ), 8: SkyType_CIE2003( 3, 4, 0, -1.0, 10, -3.0, 0.45, "Partly cloudy sky, no gradation towards zenith, distinct solar corona", ), 9: SkyType_CIE2003( 4, 2, -1.0, -0.55, 2, -1.5, 0.15, "Partly cloudy, with the obscured sun", ), 10: SkyType_CIE2003( 4, 3, -1.0, -0.55, 5, -2.5, 0.30, "Partly cloudy, with brighter circumsolar region", ), 11: SkyType_CIE2003( 4, 4, -1.0, -0.55, 10, -3.0, 0.45, "White-blue sky with distinct solar corona", ), 12: SkyType_CIE2003( 5, 4, -1.0, -0.32, 10, -3.0, 0.45, "CIE Standard Clear Sky, low luminance turbidity", ), 13: SkyType_CIE2003( 5, 5, -1.0, -0.32, 16, -3.0, 0.30, "CIE Standard Clear Sky, polluted atmosphere", ), 14: SkyType_CIE2003( 6, 5, -1.0, -0.15, 16, -3.0, 0.30, "Cloudless turbid sky with broad solar corona", ), 15: SkyType_CIE2003( 6, 6, -1.0, -0.15, 24, -2.8, 0.15, "White-blue turbid sky with broad solar corona", ), } """ *CIE Standard General Sky* parameters for 15 sky types. References ---------- :cite:`CIE2003` """
[docs] def sky_luminance_gradation_CIE2003( Z: ArrayLike, a: ArrayLike, b: ArrayLike, ) -> NDArrayFloat: """ Compute the *CIE Standard General Sky* luminance gradation function :math:`\\varphi(Z)` at the given zenith angle :math:`Z`. Parameters ---------- Z Zenith angle :math:`Z` in radians. a Gradation parameter :math:`a`. b Gradation parameter :math:`b`. Returns ------- :class:`numpy.ndarray` Luminance gradation :math:`\\varphi(Z)`. References ---------- :cite:`CIE2003` Examples -------- >>> sky_luminance_gradation_CIE2003(0, 4.0, -0.70) # doctest: +ELLIPSIS np.float64(2.9863412...) >>> sky_luminance_gradation_CIE2003( # doctest: +ELLIPSIS ... np.pi / 2, 4.0, -0.70 ... ) np.float64(1.0) """ Z = as_float_array(Z) a = as_float_array(a) b = as_float_array(b) phi = np.where( np.pi / 2 > Z, 1 + a * np.exp(b / np.cos(Z)), 1.0, ) return as_float(phi)
[docs] def sky_scattering_indicatrix_CIE2003( chi: ArrayLike, c: ArrayLike, d: ArrayLike, e: ArrayLike, ) -> NDArrayFloat: """ Compute the *CIE Standard General Sky* scattering indicatrix function :math:`f(\\chi)` at the given angular distance :math:`\\chi` between a sky element and the sun. Parameters ---------- chi Angular distance :math:`\\chi` between the sky element and the sun in radians. c Indicatrix parameter :math:`c`. d Indicatrix parameter :math:`d`. e Indicatrix parameter :math:`e`. Returns ------- :class:`numpy.ndarray` Scattering indicatrix :math:`f(\\chi)`. References ---------- :cite:`CIE2003` Examples -------- >>> sky_scattering_indicatrix_CIE2003( # doctest: +ELLIPSIS ... np.radians(30), 10, -3.0, 0.45 ... ) np.float64(3.3264628...) """ chi = as_float_array(chi) c = as_float_array(c) d = as_float_array(d) e = as_float_array(e) f = 1 + c * (np.exp(d * chi) - np.exp(d * np.pi / 2)) + e * np.cos(chi) ** 2 return as_float(f)
[docs] def sky_luminance_distribution_CIE2003( sky_type: int, Z: ArrayLike, alpha: ArrayLike, Z_s: ArrayLike, alpha_s: ArrayLike, ) -> NDArrayFloat: """ Compute the relative sky luminance :math:`L_{\\alpha} / L_z` for the given *CIE Standard General Sky* type. The relative luminance at any point is the ratio of the luminance of an arbitrary sky element to the zenith luminance :math:`L_z`: :math:`L_{\\alpha} / L_z = f(\\chi) \\cdot \\varphi(Z) / \ (f(Z_s) \\cdot \\varphi(0))` Parameters ---------- sky_type *CIE Standard General Sky* type (1-15). Z Zenith angle :math:`Z` of the sky element in radians. alpha Azimuth angle :math:`\\alpha` of the sky element in radians (clockwise from north). Z_s Zenith angle :math:`Z_s` of the sun in radians. alpha_s Azimuth angle :math:`\\alpha_s` of the sun in radians (clockwise from north). Returns ------- :class:`numpy.ndarray` Relative sky luminance :math:`L_{\\alpha} / L_z`. Raises ------ ValueError If ``sky_type`` is not in range [1, 15]. References ---------- :cite:`CIE2003` Examples -------- >>> sky_luminance_distribution_CIE2003( # doctest: +ELLIPSIS ... 1, np.radians(45), np.radians(180), np.radians(30), np.radians(0) ... ) np.float64(0.8325846...) >>> sky_luminance_distribution_CIE2003( # doctest: +ELLIPSIS ... 12, np.radians(45), np.radians(180), np.radians(30), np.radians(0) ... ) np.float64(0.4544524...) """ if sky_type not in CIE_STANDARD_SKY_PARAMETERS: error = f'"sky_type" must be in range [1, 15], got "{sky_type}".' raise ValueError(error) Z = as_float_array(Z) alpha = as_float_array(alpha) Z_s = as_float_array(Z_s) alpha_s = as_float_array(alpha_s) parameters = CIE_STANDARD_SKY_PARAMETERS[sky_type] a = parameters.a b = parameters.b c = parameters.c d = parameters.d e = parameters.e # Angular distance between sky element and the sun (Equation 1). chi = np.arccos( np.cos(Z_s) * np.cos(Z) + np.sin(Z_s) * np.sin(Z) * np.cos(np.abs(alpha - alpha_s)) ) # Relative luminance (Equations 3-7). f_chi = sky_scattering_indicatrix_CIE2003(chi, c, d, e) phi_Z = sky_luminance_gradation_CIE2003(Z, a, b) f_Z_s = sky_scattering_indicatrix_CIE2003(Z_s, c, d, e) phi_0 = sky_luminance_gradation_CIE2003(0, a, b) L_ratio = (f_chi * phi_Z) / (f_Z_s * phi_0) return as_float(L_ratio)
[docs] def sky_luminance_distribution_overcast_CIE2003( Z: ArrayLike, ) -> NDArrayFloat: """ Compute the relative sky luminance :math:`L_{\\alpha} / L_z` for the *CIE Traditional Overcast Sky* (the 16th sky type). :math:`L_{\\alpha}(\\gamma) / L_{zenith} = (1 + 2 \\sin \\gamma) / 3` where :math:`\\gamma` is the angle of elevation of the sky element above the horizon. Parameters ---------- Z Zenith angle :math:`Z` of the sky element in radians. Returns ------- :class:`numpy.ndarray` Relative sky luminance :math:`L_{\\alpha} / L_z`. References ---------- :cite:`CIE2003` Examples -------- >>> sky_luminance_distribution_overcast_CIE2003(0) # doctest: +ELLIPSIS np.float64(1.0) >>> sky_luminance_distribution_overcast_CIE2003( # doctest: +ELLIPSIS ... np.pi / 2 ... ) np.float64(0.3333333...) """ Z = as_float_array(Z) gamma = np.pi / 2 - Z return as_float((1 + 2 * np.sin(gamma)) / 3)