Source code for eradiate.scenes.bsdfs._ocean_mishchenko

from __future__ import annotations

import attrs
import mitsuba as mi
import pint
import pinttrs

from ._core import BSDF
from ..core import traverse
from ..spectra import Spectrum, spectrum_factory
from ... import validators
from ...attrs import define, documented
from ...kernel import TypeIdLookupStrategy, UpdateParameter
from ...units import unit_registry as ureg


[docs] @define(eq=False, slots=False) class OceanMishchenkoBSDF(BSDF): """ Ocean Mishchenko BSDF [``ocean_mishchenko``]. This plugin implements the polarized ocean surface model as implemented by :cite:t:`Mishchenko1997AerosolRetrievalPolarization`. This model treats the ocean as an opaque surface and models the polarized sunglint. It depends on wind speed and the index of refraction of the water and external medium (assumed to be air). See Also -------- :ref:`plugin-bsdf-ocean_legacy` """ wind_speed: pint.Quantity = documented( pinttrs.field( units=ureg("m/s").units, factory=lambda: 0.01 * ureg("m/s"), validator=[validators.is_positive, pinttrs.validators.has_compatible_units], ), doc="Wind speed [m/s] at 10 meters above the surface.", type="quantity", init_type="quantity or float", default="0.01 m/s", ) eta: Spectrum = documented( attrs.field( default=1.33, converter=spectrum_factory.converter("dimensionless"), validator=[ attrs.validators.instance_of(Spectrum), validators.has_quantity("dimensionless"), ], ), doc="Real component of the water's index of refraction " "processed by :data:`.spectrum_factory`.", type=".Spectrum", init_type=".Spectrum or dict or float", default="1.33", ) k: Spectrum = documented( attrs.field( default=0.0, converter=spectrum_factory.converter("dimensionless"), validator=[ attrs.validators.instance_of(Spectrum), validators.has_quantity("dimensionless"), ], ), doc="Imaginary component of the water's index of refraction " "processed by :data:`.spectrum_factory`.", type=".Spectrum", init_type=".Spectrum or dict or float", default="0.", ) ext_ior: Spectrum = documented( attrs.field( default=1.0, converter=spectrum_factory.converter("dimensionless"), validator=[ attrs.validators.instance_of(Spectrum), validators.has_quantity("dimensionless"), ], ), doc="Real component of the air's index of refraction " "processed by :data:`.spectrum_factory`. The imaginary component " "is assumed to be zero. ", type=".Spectrum", init_type=".Spectrum or dict or float", default="1.000277f", ) shadowing: bool = documented( attrs.field( converter=bool, validator=attrs.validators.instance_of(bool), default=True, ), doc="Indicates whether evaluation of BRDF computes shadowing and masking.", type="bool", default="True", ) @property def template(self) -> dict: # Inherit docstring objects = { "eta": traverse(self.eta)[0], "k": traverse(self.k)[0], "ext_ior": traverse(self.ext_ior)[0], } result = { "type": "ocean_mishchenko", "wind_speed": self.wind_speed.m_as("m/s"), "shadowing": self.shadowing, } for obj_key, obj_values in objects.items(): for key, value in obj_values.items(): result[f"{obj_key}.{key}"] = value if self.id is not None: result["id"] = self.id return result @property def params(self) -> dict[str, UpdateParameter]: # Inherit docstring objects = { "eta": traverse(self.eta)[1], "k": traverse(self.k)[1], "ext_ior": traverse(self.ext_ior)[1], } result = {} for obj_key, obj_params in objects.items(): for key, param in obj_params.items(): result[f"{obj_key}.{key}"] = attrs.evolve( param, lookup_strategy=TypeIdLookupStrategy( node_type=mi.BSDF, node_id=self.id, parameter_relpath=f"{obj_key}.{key}", ) if self.id is not None else None, ) return result