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