Source code for ewoksid24.fit.planck
import logging
from typing import Optional
import numpy
import scipy.constants
from scipy.optimize import curve_fit
from ..io.temperature import TemperatureData
_logger = logging.getLogger(__name__)
[docs]def spectral_radiance(wavelength: numpy.ndarray, temperature: float, scale: float):
r"""Planck's law describing the spectral density of electromagnetic radiation emitted by
a black body in thermal equilibrium at a given temperature T.
.. math::
B(\lambda, T) = \frac{2hc^2}{\lambda^5} \cdot \frac{1}{e^{\frac{hc}{\lambda kT} - 1}}
Where:
- :math:`B(\lambda, T)` is the spectral radiance (:math:`\frac{W}{m^3\text{sr}}`) at wavelength :math:`\lambda` and temperature :math:`T`.
- :math:`h` is Planck's constant (:math:`6.62607015 \times 10^{-34}` J·s).
- :math:`c` is the speed of light in vacuum (:math:`2.998 \times 10^8` m/s).
- :math:`k` is the Boltzmann constant (:math:`1.380649 \times 10^{-23}` J/K).
- :math:`\lambda` is the wavelength of the radiation in meters.
- :math:`T` is the temperature of the blackbody radiator in Kelvin.
:param wavelength: wavelength in nanometer
:param temperature: temperature in Kelvin
:param scale: scaling factor to fit the data
:returns: spectral radiance
"""
h = scipy.constants.Planck # J·s
c = scipy.constants.speed_of_light # m/s
k = scipy.constants.Boltzmann # J/K
lam = wavelength * 1e-9
exp = numpy.exp((h * c) / (lam * k * temperature))
radiance = (2 * h * c**2) / (lam**5) / (exp - 1)
return radiance * scale
[docs]def fit_temperature_data(
temp_data: TemperatureData,
wavelength_min: Optional[float] = None,
wavelength_max: Optional[float] = None,
) -> None:
"""Fit temperature data and overwrite the existing fit results."""
yfit = numpy.zeros(temp_data.planck_fit.shape[1], dtype=temp_data.planck_fit.dtype)
xyiter = zip(temp_data.wavelength, temp_data.planck_data)
for i, (x, y) in enumerate(xyiter):
if wavelength_min is None:
start = temp_data.planck_fit_slice.start
else:
start = numpy.argmin(numpy.abs(x - wavelength_min))
if wavelength_max is None:
stop = temp_data.planck_fit_slice.stop
else:
stop = numpy.argmin(numpy.abs(x - wavelength_max)) + 1
fit_slice = slice(start, stop)
temp_data.planck_fit_slice = fit_slice
x = x[fit_slice]
y = y[fit_slice]
temperature0 = temp_data.planck_temperature[i]
scale0 = numpy.median(y / spectral_radiance(x, temperature0, 1))
p0 = [temperature0, scale0]
(temperature, scale), _ = curve_fit(spectral_radiance, x, y, p0=p0)
yfit[fit_slice] = spectral_radiance(x, temperature, scale)
temp_data.planck_fit[i] = yfit
_logger.debug(
"Point %d: %f K -> %f K", i, temp_data.planck_temperature[i], temperature
)
temp_data.planck_temperature[i] = temperature