def test_interpolated_eval(modes_all): if eradiate.mode().has_flags(ModeFlags.ANY_MONO): spectral_ctx = SpectralContext.new(wavelength=550.0) expected = 0.5 elif eradiate.mode().has_flags(ModeFlags.ANY_CKD): bin = BinSet.from_db("10nm").select_bins("550")[0] spectral_ctx = SpectralContext.new(bindex=bin.bindexes[0]) expected = 0.5 else: assert False # Spectrum without quantity performs linear interpolation and yields units # consistent with values spectrum = InterpolatedSpectrum(wavelengths=[500.0, 600.0], values=[0.0, 1.0]) assert spectrum.eval(spectral_ctx) == expected spectrum.values *= ureg("W/m^2/nm") assert spectrum.eval(spectral_ctx) == expected * ureg("W/m^2/nm") # Spectrum with quantity performs linear interpolation and yields units # consistent with quantity spectrum = InterpolatedSpectrum( quantity="irradiance", wavelengths=[500.0, 600.0], values=[0.0, 1.0] ) # Interpolation returns quantity assert spectrum.eval(spectral_ctx) == expected * ucc.get("irradiance")
def test_spectral_context_new(modes_all): """ Unit tests for :meth:`SpectralContext.new`. """ # Empty call to new() should yield the appropriate SpectralContext instance if eradiate.mode().has_flags(ModeFlags.ANY_MONO): assert isinstance(SpectralContext.new(), MonoSpectralContext) elif eradiate.mode().has_flags(ModeFlags.ANY_CKD): assert isinstance(SpectralContext.new(), CKDSpectralContext) else: # All modes must have a context: this test fails if the mode has no # associated spectral context assert False
def test_afgl_1986_rad_profile_concentrations( mode_mono, afgl_1986_test_absorption_data_sets): """ Absorption coefficient is twice larger when H2O concentration is doubled. """ thermoprops = make_profile_afgl_1986() column_amount_H2O = compute_column_number_density(ds=thermoprops, species="H2O") p1 = AFGL1986RadProfile( thermoprops=thermoprops, absorption_data_sets=afgl_1986_test_absorption_data_sets, ) p2 = AFGL1986RadProfile( thermoprops=dict(concentrations={ "H2O": 2 * column_amount_H2O, }), absorption_data_sets=afgl_1986_test_absorption_data_sets, ) spectral_ctx = SpectralContext.new(wavelength=1500.0 * ureg.nm) sigma_a_initial = p1.eval_sigma_a(spectral_ctx) sigma_a_doubled = p2.eval_sigma_a(spectral_ctx) assert np.allclose(sigma_a_doubled, 2 * sigma_a_initial, rtol=1e-2)
def test_homogeneous_sigma_s(mode_mono): """ Assigns custom 'sigma_s' value. """ spectral_ctx = SpectralContext.new() r = HomogeneousAtmosphere(sigma_s=1e-5) assert r.eval_sigma_s(spectral_ctx) == ureg.Quantity(1e-5, ureg.m ** -1)
def test_us76_approx_rad_profile_ckd_sigma_s(mode_ckd): """ Scattering coefficient evaluation methods return pint.Quantity object. """ p = US76ApproxRadProfile() spectral_ctx = SpectralContext.new() assert isinstance(p.eval_sigma_s_ckd(spectral_ctx.bindex), ureg.Quantity)
def test_molecular_atmosphere_default(mode_mono, tmpdir, ussa76_approx_test_absorption_data_set): """Default MolecularAtmosphere constructor produces a valid kernel dictionary.""" spectral_ctx = SpectralContext.new(wavelength=550.0) ctx = KernelDictContext(spectral_ctx=spectral_ctx) atmosphere = MolecularAtmosphere(absorption_data_sets=dict( us76_u86_4=ussa76_approx_test_absorption_data_set)) assert KernelDict.from_elements(atmosphere, ctx=ctx).load() is not None
def test_particle_layer_eval_radprops(modes_all_single, test_dataset): """Method 'eval_radprops' returns dataset with expected datavars and coords.""" layer = ParticleLayer(dataset=test_dataset) spectral_ctx = SpectralContext.new() ds = layer.eval_radprops(spectral_ctx) expected_data_vars = ["sigma_t", "albedo"] expected_coords = ["z_layer"] assert all([coord in ds.coords for coord in expected_coords]) and all( [var in ds.data_vars for var in expected_data_vars] )
def test_us76_approx_rad_profile(mode_mono, us76_approx_test_absorption_data_set): """ Collision coefficient evaluation methods return pint.Quantity objects. """ p = US76ApproxRadProfile( absorption_data_set=us76_approx_test_absorption_data_set) spectral_ctx = SpectralContext.new() for field in ["sigma_a", "sigma_s", "sigma_t", "albedo"]: x = getattr(p, f"eval_{field}")(spectral_ctx) assert isinstance(x, ureg.Quantity)
def test_afgl_1986_rad_profile_default(mode_mono, afgl_1986_test_absorption_data_sets): """ Collision coefficient evaluation methods return pint.Quantity objects. """ p = AFGL1986RadProfile( absorption_data_sets=afgl_1986_test_absorption_data_sets) spectral_ctx = SpectralContext.new(wavelength=1500.0) for field in ["sigma_a", "sigma_s", "sigma_t", "albedo"]: x = getattr(p, f"eval_{field}")(spectral_ctx) assert isinstance(x, ureg.Quantity)
def test_us76_approx_rad_profile_has_scattering_default( mode_mono, us76_approx_test_absorption_data_set): """ Default value for 'has_scattering' is True, hence the scattering coefficient is computed and is not zero everywhere at 550 nm. """ p = US76ApproxRadProfile( absorption_data_set=us76_approx_test_absorption_data_set) assert p.has_scattering spectral_ctx = SpectralContext.new(wavelength=550.0) ds = p.eval_dataset(spectral_ctx) assert (ds.sigma_s.values != 0.0).any()
def test_array_rad_props_profile_eval_dataset(mode_mono): """ Returns a data set. """ p = ArrayRadProfile( levels=ureg.Quantity(np.linspace(0, 100, 12), "km"), albedo_values=ureg.Quantity(np.linspace(0.0, 1.0, 11), ureg.dimensionless), sigma_t_values=ureg.Quantity(np.linspace(0.0, 1e-5, 11), "m^-1"), ) spectral_ctx = SpectralContext.new() assert isinstance(p.eval_dataset(spectral_ctx), xr.Dataset)
def test_afgl_1986_rad_profile_has_scattering_default( mode_mono, afgl_1986_test_absorption_data_sets): """ Default value for 'has_scattering' is True, hence the absorption coefficient is computed and is not zero everywhere at 550 nm. """ p = AFGL1986RadProfile( absorption_data_sets=afgl_1986_test_absorption_data_sets) assert p.has_scattering spectral_ctx = SpectralContext.new(wavelength=550.0) ds = p.eval_dataset(spectral_ctx) assert (ds.sigma_s.values != 0.0).any()
def test_molecular_atmosphere_afgl_1986( mode_mono, tmpdir, afgl_1986_test_absorption_data_sets, ): """MolecularAtmosphere 'afgl_1986' constructor produces a valid kernel dictionary.""" spectral_ctx = SpectralContext.new(wavelength=550.0) ctx = KernelDictContext(spectral_ctx=spectral_ctx) atmosphere = MolecularAtmosphere.afgl_1986( absorption_data_sets=afgl_1986_test_absorption_data_sets) assert KernelDict.from_elements(atmosphere, ctx=ctx).load() is not None
def test_solar_irradiance_eval(modes_all): # Irradiance is correctly interpolated in mono mode s = SolarIrradianceSpectrum(dataset="thuillier_2003") if eradiate.mode().has_flags(ModeFlags.ANY_MONO): spectral_ctx = SpectralContext.new(wavelength=550.0) # Reference value computed manually assert np.allclose(s.eval(spectral_ctx), ureg.Quantity(1.87938, "W/m^2/nm")) elif eradiate.mode().has_flags(ModeFlags.ANY_CKD): bin_set = BinSet.from_db("10nm") bin = bin_set.select_bins("550")[0] bindex = bin.bindexes[0] spectral_ctx = SpectralContext.new(bindex=bindex) # Reference value computed manually assert np.allclose(s.eval(spectral_ctx), ureg.Quantity(1.871527, "W/m^2/nm")) else: assert False
def test_afgl_1986_rad_profile_has_absorption_true( mode_mono, afgl_1986_test_absorption_data_sets): """ When 'has_absorption' is True, the absorption coefficient is computed and is not zero everywhere at 1650 nm. """ p = AFGL1986RadProfile( has_absorption=True, absorption_data_sets=afgl_1986_test_absorption_data_sets) assert p.has_absorption spectral_ctx = SpectralContext.new(wavelength=1650.0) ds = p.eval_dataset(spectral_ctx) assert (ds.sigma_a.values != 0.0).any()
def test_afgl_1986_rad_profile_has_scattering_false( mode_mono, afgl_1986_test_absorption_data_sets): """ When 'has_scattering' is False, the scattering coefficient is not computed and is zero everywhere. """ p = AFGL1986RadProfile( has_scattering=False, absorption_data_sets=afgl_1986_test_absorption_data_sets) assert not p.has_scattering spectral_ctx = SpectralContext.new(wavelength=550.0) ds = p.eval_dataset(spectral_ctx) assert (ds.sigma_s.values == 0.0).all()
def test_us76_approx_rad_profile_has_absorption_false( mode_mono, us76_approx_test_absorption_data_set): """ When 'has_absorption' is False, the absorption coefficient is not computed and is zero everywhere. """ p = US76ApproxRadProfile( has_absorption=False, absorption_data_set=us76_approx_test_absorption_data_set) assert not p.has_absorption spectral_ctx = SpectralContext.new(wavelength=1650.0) ds = p.eval_dataset(spectral_ctx) assert (ds.sigma_a.values == 0.0).all()
def test_us76_approx_rad_profile_levels(mode_mono, us76_approx_test_absorption_data_set): """ Collision coefficients' shape match altitude levels shape. """ p = US76ApproxRadProfile( thermoprops=dict(levels=ureg.Quantity(np.linspace(0, 120, 121), "km")), absorption_data_set=us76_approx_test_absorption_data_set, ) spectral_ctx = SpectralContext.new() for field in ["sigma_a", "sigma_s", "sigma_t", "albedo"]: x = getattr(p, f"eval_{field}")(spectral_ctx) assert x.shape == (120, )
def test_afgl_1986_rad_profile_default_ckd(mode_ckd): """ Collision coefficient evaluation methods return pint.Quantity objects. """ p = AFGL1986RadProfile() spectral_ctx = SpectralContext.new(bin_set="10nm") for field in ["albedo", "sigma_a", "sigma_t"]: x = getattr(p, f"eval_{field}_ckd")(spectral_ctx.bindex, bin_set_id=spectral_ctx.bin_set.id) assert isinstance(x, ureg.Quantity) sigma_s = p.eval_sigma_s_ckd(spectral_ctx.bindex) assert isinstance(sigma_s, ureg.Quantity)
def test_mono_spectral_context(mode_mono): """ Unit tests for :class:`MonoSpectralContext`. """ ctx = SpectralContext.new(wavelength=550.0) # Wavelength is stored as a Pint quantity assert ctx.wavelength == 550.0 * ureg.nm # Index is a plain float assert ctx.spectral_index == 550.0 # Index string repr is nice and compact assert ctx.spectral_index_formatted == "550 nm"
def test_afgl_1986_rad_profile_levels(mode_mono, afgl_1986_test_absorption_data_sets): """ Collision coefficients' shape match altitude levels shape. """ n_layers = 101 p = AFGL1986RadProfile( thermoprops=dict( levels=ureg.Quantity(np.linspace(0.0, 100.0, n_layers + 1), "km")), absorption_data_sets=afgl_1986_test_absorption_data_sets, ) spectral_ctx = SpectralContext.new(wavelength=550.0) for field in ["sigma_a", "sigma_s", "sigma_t", "albedo"]: x = getattr(p, f"eval_{field}")(spectral_ctx) assert x.shape == (n_layers, )
def test_ckd_spectral_context(mode_ckd): """ Unit tests for :class:`CKDSpectralContext`. """ quad = Quad.gauss_legendre(16) bin = Bin.convert({ "id": "510", "wmin": 505.0, "wmax": 515.0, "quad": quad }) ctx = SpectralContext.new(bindex=bin.bindexes[8]) # Wavelength is equal to bin central wavelength assert ctx.wavelength == 510.0 * ureg.nm # Index is a (str, int) pair assert ctx.spectral_index == ("510", 8) # Index string repr is a compact "{bin_id}:{quad_point_index}" string assert ctx.spectral_index_formatted == "510:8"
def test_interpolated_kernel_dict(modes_all_mono): from mitsuba.core.xml import load_dict ctx = KernelDictContext(spectral_ctx=SpectralContext.new(wavelength=550.0)) spectrum = InterpolatedSpectrum( id="spectrum", quantity="irradiance", wavelengths=[500.0, 600.0], values=[0.0, 1.0], ) # Produced kernel dict is valid assert load_dict(spectrum.kernel_dict(ctx)["spectrum"]) is not None # Unit scaling is properly applied with ucc.override({"radiance": "W/m^2/sr/nm"}): s = InterpolatedSpectrum( quantity="radiance", wavelengths=[500.0, 600.0], values=[0.0, 1.0] ) with uck.override({"radiance": "kW/m^2/sr/nm"}): d = s.kernel_dict(ctx) assert np.allclose(d["spectrum"]["value"], 5e-4)
def test_tabulated_order(mode_mono, tmpdir): """ TabulatedPhaseFunction returns phase function values by increasing order of scattering angle cosine values, regardless how its input is ordered. """ def make_da(mu, phase): return xr.DataArray( phase[:, :, np.newaxis, np.newaxis], coords={ "w": ("w", [240.0, 2800.0], dict(units="nm")), "mu": ("mu", mu), "i": ("i", [0]), "j": ("j", [0]), }, ) da_mu_increasing = make_da(mu=np.linspace(-1, 1, 3), phase=np.array( [np.arange(1, 4), np.arange(1, 4)])) da_mu_decreasing = make_da( mu=np.linspace(1, -1, 3), phase=np.array([np.arange(3, 0, -1), np.arange(3, 0, -1)]), ) spectral_ctx = SpectralContext.new() layer_mu_increasing = TabulatedPhaseFunction(data=da_mu_increasing) phase_mu_increasing = layer_mu_increasing.eval(spectral_ctx) layer_mu_decreasing = TabulatedPhaseFunction(data=da_mu_decreasing) phase_mu_decreasing = layer_mu_decreasing.eval(spectral_ctx) assert np.all(phase_mu_increasing == phase_mu_decreasing)
def test_array_rad_props_profile(mode_mono): """ Assigns attributes. """ levels = ureg.Quantity(np.linspace(0, 100, 12), "km") albedo_values = ureg.Quantity(np.linspace(0.0, 1.0, 11), ureg.dimensionless) sigma_t_values = ureg.Quantity(np.linspace(0.0, 1e-5, 11), "m^-1") p = ArrayRadProfile( levels=levels, albedo_values=albedo_values, sigma_t_values=sigma_t_values, ) spectral_ctx = SpectralContext.new() assert isinstance(p.levels, ureg.Quantity) assert isinstance(p.eval_albedo(spectral_ctx=spectral_ctx), ureg.Quantity) assert isinstance(p.eval_sigma_t(spectral_ctx=spectral_ctx), ureg.Quantity) assert isinstance(p.eval_sigma_a(spectral_ctx=spectral_ctx), ureg.Quantity) assert isinstance(p.eval_sigma_s(spectral_ctx=spectral_ctx), ureg.Quantity) assert np.allclose(p.levels, levels) assert np.allclose(p.eval_albedo(spectral_ctx=spectral_ctx), albedo_values) assert np.allclose(p.eval_sigma_t(spectral_ctx=spectral_ctx), sigma_t_values)