"""
Optical Phenomenon Plotting
===========================
Define the optical phenomena plotting objects:
- :func:`colour.plotting.plot_single_sd_rayleigh_scattering`
- :func:`colour.plotting.plot_the_blue_sky`
"""
from __future__ import annotations
import typing
import matplotlib.pyplot as plt
if typing.TYPE_CHECKING:
from matplotlib.figure import Figure
from matplotlib.axes import Axes
from colour.algebra import normalise_maximum
from colour.colorimetry import MultiSpectralDistributions, sd_to_XYZ
if typing.TYPE_CHECKING:
from colour.hints import Any, ArrayLike, Dict, Sequence, Tuple
from colour.hints import cast
from colour.phenomena import sd_rayleigh_scattering
from colour.phenomena.rayleigh import (
CONSTANT_AVERAGE_PRESSURE_MEAN_SEA_LEVEL,
CONSTANT_DEFAULT_ALTITUDE,
CONSTANT_DEFAULT_LATITUDE,
CONSTANT_STANDARD_AIR_TEMPERATURE,
CONSTANT_STANDARD_CO2_CONCENTRATION,
)
from colour.plotting import (
CONSTANTS_COLOUR_STYLE,
SD_ASTMG173_ETR,
ColourSwatch,
XYZ_to_plotting_colourspace,
filter_cmfs,
override_style,
plot_single_colour_swatch,
plot_single_sd,
render,
)
from colour.utilities import first_item
__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__ = [
"plot_single_sd_rayleigh_scattering",
"plot_the_blue_sky",
]
[docs]
@override_style()
def plot_single_sd_rayleigh_scattering(
CO2_concentration: ArrayLike = CONSTANT_STANDARD_CO2_CONCENTRATION,
temperature: ArrayLike = CONSTANT_STANDARD_AIR_TEMPERATURE,
pressure: ArrayLike = CONSTANT_AVERAGE_PRESSURE_MEAN_SEA_LEVEL,
latitude: ArrayLike = CONSTANT_DEFAULT_LATITUDE,
altitude: ArrayLike = CONSTANT_DEFAULT_ALTITUDE,
cmfs: (
MultiSpectralDistributions | str | Sequence[MultiSpectralDistributions | str]
) = "CIE 1931 2 Degree Standard Observer",
**kwargs: Any,
) -> Tuple[Figure, Axes]:
"""
Plot a single *Rayleigh* scattering spectral distribution.
Parameters
----------
CO2_concentration
:math:`CO_2` concentration in parts per million (ppm).
temperature
Air temperature :math:`T[K]` in kelvin degrees.
pressure
Surface pressure :math:`P` of the measurement site.
latitude
Latitude of the site in degrees.
altitude
Altitude of the site in meters.
cmfs
Standard observer colour matching functions used for computing the
spectrum domain and colours. ``cmfs`` can be of any type or form
supported by the :func:`colour.plotting.common.filter_cmfs` definition.
Other Parameters
----------------
kwargs
{:func:`colour.plotting.artist`,
:func:`colour.plotting.plot_single_sd`,
:func:`colour.plotting.render`},
See the documentation of the previously listed definitions.
Returns
-------
:class:`tuple`
Current figure and axes.
Examples
--------
>>> plot_single_sd_rayleigh_scattering() # doctest: +ELLIPSIS
(<Figure size ... with 1 Axes>, <...Axes...>)
.. image:: ../_static/Plotting_Plot_Single_SD_Rayleigh_Scattering.png
:align: center
:alt: plot_single_sd_rayleigh_scattering
"""
title = "Rayleigh Scattering"
cmfs = cast(MultiSpectralDistributions, first_item(filter_cmfs(cmfs).values()))
settings: Dict[str, Any] = {"title": title, "y_label": "Optical Depth"}
settings.update(kwargs)
sd = sd_rayleigh_scattering(
cmfs.shape,
CO2_concentration,
temperature,
pressure,
latitude,
altitude,
)
return plot_single_sd(sd, **settings)
[docs]
@override_style()
def plot_the_blue_sky(
cmfs: (
MultiSpectralDistributions | str | Sequence[MultiSpectralDistributions | str]
) = "CIE 1931 2 Degree Standard Observer",
**kwargs: Any,
) -> Tuple[Figure, Axes]:
"""
Plot the blue sky.
Parameters
----------
cmfs
Standard observer colour matching functions used for computing the
spectrum domain and colours. ``cmfs`` can be of any type or form
supported by the :func:`colour.plotting.common.filter_cmfs` definition.
Other Parameters
----------------
kwargs
{:func:`colour.plotting.artist`,
:func:`colour.plotting.plot_single_sd`,
:func:`colour.plotting.plot_multi_colour_swatches`,
:func:`colour.plotting.render`},
See the documentation of the previously listed definitions.
Returns
-------
:class:`tuple`
Current figure and axes.
Examples
--------
>>> plot_the_blue_sky() # doctest: +ELLIPSIS
(<Figure size ... with 2 Axes>, <...Axes...>)
.. image:: ../_static/Plotting_Plot_The_Blue_Sky.png
:align: center
:alt: plot_the_blue_sky
"""
figure = plt.figure()
figure.subplots_adjust(hspace=CONSTANTS_COLOUR_STYLE.geometry.short / 2)
cmfs = cast(MultiSpectralDistributions, first_item(filter_cmfs(cmfs).values()))
ASTMG173_sd = SD_ASTMG173_ETR.copy()
rayleigh_sd = sd_rayleigh_scattering()
ASTMG173_sd.align(rayleigh_sd.shape)
sd = rayleigh_sd * ASTMG173_sd
axes = figure.add_subplot(211)
settings: Dict[str, Any] = {
"axes": axes,
"title": "The Blue Sky - Synthetic Spectral Distribution",
"y_label": "W / m-2 / nm-1",
}
settings.update(kwargs)
settings["show"] = False
plot_single_sd(sd, cmfs, **settings)
axes = figure.add_subplot(212)
x_label = (
"The sky is blue because molecules in the atmosphere "
"scatter shorter wavelengths more than longer ones.\n"
"The synthetic spectral distribution is computed as "
"follows: "
"(ASTM G-173 ETR * Standard Air Rayleigh Scattering)."
)
settings = {
"axes": axes,
"aspect": None,
"title": "The Blue Sky - Colour",
"x_label": x_label,
"y_label": "",
"x_ticker": False,
"y_ticker": False,
}
settings.update(kwargs)
settings["show"] = False
blue_sky_color = XYZ_to_plotting_colourspace(sd_to_XYZ(sd))
figure, axes = plot_single_colour_swatch(
ColourSwatch(normalise_maximum(blue_sky_color)), **settings
)
settings = {"axes": axes, "show": True}
settings.update(kwargs)
return render(**settings)