예제 #1
0
def test_ramiatm_experiment_kernel_dict(mode_mono, padding):
    from mitsuba.core import ScalarTransform4f

    ctx = KernelDictContext()

    # Surface width is appropriately inherited from canopy, when no atmosphere is present
    s = Rami4ATMExperiment(
        atmosphere=None,
        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=padding,
        ),
        measures=[
            {
                "type": "distant",
                "id": "distant_measure"
            },
            {
                "type": "radiancemeter",
                "origin": [1, 0, 0],
                "id": "radiancemeter"
            },
        ],
    )
    kernel_scene = s.kernel_dict(ctx)
    assert np.allclose(
        kernel_scene["surface"]["to_world"].transform_point([1, -1, 0]),
        [5 * (2 * padding + 1), -5 * (2 * padding + 1), 0],
    )

    # -- Measures get no external medium assigned
    assert "medium" not in kernel_scene["distant_measure"]
    assert "medium" not in kernel_scene["radiancemeter"]

    # Surface width is appropriately inherited from atmosphere
    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=padding,
        ),
    )
    kernel_dict = s.kernel_dict(ctx)
    assert np.allclose(
        kernel_dict["surface"]["to_world"].matrix,
        ScalarTransform4f.scale([21000, 21000, 1]).matrix,
    )
예제 #2
0
def test_rami4atm_experiment_construct_measures(mode_mono):
    """
    A variety of measure specifications are acceptable
    """

    # Init with a single measure (not wrapped in a sequence)
    assert Rami4ATMExperiment(measures=MultiDistantMeasure())

    # Init from a dict-based measure spec
    # -- Correctly wrapped in a sequence
    assert Rami4ATMExperiment(measures=[{"type": "distant"}])
    # -- Not wrapped in a sequence
    assert Rami4ATMExperiment(measures={"type": "distant"})
예제 #3
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)
예제 #4
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",
    }
예제 #5
0
def test_rami4atm_experiment_construct_normalize_measures(mode_mono, padding):

    # When canopy is not None, measure target matches canopy unit cell
    exp = Rami4ATMExperiment(
        atmosphere=None,
        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=padding,
        ),
        measures=MultiDistantMeasure(),
    )
    target = exp.measures[0].target
    canopy = exp.canopy
    assert np.isclose(target.xmin, -0.5 * canopy.size[0])
    assert np.isclose(target.xmax, 0.5 * canopy.size[0])
    assert np.isclose(target.ymin, -0.5 * canopy.size[1])
    assert np.isclose(target.ymax, 0.5 * canopy.size[1])
    assert np.isclose(target.z, canopy.size[2])

    # The measure target does not depend on the atmosphere
    exp = 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=padding,
        ),
        measures=MultiDistantMeasure(),
    )
    target = exp.measures[0].target
    canopy = exp.canopy
    assert np.isclose(target.xmin, -0.5 * canopy.size[0])
    assert np.isclose(target.xmax, 0.5 * canopy.size[0])
    assert np.isclose(target.ymin, -0.5 * canopy.size[1])
    assert np.isclose(target.ymax, 0.5 * canopy.size[1])
    assert np.isclose(target.z, canopy.size[2])
예제 #6
0
def test_ramiatm_experiment_run_detailed(mode_mono):
    """
    Test for correctness of the result dataset generated by Rami4ATMExperiment.
    Note: This test is outdated, most of its content should be transferred to
    tests for measure post-processing pipelines.
    """
    exp = Rami4ATMExperiment(measures=[
        {
            "id": "toa_brf",
            "type": "distant",
            "construct": "from_viewing_angles",
            "zeniths": np.arange(-60, 61, 5),
            "azimuths": 0.0,
        },
    ])

    exp.run()

    results = exp.results["toa_brf"]

    # Post-processing creates expected variables ...
    assert set(results.data_vars) == {
        "irradiance",
        "brf",
        "brdf",
        "radiance",
        "spp",
        "srf",
    }

    # ... dimensions
    assert set(
        results["radiance"].dims) == {"sza", "saa", "x_index", "y_index", "w"}
    assert set(results["irradiance"].dims) == {"sza", "saa", "w"}

    # ... and other coordinates
    expected_coords = {
        "sza", "saa", "vza", "vaa", "x", "x_index", "y", "y_index", "w"
    }
    assert set(results["radiance"].coords) == expected_coords
    assert set(results["irradiance"].coords) == {"sza", "saa", "w"}

    # We just check that we record something as expected
    assert np.all(results["radiance"].data > 0.0)
예제 #7
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 = 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": "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)
예제 #8
0
def test_rami4atm_experiment_construct_default(mode_mono):
    """
    Rami4ATMExperiment initialises with default params in all modes
    """
    assert Rami4ATMExperiment()