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)
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)
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
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
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