Beispiel #1
0
def test_multiview_tfm(use_real_grid):
    # make probe
    probe = arim.Probe.make_matrix_probe(5, 0.5e-3, 1, np.nan, 1e6)
    probe.set_reference_element("first")
    probe.reset_position()
    probe.translate([0.0, 0.0, -1e-3])

    # make frame
    tx_arr, rx_arr = arim.ut.fmc(probe.numelements)
    time = arim.Time(0.5e-6, 1 / 20e6, 100)
    # use random data but ensure reciprocity
    scanlines = np.zeros((len(tx_arr), len(time)))
    for i, (tx, rx) in enumerate(zip(tx_arr, rx_arr)):
        np.random.seed((tx * rx)**2)  # symmetric in tx and rx
        scanlines[i] = np.random.rand(len(time))
    block = arim.Material(6300, 3100)
    frame = arim.Frame(scanlines, time, tx_arr, rx_arr, probe,
                       arim.ExaminationObject(block))

    # prepare view LL-T in contact
    if use_real_grid:
        grid = arim.Grid(0.0, 0.0, 0.0, 0.0, 5e-3, 5e-3, np.nan)
        grid_interface = arim.Interface(*grid.to_oriented_points())
    else:
        grid = arim.Points(np.array([0.0, 0.0, 5e-3]), name="Grid")
        grid_interface = arim.Interface(
            *arim.geometry.default_oriented_points(grid.to_1d_points()))

    backwall = arim.geometry.points_1d_wall_z(-1e-3, 1e-3, 10e-3, 200)
    backwall_interface = arim.Interface(*backwall)
    probe_interface = arim.Interface(*probe.to_oriented_points())

    path_LL = arim.Path(
        [probe_interface, backwall_interface, grid_interface],
        [block, block],
        ["L", "L"],
    )
    path_T = arim.Path([probe_interface, grid_interface], [block], ["T"])
    view = arim.View(path_LL, path_T, "LL-T")
    arim.ray.ray_tracing([view], convert_to_fortran_order=True)

    # make TFM
    tfm = im.tfm.tfm_for_view(frame, grid, view, fillvalue=np.nan)

    # Check this value is unchanged over time!
    expected_val = 12.745499105785953
    assert tfm.res.shape == grid.shape
    if use_real_grid:
        np.testing.assert_array_almost_equal(tfm.res, [[[expected_val]]])
    else:
        np.testing.assert_allclose(tfm.res, expected_val)

    # Reverse view
    view_rev = arim.View(path_LL, path_T, "T-LL")
    tfm_rev = im.tfm.tfm_for_view(frame, grid, view_rev, fillvalue=np.nan)
    assert tfm.res.shape == grid.shape
    if use_real_grid:
        np.testing.assert_array_almost_equal(tfm_rev.res, [[[expected_val]]])
    else:
        np.testing.assert_allclose(tfm_rev.res, expected_val)
Beispiel #2
0
def test_scat_factory():
    material = arim.Material(6300.0,
                             3120.0,
                             2700.0,
                             "solid",
                             metadata={"long_name": "Aluminium"})

    fname = tests.helpers.get_data_filename("scat/scat_matlab.mat")
    scat_obj = scat.scat_factory("file", material, fname)
    assert isinstance(scat_obj, scat.ScatFromData)
    scat_obj(0.0, 0.0, 2e6)

    scat_obj = scat.scat_factory("crack_centre", material, crack_length=2.0e-3)
    assert isinstance(scat_obj, scat.CrackCentreScat)
    scat_obj(0.0, 0.0, 2e6)

    scat_obj = scat.scat_factory("sdh", material, radius=0.5e-3)
    assert isinstance(scat_obj, scat.SdhScat)
    scat_obj(0.0, 0.0, 2e6)

    scat_obj = scat.scat_factory("point", material)
    assert isinstance(scat_obj, scat.PointSourceScat)
    scat_obj(0.0, 0.0, 2e6)

    scat_obj = scat.scat_factory("crack_tip", material)
    assert isinstance(scat_obj, scat.CrackTipScat)
    scat_obj(0.0, 0.0, 2e6)
Beispiel #3
0
def test_make_views():
    xmin = -5e-3
    xmax = 5e-3
    zmin = 0.0
    zmax = 7e-3
    grid = arim.Grid(xmin, xmax, 0.0, 0.0, zmin, zmax, pixel_size=1e-3)
    grid_p = grid.to_oriented_points()
    probe = arim.probes["ima_50_MHz_128_1d"]
    probe_p = probe.to_oriented_points()
    frontwall = arim.geometry.points_1d_wall_z(xmin, xmax, zmin, 11)
    backwall = arim.geometry.points_1d_wall_z(xmin, xmax, zmax, 10)
    block_material = arim.Material(6300.0, 3120.0)

    # General ExaminationObject
    examination_object = arim.ExaminationObject(block_material)
    views = bic.make_views(
        examination_object,
        probe_p,
        grid_p,
        max_number_of_reflection=0,
        tfm_unique_only=False,
    )
    assert len(views) == 4

    with pytest.raises(ValueError):
        # Undefined backwall
        views = bic.make_views(examination_object,
                               probe_p,
                               grid_p,
                               max_number_of_reflection=2)

    # BlockInContact with a backwall
    examination_object = arim.BlockInContact(block_material, backwall=backwall)
    views = bic.make_views(
        examination_object,
        probe_p,
        grid_p,
        max_number_of_reflection=1,
        tfm_unique_only=False,
    )
    assert len(views) == 36

    with pytest.raises(ValueError):
        # Undefined frontwall
        views = bic.make_views(examination_object,
                               probe_p,
                               grid_p,
                               max_number_of_reflection=2)

    # BlockInContact with a backwall and a frontwall
    examination_object = arim.BlockInContact(block_material, frontwall,
                                             backwall)
    views = bic.make_views(
        examination_object,
        probe_p,
        grid_p,
        max_number_of_reflection=2,
        tfm_unique_only=False,
    )
    assert len(views) == 196
Beispiel #4
0
    def make_case(self, are_normals_zplus):
        """
        Source point: omega
        Dest points: 12 points along a circle of centre omega and radius 5 (points are
        spaced by  30°)

        Parameters
        ----------
        are_normals_zplus

        Returns
        -------

        """
        omega = np.array((3.0, 0.0, 5.0)) * 1e-2
        src_points = g.Points(omega.reshape([1, 3]), name="source")
        src_basis = g.default_orientations(src_points)
        src_basis = src_basis.rotate(g.rotation_matrix_y(np.pi / 6))
        source_interface = arim.Interface(
            src_points,
            src_basis,
            are_normals_on_out_rays_side=are_normals_zplus)

        # circle:
        dst_points = g.Points(np.zeros([len(self.circle_theta), 3]),
                              name="dest")
        dst_points.x[...] = omega[0]
        dst_points.y[...] = omega[1]
        dst_points.z[...] = omega[2]
        dst_points.x[...] += self.circle_radius * np.sin(self.circle_theta)
        dst_points.z[...] += self.circle_radius * np.cos(self.circle_theta)

        dst_basis = g.default_orientations(dst_points)

        dest_interface = arim.Interface(
            dst_points,
            dst_basis,
            are_normals_on_inc_rays_side=are_normals_zplus)

        material = arim.Material(1.0, metadata=dict(long_name="Dummy"))

        interfaces = [source_interface, dest_interface]

        # The i-th ray starts from the source and ends at the i-th destination point.
        shape = [len(source_interface.points), len(dest_interface.points)]
        ray_indices = np.zeros((0, *shape), arim.settings.INT)
        times = np.empty(shape, float)
        times.fill(np.nan)

        path = arim.Path(interfaces, [material], ["L"])
        ray = arim.ray.Rays(times, ray_indices, path.to_fermat_path())
        path.rays = ray
        ray_geometry = arim.ray.RayGeometry.from_path(path)
        return path, ray_geometry
Beispiel #5
0
def test_contact_tfm(use_hmc):
    # make probe
    probe = arim.Probe.make_matrix_probe(5, 0.5e-3, 1, np.nan, 1e6)
    probe.set_reference_element("first")
    probe.reset_position()
    probe.translate([0.0, 0.0, -1e-3])

    # make frame
    if use_hmc:
        tx_arr, rx_arr = arim.ut.hmc(probe.numelements)
    else:
        tx_arr, rx_arr = arim.ut.fmc(probe.numelements)

    time = arim.Time(0.5e-6, 1 / 20e6, 100)

    # use random data but ensure reciprocity
    scanlines = np.zeros((len(tx_arr), len(time)))
    for i, (tx, rx) in enumerate(zip(tx_arr, rx_arr)):
        np.random.seed((tx * rx)**2)  # symmetric in tx and rx
        scanlines[i] = np.random.rand(len(time))

    # check reciprocity
    if not use_hmc:
        for i, (tx, rx) in enumerate(zip(tx_arr, rx_arr)):
            scanline_1 = scanlines[i]
            scanline_2 = scanlines[np.logical_and(tx_arr == rx,
                                                  rx_arr == tx)][0]
            np.testing.assert_allclose(scanline_1,
                                       scanline_2,
                                       err_msg="fmc data not symmetric")

    block = arim.Material(6300, 3100)
    frame = arim.Frame(scanlines, time, tx_arr, rx_arr, probe,
                       arim.ExaminationObject(block))

    # prepare view LL-T in contact
    grid = arim.Points(np.array([0.0, 0.0, 5e-3]), name="Grid")

    tfm = im.tfm.contact_tfm(frame,
                             grid,
                             block.longitudinal_vel,
                             fillvalue=np.nan)

    # Check this value is unchanged over time!
    expected_val = 12.49925772283528
    assert tfm.res.shape == grid.shape
    np.testing.assert_allclose(tfm.res, expected_val)
def test_path_in_immersion():
    xmin = -20e-3
    xmax = 100e-3

    couplant = arim.Material(
        longitudinal_vel=1480,
        transverse_vel=None,
        density=1000.0,
        state_of_matter="liquid",
        metadata={"long_name": "Water"},
    )
    block = arim.Material(
        longitudinal_vel=6320.0,
        transverse_vel=3130.0,
        density=2700.0,
        state_of_matter="solid",
        metadata={"long_name": "Aluminium"},
    )

    probe_points, probe_orientations = arim.geometry.points_1d_wall_z(
        0e-3, 15e-3, z=0.0, numpoints=16, name="Frontwall")

    frontwall_points, frontwall_orientations = arim.geometry.points_1d_wall_z(
        xmin, xmax, z=0.0, numpoints=20, name="Frontwall")
    backwall_points, backwall_orientations = arim.geometry.points_1d_wall_z(
        xmin, xmax, z=40.18e-3, numpoints=21, name="Backwall")

    grid = arim.geometry.Grid(xmin,
                              xmax,
                              ymin=0.0,
                              ymax=0.0,
                              zmin=0.0,
                              zmax=20e-3,
                              pixel_size=5e-3)
    grid_points, grid_orientation = grid.to_oriented_points()

    interfaces = arim.models.block_in_immersion.make_interfaces(
        couplant,
        (probe_points, probe_orientations),
        (frontwall_points, frontwall_orientations),
        (backwall_points, backwall_orientations),
        (grid_points, grid_orientation),
    )
    assert interfaces["probe"].points is probe_points
    assert interfaces["probe"].orientations is probe_orientations
    assert interfaces["frontwall_trans"].points is frontwall_points
    assert interfaces["frontwall_trans"].orientations is frontwall_orientations
    assert interfaces["frontwall_refl"].points is frontwall_points
    assert interfaces["frontwall_refl"].orientations is frontwall_orientations
    assert interfaces["backwall_refl"].points is backwall_points
    assert interfaces["backwall_refl"].orientations is backwall_orientations
    assert interfaces["grid"].points is grid_points
    assert interfaces["grid"].orientations is grid_orientation

    # ------------------------------------------------------------------------------------
    # 6 paths, 21 views

    paths = arim.models.block_in_immersion.make_paths(block, couplant,
                                                      interfaces)
    assert len(paths) == 6
    assert paths["L"].to_fermat_path() == (
        probe_points,
        couplant.longitudinal_vel,
        frontwall_points,
        block.longitudinal_vel,
        grid_points,
    )
    assert paths["TL"].to_fermat_path() == (
        probe_points,
        couplant.longitudinal_vel,
        frontwall_points,
        block.transverse_vel,
        backwall_points,
        block.longitudinal_vel,
        grid_points,
    )

    for path_key, path in paths.items():
        assert path_key == path.name

    # Make views
    views = arim.models.block_in_immersion.make_views_from_paths(
        paths, tfm_unique_only=True)
    assert len(views) == 21

    view = views["LT-LT"]
    assert view.tx_path is paths["LT"]
    assert view.rx_path is paths["TL"]

    # ------------------------------------------------------------------------------------
    # 14 paths, 105 views
    paths = arim.models.block_in_immersion.make_paths(
        block, couplant, interfaces, max_number_of_reflection=2)
    assert len(paths) == 14
    assert paths["L"].to_fermat_path() == (
        probe_points,
        couplant.longitudinal_vel,
        frontwall_points,
        block.longitudinal_vel,
        grid_points,
    )
    assert paths["TL"].to_fermat_path() == (
        probe_points,
        couplant.longitudinal_vel,
        frontwall_points,
        block.transverse_vel,
        backwall_points,
        block.longitudinal_vel,
        grid_points,
    )
    assert paths["TTL"].to_fermat_path() == (
        probe_points,
        couplant.longitudinal_vel,
        frontwall_points,
        block.transverse_vel,
        backwall_points,
        block.transverse_vel,
        frontwall_points,
        block.longitudinal_vel,
        grid_points,
    )

    for path_key, path in paths.items():
        assert path_key == path.name

    # Make views
    views = arim.models.block_in_immersion.make_views_from_paths(
        paths, tfm_unique_only=True)
    assert len(views) == 105

    view = views["LT-LT"]
    assert view.tx_path is paths["LT"]
    assert view.rx_path is paths["TL"]
def test_fulltime_model(use_multifreq, show_plots):
    # Setup
    couplant = arim.Material(longitudinal_vel=1480.0,
                             density=1000.0,
                             state_of_matter="liquid")
    block = arim.Material(
        longitudinal_vel=6320.0,
        transverse_vel=3130.0,
        density=2700.0,
        state_of_matter="solid",
        longitudinal_att=arim.material_attenuation_factory("constant", 2.0),
        transverse_att=arim.material_attenuation_factory("constant", 20.0),
    )

    probe = arim.Probe.make_matrix_probe(20, 1e-3, 1, np.nan, 5e6)
    probe_element_width = 0.8e-3
    probe.set_reference_element("first")
    probe.reset_position()
    probe.translate([0.0, 0.0, -5e-3])
    probe.rotate(arim.geometry.rotation_matrix_y(np.deg2rad(10)))

    probe_p = probe.to_oriented_points()
    frontwall = arim.geometry.points_1d_wall_z(numpoints=1000,
                                               xmin=0.0e-3,
                                               xmax=40.0e-3,
                                               z=0.0,
                                               name="Frontwall")
    backwall = arim.geometry.points_1d_wall_z(numpoints=1000,
                                              xmin=0.0e-3,
                                              xmax=40.0e-3,
                                              z=30.0e-3,
                                              name="Backwall")
    scatterer_p = arim.geometry.default_oriented_points(
        arim.Points([[35e-3, 0.0, 20e-3]]))
    all_points = [probe_p, frontwall, backwall, scatterer_p]

    # if show_plots:
    #     import arim.plot as aplt
    #     aplt.plot_interfaces(
    #         all_points, markers=["o", "o", "o", "d"], show_orientations=True
    #     )
    #     aplt.plt.show()

    exam_obj = arim.BlockInImmersion(block, couplant, frontwall, backwall,
                                     scatterer_p)
    scat_obj = arim.scat.scat_factory(material=block,
                                      kind="sdh",
                                      radius=0.5e-3)
    scat_funcs = scat_obj.as_angles_funcs(probe.frequency)
    scat_angle = 0.0

    tx_list, rx_list = arim.ut.fmc(probe.numelements)

    # Toneburst
    dt = 0.25 / probe.frequency  # to adjust so that the whole toneburst is sampled
    toneburst_time, toneburst, toneburst_t0_idx = arim.model.make_toneburst2(
        5, probe.frequency, dt, num_before=1)
    toneburst_f = np.fft.rfft(toneburst)
    toneburst_freq = np.fft.rfftfreq(len(toneburst_time), dt)

    # Allocate a long enough time vector for the timetraces
    views = bim.make_views(
        exam_obj,
        probe_p,
        scatterer_p,
        max_number_of_reflection=0,
        tfm_unique_only=False,
    )
    arim.ray.ray_tracing(views.values())
    max_delay = max(
        (view.tx_path.rays.times.max() + view.rx_path.rays.times.max()
         for view in views.values()))
    timetraces_time = arim.Time(
        0.0, dt,
        math.ceil(max_delay / dt) + len(toneburst_time))
    timetraces = None

    # Run model
    if use_multifreq:
        model_freq_array = toneburst_freq
    else:
        model_freq_array = probe.frequency

    transfer_function_iterator = bim.scat_unshifted_transfer_functions(
        views,
        tx_list,
        rx_list,
        model_freq_array,
        scat_obj,
        probe_element_width=probe_element_width,
        use_directivity=True,
        use_beamspread=True,
        use_transrefl=True,
        use_attenuation=True,
        scat_angle=scat_angle,
        numangles_for_scat_precomp=120,
    )

    for unshifted_transfer_func, delays in transfer_function_iterator:
        timetraces = arim.model.transfer_func_to_timetraces(
            unshifted_transfer_func,
            delays,
            timetraces_time,
            toneburst_time,
            toneburst_freq,
            toneburst_f,
            toneburst_t0_idx,
            timetraces=timetraces,
        )
    frame = arim.Frame(timetraces, timetraces_time, tx_list, rx_list, probe,
                       exam_obj)
    if show_plots:
        import matplotlib.pyplot as plt
        import arim.plot as aplt

        aplt.plot_bscan_pulse_echo(frame)
        plt.title(
            f"test_fulltime_model - Bscan - use_multifreq={use_multifreq}")

        tx = 0
        rx = probe.numelements - 1
        plt.figure()
        plt.plot(np.real(frame.get_timetrace(tx, rx)),
                 label=f"tx={tx}, rx={rx}")
        plt.plot(np.real(frame.get_timetrace(rx, tx)),
                 label=f"tx={rx}, rx={tx}")
        plt.title(f"test_fulltime_model - use_multifreq={use_multifreq}")
        plt.legend()
        plt.show()
def test_model(scat_specs, show_plots):
    couplant = arim.Material(
        longitudinal_vel=1480.0,
        density=1000.0,
        state_of_matter="liquid",
        longitudinal_att=arim.material_attenuation_factory("constant", 1.0),
    )
    block = arim.Material(
        longitudinal_vel=6320.0,
        transverse_vel=3130.0,
        density=2700.0,
        state_of_matter="solid",
        longitudinal_att=arim.material_attenuation_factory("constant", 2.0),
        transverse_att=arim.material_attenuation_factory("constant", 3.0),
    )

    probe = arim.Probe.make_matrix_probe(5, 1e-3, 1, np.nan, 5e6)
    probe_element_width = 0.8e-3
    probe.set_reference_element("first")
    probe.reset_position()
    probe.translate([0.0, 0.0, -5e-3])
    probe.rotate(arim.geometry.rotation_matrix_y(np.deg2rad(10)))

    probe_p = probe.to_oriented_points()
    frontwall = arim.geometry.points_1d_wall_z(numpoints=1000,
                                               xmin=-5.0e-3,
                                               xmax=20.0e-3,
                                               z=0.0,
                                               name="Frontwall")
    backwall = arim.geometry.points_1d_wall_z(numpoints=1000,
                                              xmin=-5.0e-3,
                                              xmax=20.0e-3,
                                              z=30.0e-3,
                                              name="Backwall")
    scatterer_p = arim.geometry.default_oriented_points(
        arim.Points([[19e-3, 0.0, 20e-3]]))
    all_points = [probe_p, frontwall, backwall, scatterer_p]

    # import arim.plot as aplt
    # aplt.plot_interfaces(all_points, markers=['o', 'o', 'o', 'd'],
    #                      show_orientations=True)
    # aplt.plt.show()

    exam_obj = arim.BlockInImmersion(block, couplant, frontwall, backwall,
                                     scatterer_p)
    scat_obj = arim.scat.scat_factory(material=block, **scat_specs)
    scat_funcs = scat_obj.as_angles_funcs(probe.frequency)

    # compute only a subset of the FMC: first row and first column
    tx = np.zeros(probe.numelements * 2, np.int_)
    tx[:probe.numelements] = np.arange(probe.numelements)
    rx = np.zeros(probe.numelements * 2, np.int_)
    rx[probe.numelements:] = np.arange(probe.numelements)

    # Compute model
    views = bim.make_views(exam_obj,
                           probe_p,
                           scatterer_p,
                           max_number_of_reflection=2)
    arim.ray.ray_tracing(views.values())
    ray_weights = bim.ray_weights_for_views(views, probe.frequency,
                                            probe_element_width)
    lti_coefficients = collections.OrderedDict()
    for viewname, view in views.items():
        amp_obj = arim.model.model_amplitudes_factory(tx, rx, view,
                                                      ray_weights, scat_funcs)
        lti_coefficients[viewname] = amp_obj[0]

    # Test reciprocity
    for i, viewname in enumerate(views):
        viewname_r = arim.ut.reciprocal_viewname(viewname)
        lhs = lti_coefficients[viewname][:probe.
                                         numelements]  # (tx=k, rx=0) for all k
        rhs = lti_coefficients[viewname_r][
            probe.numelements:]  # (tx=0, rx=k) for all k

        max_err = np.max(np.abs(lhs - rhs))
        err_msg = "view {} (#{}) - max_err={}".format(viewname, i, max_err)

        tol = dict(rtol=1e-7, atol=1e-8)

        try:
            np.testing.assert_allclose(lhs, rhs, err_msg=err_msg, **tol)
        except AssertionError as e:
            if show_plots:
                import matplotlib.pyplot as plt

                fig, axes = plt.subplots(nrows=2, sharex=True)
                ax = axes[0]
                ax.plot(lhs.real, label="tx=k, rx=0")
                ax.plot(rhs.real, label="tx=0, rx=k")
                ax.set_title(scat_obj.__class__.__name__ +
                             "\n {} and {}".format(viewname, viewname_r))
                ax.set_ylabel("real")
                ax.legend()
                ax = axes[1]
                ax.plot(lhs.imag, label="tx=k, rx=0")
                ax.plot(rhs.imag, label="tx=0, rx=k")
                ax.legend()
                ax.set_xlabel("element index k")
                ax.set_ylabel("imag")
                plt.show()
            raise e