Source code for sasktran2.constituent.brdf.lambertiansurface
from __future__ import annotations
import numpy as np
from sasktran2.atmosphere import Atmosphere
from ..base import Constituent
from . import PyLambertian, WavelengthInterpolatorMixin
[docs]
class LambertianSurface(Constituent, WavelengthInterpolatorMixin):
[docs]
def __init__(
self,
albedo: np.array,
wavelengths_nm: np.array = None,
wavenumbers_cminv: np.array = None,
out_of_bounds_mode="zero",
) -> None:
"""
A Lambertian surface that is defined by albedo at discrete grid points.
This can either operate in a "scalar" mode where the albedo is constant in wavelength,
a "native" mode where the albedo is defined on the same grid as the atmosphere, or
an "interpolated" mode where the albedo is interpolated either in wavenumber or wavelength
Parameters
----------
albedo : np.array
Surface albedo. Can be a scalar to indicate it is constant in wavelength. If set to an
array it must either match the atmosphere wavelength grid dimension, or one of
wavelengths_nm or wavenumbers_cminv must be set.
wavelengths_nm : np.array, optional
Wavelengths in [nm] that the albedo is specified at, by default None
wavenumbers_cminv : np.array, optional
Wavenumbers in inverse cm that the albedo is specified at, by default None
out_of_bounds_mode : str, optional
One of ["extend" or "zero"], "extend" will extend the last/first value if we are
interpolating outside the grid. "zero" will set the albedo to 0 outside of the
grid boundaries, by default "zero"
"""
Constituent.__init__(self)
WavelengthInterpolatorMixin.__init__(
self,
wavelengths_nm=wavelengths_nm,
wavenumbers_cminv=wavenumbers_cminv,
out_of_bounds_mode=out_of_bounds_mode,
param_length=len(np.atleast_1d(albedo)),
)
self._albedo = np.atleast_1d(albedo)
@property
def albedo(self) -> np.array:
return self._albedo
@albedo.setter
def albedo(self, albedo: np.array):
self._albedo = np.atleast_1d(albedo)
def add_to_atmosphere(self, atmo: Atmosphere):
atmo.surface.brdf = PyLambertian(atmo.nstokes)
interp_matrix = self._interpolating_matrix(atmo)
atmo.surface.brdf_args[0, :] = interp_matrix @ self._albedo
def register_derivative(self, atmo: Atmosphere, name: str):
# Start by constructing the interpolation matrix
interp_matrix = self._interpolating_matrix(atmo)
derivs = {}
deriv_mapping = atmo.surface.get_derivative_mapping(f"wf_{name}_albedo")
deriv_mapping.d_brdf[:] = np.ones((atmo.num_wavel, 1))
deriv_mapping.interpolator = interp_matrix
deriv_mapping.interp_dim = f"{name}_wavelength"
return derivs