示例#1
0
def test_solar_irradiance(mode_mono):

    # Default context
    ctx = KernelDictContext()

    # We can instantiate the element
    s = SolarIrradianceSpectrum()

    # Unsupported solar spectrum keywords raise
    with pytest.raises(ValueError):
        SolarIrradianceSpectrum(dataset="doesnt_exist")

    # Produced kernel dict is valid
    assert KernelDict.from_elements(s, ctx=ctx).load()

    # A more detailed specification still produces a valid object
    s = SolarIrradianceSpectrum(scale=2.0)
    assert KernelDict.from_elements(s, ctx=ctx).load()

    # Element doesn't work out of the supported spectral range
    s = SolarIrradianceSpectrum(dataset="thuillier_2003")

    with pytest.raises(ValueError):
        ctx = KernelDictContext(spectral_ctx={"wavelength": 2400.0})
        s.kernel_dict(ctx)

    # solid_2017_mean dataset can be used
    ctx = KernelDictContext()
    s = SolarIrradianceSpectrum(dataset="solid_2017_mean")
    assert KernelDict.from_elements(s, ctx=ctx).load()
示例#2
0
def test_centralpatch_compute_scale(modes_all_double):
    ctx = KernelDictContext()
    cs = CentralPatchSurface(width=10 * ureg.m,
                             central_patch=LambertianSurface(width=1 * ureg.m))

    scale = cs._compute_scale_parameter(ctx=ctx)

    assert np.allclose(scale, 3.33333333)

    ctx = ctx.evolve(override_canopy_width=2 * ureg.m)
    scale = cs._compute_scale_parameter(ctx=ctx)
    assert np.allclose(scale, 1.6666666666667)
示例#3
0
def test_molecular_atmosphere_switches(mode_mono):
    # Absorption can be deactivated
    atmosphere = MolecularAtmosphere(has_absorption=False)
    ctx = KernelDictContext()
    assert np.all(atmosphere.eval_radprops(ctx.spectral_ctx).sigma_a == 0.0)

    # Scattering can be deactivated
    atmosphere = MolecularAtmosphere(has_scattering=False)
    ctx = KernelDictContext()
    assert np.all(atmosphere.eval_radprops(ctx.spectral_ctx).sigma_s == 0.0)

    # At least one must be active
    with pytest.raises(ValueError):
        MolecularAtmosphere(has_absorption=False, has_scattering=False)
示例#4
0
def test_multi_radiancemeter_external_medium(mode_mono):
    # create a series of multiradiancemeter measures and a kernel dict context
    # which places some of them inside and outside the atmospheric volume
    # assert that the external medium is set correctly in the cameras' kernel dicts

    d1 = MultiRadiancemeterMeasure()

    ctx1 = KernelDictContext(atmosphere_medium_id="test_atmosphere")
    ctx2 = KernelDictContext()

    kd1 = d1.kernel_dict(ctx=ctx1)
    kd2 = d1.kernel_dict(ctx=ctx2)

    assert kd1["measure"]["medium"] == {"type": "ref", "id": "test_atmosphere"}
    assert "medium" not in kd2["measure"].keys()
示例#5
0
def test_perspective_external_medium(mode_mono):
    # create a series of perspective camera measures and a kernel dict context
    # which places some of them inside and outside the atmospheric volume
    # assert that the external medium is set correctly in the cameras' kernel dicts

    s1 = PerspectiveCameraMeasure()

    ctx1 = KernelDictContext(atmosphere_medium_id="test_atmosphere")
    ctx2 = KernelDictContext()

    kd1 = s1.kernel_dict(ctx=ctx1)
    kd2 = s1.kernel_dict(ctx=ctx2)

    assert kd1["measure"]["medium"] == {"type": "ref", "id": "test_atmosphere"}
    assert "medium" not in kd2["measure"].keys()
示例#6
0
def test_uniform(modes_all):
    from mitsuba.core.xml import load_dict

    # Instantiate with value only
    s = UniformSpectrum(value=1.0)
    assert s.quantity is PhysicalQuantity.DIMENSIONLESS
    assert s.value == 1.0 * ureg.dimensionless

    # Instantiate with value and quantity
    s = UniformSpectrum(value=1.0,
                        quantity=PhysicalQuantity.COLLISION_COEFFICIENT)
    assert s.value == 1.0 * ureg.m**-1
    UniformSpectrum(value=1.0, quantity="collision_coefficient")
    assert s.quantity == PhysicalQuantity.COLLISION_COEFFICIENT
    assert s.value == 1.0 * ureg.m**-1

    # Instantiate with unsupported quantity
    with pytest.raises(ValueError):
        UniformSpectrum(value=1.0, quantity="speed")

    # Instantiate with all arguments
    s = UniformSpectrum(quantity="collision_coefficient", value=1.0)
    assert s.value == ureg.Quantity(1.0, "m^-1")

    # Raise if units and quantity are inconsistent
    with pytest.raises(pinttr.exceptions.UnitsError):
        UniformSpectrum(quantity="collision_coefficient",
                        value=ureg.Quantity(1.0, ""))

    # Instantiate from factory using dict
    s = spectrum_factory.convert({
        "type": "uniform",
        "quantity": "radiance",
        "value": 1.0,
        "value_units": "W/km^2/sr/nm",
    })

    # Produced kernel dict is valid
    ctx = KernelDictContext()
    assert load_dict(onedict_value(s.kernel_dict(ctx))) is not None

    # Unit scaling is properly applied
    with ucc.override({"radiance": "W/m^2/sr/nm"}):
        s = UniformSpectrum(quantity="radiance", value=1.0)
    with uck.override({"radiance": "kW/m^2/sr/nm"}):
        ctx = KernelDictContext()
        d = s.kernel_dict(ctx)
        assert np.allclose(d["spectrum"]["value"], 1e-3)
示例#7
0
def test_multi_radiancemeter_noargs(mode_mono):
    # Instantiation succeeds
    s = MultiRadiancemeterMeasure()

    # The kernel dict can be instantiated
    ctx = KernelDictContext()
    assert KernelDict.from_elements(s, ctx=ctx).load()
示例#8
0
def test_directional(mode_mono):
    from mitsuba.core.xml import load_dict

    # We need a default spectral config
    ctx = KernelDictContext()

    # Constructor
    d = DirectionalIllumination()
    assert load_dict(onedict_value(d.kernel_dict(ctx))) is not None

    # Check if a more detailed spec is valid
    d = DirectionalIllumination(irradiance={"type": "uniform", "value": 1.0})
    assert load_dict(onedict_value(d.kernel_dict(ctx))) is not None

    # Check if solar irradiance spectrum can be used
    d = DirectionalIllumination(irradiance={"type": "solar_irradiance"})
    assert load_dict(onedict_value(d.kernel_dict(ctx))) is not None

    # Check if specification from a float works
    d = DirectionalIllumination(irradiance=1.0)
    assert load_dict(onedict_value(d.kernel_dict(ctx))) is not None

    # Check if specification from a constant works
    d = DirectionalIllumination(irradiance=ureg.Quantity(1.0, "W/m^2/nm"))
    assert load_dict(onedict_value(d.kernel_dict(ctx))) is not None
    with pytest.raises(pinttr.exceptions.UnitsError):  # Wrong units
        DirectionalIllumination(irradiance=ureg.Quantity(1.0, "W/m^2/sr/nm"))
示例#9
0
def test_blend_array(modes_all):
    """
    Test instantiation and kernel dict generation with an array of weights.
    """
    # Constructing using 1D arrays for weights succeeds
    phase = BlendPhaseFunction(
        components=[
            {
                "type": "isotropic"
            },
            {
                "type": "isotropic"
            },
            {
                "type": "isotropic"
            },
        ],
        weights=[np.ones((10, )),
                 np.ones((10, )),
                 np.ones((10, ))],
        bbox=[[0, 0, 0], [1, 1, 1]],
    )

    # Weights are normalised
    assert np.allclose(1 / 3, phase.weights)

    # Kernel dict generation succeeds
    ctx = KernelDictContext()
    assert phase.kernel_dict(ctx).load()
示例#10
0
def test_ramiatm_experiment_surface_adjustment(mode_mono):
    """Create a Rami4ATM experiment and assert the central patch surface is created with the
    correct parameters, according to the canopy and atmosphere."""
    from mitsuba.core import ScalarTransform4f

    ctx = KernelDictContext()

    s = Rami4ATMExperiment(
        atmosphere=HomogeneousAtmosphere(width=ureg.Quantity(42.0, "km")),
        canopy=DiscreteCanopy.homogeneous(
            lai=3.0,
            leaf_radius=0.1 * ureg.m,
            l_horizontal=10.0 * ureg.m,
            l_vertical=2.0 * ureg.m,
            padding=0,
        ),
        surface=CentralPatchSurface(central_patch=LambertianSurface(),
                                    background_surface=LambertianSurface()),
    )

    expected_trafo = ScalarTransform4f.scale(
        1400) * ScalarTransform4f.translate((-0.499642857, -0.499642857, 0.0))

    kernel_dict = s.kernel_dict(ctx=ctx)

    assert np.allclose(kernel_dict["bsdf_surface"]["weight"]["to_uv"].matrix,
                       expected_trafo.matrix)
示例#11
0
def test_leaf_cloud_kernel_dict(mode_mono):
    """Partial unit testing for :meth:`LeafCloud.kernel_dict`."""
    ctx = KernelDictContext()

    cloud_id = "my_cloud"
    cloud = LeafCloud(
        id=cloud_id,
        leaf_positions=[[0, 0, 0], [1, 1, 1]],
        leaf_orientations=[[1, 0, 0], [0, 1, 0]],
        leaf_radii=[0.1, 0.1],
        leaf_reflectance=0.5,
        leaf_transmittance=0.5,
    )

    kernel_dict = cloud.kernel_dict(ctx=ctx)

    # The BSDF is bilambertian with the parameters we initially set
    assert kernel_dict[f"bsdf_{cloud_id}"] == {
        "type": "bilambertian",
        "reflectance": {"type": "uniform", "value": 0.5},
        "transmittance": {"type": "uniform", "value": 0.5},
    }

    # Leaves are disks
    for shape_key in [f"{cloud_id}_leaf_0", f"{cloud_id}_leaf_1"]:
        assert kernel_dict[shape_key]["type"] == "disk"

    # Kernel dict is valid
    assert KernelDict(kernel_dict).load()
示例#12
0
def test_kernel_dict_duplicate_id():
    from eradiate.contexts import KernelDictContext
    from eradiate.scenes.illumination import illumination_factory

    # Upon trying to add a scene element, whose ID is already present
    # in the KernelDict, a Warning must be issued.
    with pytest.warns(Warning):
        kd = KernelDict({
            "testmeasure": {
                "type": "directional",
                "id": "testmeasure",
                "irradiance": {
                    "type": "interpolated",
                    "wavelengths": [400, 500],
                    "values": [1, 1],
                },
            }
        })

        kd.add(
            illumination_factory.convert({
                "type": "directional",
                "id": "testmeasure",
                "irradiance": {
                    "type": "interpolated",
                    "wavelengths": [400, 500],
                    "values": [2, 2],
                },
            }),
            ctx=KernelDictContext(),
        )
示例#13
0
def test_onedim_experiment_inconsistent_multiradiancemeter(mode_mono):
    # A MultiRadiancemeter measure must have all origins inside the atmosphere or none.
    # A mix of both will raise an error.

    ctx = KernelDictContext()

    # Construct with typical parameters
    test_absorption_data_set = eradiate.path_resolver.resolve(
        "tests/spectra/absorption/us76_u86_4-spectra-4000_25711.nc")
    exp = OneDimExperiment(
        surface={"type": "rpv"},
        atmosphere={
            "type": "heterogeneous",
            "molecular_atmosphere": {
                "construct": "ussa1976",
                "absorption_data_sets":
                dict(us76_u86_4=test_absorption_data_set),
            },
        },
        illumination={
            "type": "directional",
            "zenith": 45.0
        },
        measures=[
            {
                "type": "multi_radiancemeter",
                "origins": [[1, 0, 0], [1000000, 0, 0]],
                "directions": [[0, 0, -1], [0, 0, -1]],
                "id": "multi_radiancemeter",
            },
        ],
    )
    with pytest.raises(ValueError):
        exp.kernel_dict(ctx=ctx)
示例#14
0
def test_heterogeneous_single(modes_all_single, components, bin_set,
                              path_to_ussa76_approx_data):
    """
    Unit tests for a HeterogeneousAtmosphere with a single component.
    """
    # Construct succeeds
    if components == "molecular":
        if eradiate.mode().has_flags(ModeFlags.ANY_MONO):
            component = MolecularAtmosphere.ussa1976(absorption_data_sets={
                "us76_u86_4":
                path_to_ussa76_approx_data
            }, )
        elif eradiate.mode().has_flags(ModeFlags.ANY_CKD):
            component = MolecularAtmosphere.afgl_1986()
        else:
            pytest.skip(f"unsupported mode '{eradiate.mode().id}'")

        atmosphere = HeterogeneousAtmosphere(molecular_atmosphere=component)
    else:
        component = ParticleLayer()
        atmosphere = HeterogeneousAtmosphere(particle_layers=[component])

    # Produced kernel dict can be loaded
    ctx = KernelDictContext(spectral_ctx=CKDSpectralContext(bin_set=bin_set))
    assert atmosphere.kernel_dict(ctx).load()
示例#15
0
def test_heterogeneous_multi(modes_all_single, bin_set,
                             path_to_ussa76_approx_data):
    """
    Unit tests for a HeterogeneousAtmosphere with multiple (2+) components.
    """
    # Construct succeeds
    if eradiate.mode().has_flags(ModeFlags.ANY_MONO):
        molecular_atmosphere = MolecularAtmosphere.ussa1976(
            absorption_data_sets={"us76_u86_4": path_to_ussa76_approx_data}, )
    elif eradiate.mode().has_flags(ModeFlags.ANY_CKD):
        molecular_atmosphere = MolecularAtmosphere.afgl_1986()
    else:
        pytest.skip(f"unsupported mode '{eradiate.mode().id}'")

    atmosphere = HeterogeneousAtmosphere(
        molecular_atmosphere=molecular_atmosphere,
        particle_layers=[ParticleLayer() for _ in range(2)],
    )

    # Radiative property metadata are correct
    ctx = KernelDictContext(spectral_ctx=CKDSpectralContext(bin_set=bin_set))

    # Kernel dict production succeeds
    assert atmosphere.kernel_phase(ctx)
    assert atmosphere.kernel_media(ctx)
    assert atmosphere.kernel_shapes(ctx)

    # Produced kernel dict can be loaded
    kernel_dict = atmosphere.kernel_dict(ctx)
    assert kernel_dict.load()
示例#16
0
def test_discrete_canopy_padded(mode_mono, tempfile_leaves, tempfile_spheres):
    """Unit tests for :meth:`.DiscreteCanopy.padded`"""
    ctx = KernelDictContext()

    canopy = DiscreteCanopy.leaf_cloud_from_files(
        id="canopy",
        size=[100, 100, 30],
        leaf_cloud_dicts=[
            {
                "instance_filename": tempfile_spheres,
                "leaf_cloud_filename": tempfile_leaves,
                "sub_id": "leaf_cloud",
            }
        ],
    )
    # The padded canopy object is valid and instantiable
    padded_canopy = canopy.padded_copy(2)
    assert padded_canopy
    assert KernelDict.from_elements(padded_canopy, ctx=ctx).load()
    # Padded canopy has (2*padding + 1) ** 2 times more instances than original
    assert len(padded_canopy.instances(ctx)) == len(canopy.instances(ctx)) * 25
    # Padded canopy has 2*padding + 1 times larger horizontal size than original
    assert np.allclose(padded_canopy.size[:2], 5 * canopy.size[:2])
    # Padded canopy has same vertical size as original
    assert padded_canopy.size[2] == canopy.size[2]
示例#17
0
def test_rpv(mode_mono):
    ctx = KernelDictContext()

    # Default constructor
    surface = RPVSurface()

    # Check if produced scene can be instantiated
    kernel_dict = KernelDict.from_elements(surface, ctx=ctx)
    assert kernel_dict.load() is not None

    # Construct from floats
    surface = RPVSurface(width=ureg.Quantity(1000.0, "km"),
                         rho_0=0.3,
                         k=1.4,
                         g=-0.23)
    assert np.allclose(surface.width, ureg.Quantity(1e6, ureg.m))

    # Construct from mixed spectrum types
    surface = RPVSurface(
        width=ureg.Quantity(1000.0, "km"),
        rho_0=0.3,
        k={
            "type": "uniform",
            "value": 0.3
        },
        g={
            "type": "interpolated",
            "wavelengths": [300.0, 800.0],
            "values": [-0.23, 0.23],
        },
    )

    # Check if produced scene can be instantiated
    assert KernelDict.from_elements(surface, ctx=ctx).load() is not None
示例#18
0
def test_discrete_canopy_homogeneous(mode_mono):
    ctx = KernelDictContext()

    # The generate_homogeneous() constructor returns a valid canopy object
    canopy = DiscreteCanopy.homogeneous(
        n_leaves=1, leaf_radius=0.1, l_horizontal=10, l_vertical=3
    )
    assert KernelDict.from_elements(canopy, ctx=ctx).load()
示例#19
0
def test_homogeneous_phase_function(mode_mono, phase_id, ref):
    """Supports all available phase function types."""
    r = HomogeneousAtmosphere(phase={"type": phase_id})

    # The resulting object produces a valid kernel dictionary
    ctx = KernelDictContext(ref=ref)
    kernel_dict = KernelDict.from_elements(r, ctx=ctx)
    assert kernel_dict.load() is not None
示例#20
0
def test_distant_flux_direction(modes_all, direction, frame):
    d = DistantFluxMeasure(direction=direction)
    ctx = KernelDictContext()
    to_world = onedict_value(d.kernel_dict(ctx))["to_world"]
    # The reference frame is rotated as expected
    assert ek.allclose(to_world.transform_vector([1, 0, 0]), frame[0])
    assert ek.allclose(to_world.transform_vector([0, 1, 0]), frame[1])
    assert ek.allclose(to_world.transform_vector([0, 0, 1]), frame[2])
示例#21
0
def test_isotropic(modes_all):
    ctx = KernelDictContext()

    # Default constructor
    phase = IsotropicPhaseFunction()

    # Check if produced kernel dict can be instantiated
    kernel_dict = KernelDict.from_elements(phase, ctx=ctx)
    assert kernel_dict.load() is not None
示例#22
0
def test_multi_radiancemeter_args(mode_mono):
    # Instantiation succeeds
    s = MultiRadiancemeterMeasure(
        origins=[[0, 0, 0]] * 3, directions=[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
    )

    # The kernel dict can be instantiated
    ctx = KernelDictContext()
    assert KernelDict.from_elements(s, ctx=ctx).load()
示例#23
0
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
示例#24
0
def test_leaf_cloud_from_file(mode_mono, tempfile_leaves):
    """Unit testing for :meth:`LeafCloud.from_file`."""
    ctx = KernelDictContext()

    # A LeafCloud instance can be loaded from a file on the hard drive
    cloud = LeafCloud.from_file(tempfile_leaves)
    assert len(cloud.leaf_positions) == 5
    assert np.allclose(cloud.leaf_radii, 0.1 * ureg.m)
    # Produced kernel dict is valid
    assert KernelDict.from_elements(cloud, ctx=ctx).load()
示例#25
0
def test_homogeneous_width(mode_mono):
    """
    Automatically sets width to ten times the scattering mean free path.
    """
    r = HomogeneousAtmosphere()
    ctx = KernelDictContext()
    wavelength = ctx.spectral_ctx.wavelength
    assert np.isclose(
        r.kernel_width(ctx), 10.0 / compute_sigma_s_air(wavelength=wavelength)
    )
示例#26
0
def test_heterogeneous_scale(mode_mono, path_to_ussa76_approx_data):
    ctx = KernelDictContext()
    d = HeterogeneousAtmosphere(
        molecular_atmosphere=MolecularAtmosphere.ussa1976(
            absorption_data_sets={"us76_u86_4": path_to_ussa76_approx_data}, ),
        particle_layers=[ParticleLayer() for _ in range(2)],
        scale=2.0,
    ).kernel_dict(ctx)
    assert d["medium_atmosphere"]["scale"] == 2.0
    assert d.load()
示例#27
0
def test_tabulated_basic(modes_all, dataset):
    # The phase function can be constructed
    phase = TabulatedPhaseFunction(data=dataset.phase)

    # Its kernel dict can be generated
    ctx = KernelDictContext()
    kernel_dict = phase.kernel_dict(ctx)

    # The kernel dict can be loaded
    assert kernel_dict.load()
示例#28
0
def test_ramiatm_experiment_real_life(mode_mono):
    ctx = KernelDictContext()

    # Construct with typical parameters
    test_absorption_data_set = eradiate.path_resolver.resolve(
        "tests/spectra/absorption/us76_u86_4-spectra-4000_25711.nc")

    # Construct with typical parameters
    exp = Rami4ATMExperiment(
        surface={"type": "rpv"},
        atmosphere={
            "type": "heterogeneous",
            "molecular_atmosphere": {
                "construct": "ussa1976",
                "absorption_data_sets":
                dict(us76_u86_4=test_absorption_data_set),
            },
        },
        canopy={
            "type": "discrete_canopy",
            "construct": "homogeneous",
            "lai": 3.0,
            "leaf_radius": 0.1 * ureg.m,
            "l_horizontal": 10.0 * ureg.m,
            "l_vertical": 2.0 * ureg.m,
        },
        illumination={
            "type": "directional",
            "zenith": 45.0
        },
        measures=[
            {
                "type": "distant",
                "construct": "from_viewing_angles",
                "zeniths": np.arange(-60, 61, 5),
                "azimuths": 0.0,
                "id": "distant",
            },
            {
                "type": "radiancemeter",
                "origin": [1, 0, 0],
                "id": "radiancemeter"
            },
        ],
    )
    assert exp.kernel_dict(ctx=ctx).load() is not None

    # -- Distant measures get no external medium
    assert "medium" not in exp.kernel_dict(ctx=ctx)["distant"]

    # -- Radiancemeter inside the atmosphere must have a medium assigned
    assert exp.kernel_dict(ctx=ctx)["radiancemeter"]["medium"] == {
        "type": "ref",
        "id": "medium_atmosphere",
    }
示例#29
0
def test_kernel_width(mode_mono):
    obj = MyBlackSurface()

    # Size value is appropriately used as kernel object size
    ctx = KernelDictContext()
    obj.width = 1.0 * ureg.m
    assert obj.kernel_width(ctx) == 1.0 * ureg.m

    # Auto size yields 100 km kernel width
    obj.width = AUTO
    assert obj.kernel_width(ctx) == 100.0 * ureg.km

    # Override constrains auto size
    obj.width = AUTO
    ctx = KernelDictContext(override_scene_width=100.0 * ureg.m)
    assert obj.kernel_width(ctx) == 100.0 * ureg.m

    # Override with set value raises a warning
    obj.width = 1.0 * ureg.m
    assert obj.kernel_width(ctx) == 100.0 * ureg.m
示例#30
0
def test_particle_layer_eval_ckd_absorbing_only(mode_ckd, tmpdir, absorbing_only, bins):
    """eval methods return expected values for an absorbing-only layer."""
    layer = ParticleLayer(dataset=absorbing_only)
    spectral_config = CKDMeasureSpectralConfig(bin_set="10nm", bins=bins)
    spectral_ctx = spectral_config.spectral_ctxs()[0]
    assert np.all(layer.eval_sigma_s(spectral_ctx).magnitude == 0.0)
    assert np.all(layer.eval_sigma_a(spectral_ctx).magnitude > 0.0)
    assert np.all(layer.eval_albedo(spectral_ctx).magnitude == 0.0)

    ctx = KernelDictContext(spectral_ctx=spectral_ctx)
    assert layer.eval_width(ctx).magnitude > 0.0