Example #1
0
# %% Perform TFM:
grid = arim.geometry.Grid(
    xmin=-20e-3,
    xmax=20e-3,
    ymin=0.0,
    ymax=0.0,
    zmin=0.0,
    zmax=50e-3,
    pixel_size=0.15e-3,
)
speed = frame.examination_object.material.longitudinal_vel
tfm = arim.im.tfm.contact_tfm(frame, grid, speed)

# %% Plot TFM in linear scale

func_res = lambda x: np.real(x)
aplt.plot_tfm(tfm, func_res=func_res)
plt.title("TFM image - linear scale")
plt.axis("tight")

# %% Plot TFM in dB scale

clim = [-40, 0]
func_res = lambda x: arim.ut.decibel(x)
aplt.plot_tfm(tfm, func_res=func_res, interpolation="none", clim=clim)
plt.title("TFM image - dB scale")
plt.axis("tight")

# Block script until windows are closed.
plt.show()
Example #2
0
def model_full(dataset_name, use_multifreq, full_tfm=True):
    # %%
    conf = arim.io.load_conf(dataset_name)
    result_dir = conf["result_dir"]

    logger.info(f"dataset_name: {dataset_name}")

    probe = common.load_probe(conf)
    examination_object = arim.io.block_in_immersion_from_conf(conf)
    tx, rx = arim.ut.fmc(probe.numelements)
    numscanlines = len(tx)

    scatterers = common.defect_oriented_point(conf)
    grid = common.grid_near_defect(conf)
    grid_p = grid.to_oriented_points()

    probe_p = probe.to_oriented_points()
    views = bim.make_views(
        examination_object,
        probe_p,
        scatterers,
        max_number_of_reflection=1,
        tfm_unique_only=True,
    )
    views_imaging = bim.make_views(
        examination_object,
        probe_p,
        grid_p,
        max_number_of_reflection=1,
        tfm_unique_only=True,
    )

    arim.ray.ray_tracing(views.values(), convert_to_fortran_order=True)
    arim.ray.ray_tracing(views_imaging.values(), convert_to_fortran_order=True)

    if full_tfm:
        grid_large = common.make_grid_tfm(conf)
        grid_large_p = grid_large.to_oriented_points()
        views_imaging_large = bim.make_views(
            examination_object,
            probe_p,
            grid_large_p,
            max_number_of_reflection=1,
            tfm_unique_only=True,
        )
        arim.ray.ray_tracing(views_imaging_large.values(),
                             convert_to_fortran_order=True)

    if use_multifreq:
        multifreq_key = "multif"
        multifreq_key_title = "MultiFreq"
    else:
        multifreq_key = "singlef"
        multifreq_key_title = "SingleFreq"

    # %% Toneburst and time vector

    max_delay = max(
        (view.tx_path.rays.times.max() + view.rx_path.rays.times.max()
         for view in views.values()))

    numcycles = conf["model"]["toneburst"]["numcycles"]
    centre_freq = common.get_centre_freq(conf, probe)
    dt = 0.25 / centre_freq  # to adjust so that the whole toneburst is sampled
    _tmax = max_delay + 4 * numcycles / centre_freq

    numsamples = scipy.fftpack.next_fast_len(math.ceil(_tmax / dt))
    time = arim.Time(0.0, dt, numsamples)
    freq_array = np.fft.rfftfreq(len(time), dt)
    numfreq = len(freq_array)

    toneburst = arim.model.make_toneburst(numcycles,
                                          centre_freq,
                                          dt,
                                          numsamples,
                                          wrap=True)
    toneburst *= 1.0 / np.abs(hilbert(toneburst)[0])
    toneburst_f = np.fft.rfft(toneburst)

    # plot toneburst
    plt.figure(figsize=(10, 5))
    plt.subplot(1, 2, 1)
    plt.plot(1e6 * time.samples, toneburst)
    plt.title("toneburst (time domain)")
    plt.xlabel("time (µs)")

    plt.subplot(1, 2, 2)
    plt.plot(1e-6 * np.fft.rfftfreq(len(toneburst), dt), abs(toneburst_f))
    plt.title("toneburst (frequency domain)")
    plt.xlabel("frequency (MHz)")

    # %% Compute transfer function
    numangles_for_scat_precomp = 180  # 0 to disable

    model_options = dict(
        probe_element_width=probe.dimensions.x[0],
        numangles_for_scat_precomp=numangles_for_scat_precomp,
    )

    scat_obj = arim.scat.scat_factory(
        material=examination_object.block_material,
        **conf["scatterer"]["specs"])

    scat_angle = np.deg2rad(conf["scatterer"]["angle_deg"])

    transfer_function_f = np.zeros((numscanlines, numfreq), np.complex_)
    tfms = OrderedDict()
    if full_tfm:
        tfms_large = OrderedDict()
    else:
        tfms_large = None

    if use_multifreq:
        # Multi frequency model
        transfer_function_iterator = bim.multifreq_scat_transfer_functions(
            views,
            tx,
            rx,
            freq_array=freq_array,
            scat_obj=scat_obj,
            scat_angle=scat_angle,
            **model_options,
        )
    else:
        # Single frequency model
        transfer_function_iterator = bim.singlefreq_scat_transfer_functions(
            views,
            tx,
            rx,
            freq_array=freq_array,
            scat_obj=scat_obj,
            scat_angle=scat_angle,
            **model_options,
            frequency=common.get_centre_freq(conf, probe),
        )

    with arim.helpers.timeit("Main loop"):
        for viewname, partial_transfer_func in transfer_function_iterator:
            transfer_function_f += partial_transfer_func

            # imaging:
            partial_response = arim.signal.rfft_to_hilbert(
                partial_transfer_func * toneburst_f, numsamples)
            partial_frame = arim.Frame(partial_response, time, tx, rx, probe,
                                       examination_object)

            tfms[viewname] = arim.im.tfm.tfm_for_view(
                partial_frame,
                grid,
                views_imaging[viewname],
                interpolation=common.TFM_FINE_INTERP,
                fillvalue=0.0,
            )
            if full_tfm:
                tfms_large[viewname] = arim.im.tfm.tfm_for_view(
                    partial_frame,
                    grid_large,
                    views_imaging_large[viewname],
                    fillvalue=0.0,
                )

    # %% Save raw TFM results
    if save:
        with open(result_dir / f"tfm_{multifreq_key}.pickle", "wb") as f:
            pickle.dump(tfms, f, pickle.HIGHEST_PROTOCOL)
        if full_tfm:
            with open(result_dir / f"tfm_{multifreq_key}_large.pickle",
                      "wb") as f:
                pickle.dump(tfms_large, f, pickle.HIGHEST_PROTOCOL)

    # %% Measure TFM intensities

    tmp = []
    scatterer_idx = grid.closest_point(*scatterers.points[0])

    for viewname, tfm in tfms.items():
        max_tfm_idx = np.argmax(np.abs(tfm.res))
        tmp.append((
            viewname,
            np.abs(tfm.res.flat[scatterer_idx]),
            np.abs(tfm.res.flat[max_tfm_idx]),
            grid.x.flat[max_tfm_idx],
            grid.y.flat[max_tfm_idx],
            grid.z.flat[max_tfm_idx],
        ))
    intensities_df = pd.DataFrame(
        tmp,
        columns=[
            "view",
            f"Model_{multifreq_key_title}_Centre",
            f"Model_{multifreq_key_title}_Max",
            "x_max_intensity",
            "y_max_intensity",
            "z_max_intensity",
        ],
    ).set_index("view")

    if save:
        intensities_df.to_csv(
            str(result_dir / f"intensities_{multifreq_key}_unscaled.csv"))

    # %% Plot TFM (defect only)
    scale_tfm = aplt.common_dynamic_db_scale(
        [tfm.res for tfm in tfms.values()])
    # scale_tfm = itertools.repeat((None, None))

    ncols = 6
    fig, axes = plt.subplots(
        ncols=ncols,
        nrows=math.ceil(len(tfms) / ncols),
        figsize=(16, 9),
        sharex=True,
        sharey=True,
    )

    for (viewname, tfm), ax in zip(tfms.items(), axes.ravel()):
        ref_db, clim = next(scale_tfm)
        aplt.plot_tfm(
            tfm,
            ax=ax,
            scale="db",
            ref_db=ref_db,
            clim=clim,
            interpolation="none",
            savefig=False,
        )
        ax.set_title(viewname)

        if ax in axes[-1, :]:
            ax.set_xlabel("x (mm)")
        else:
            ax.set_xlabel("")
        if ax in axes[:, 0]:
            ax.set_ylabel("z (mm)")
        else:
            ax.set_ylabel("")
        amp = intensities_df.loc[viewname]
        ax.plot(amp["x_max_intensity"], amp["z_max_intensity"], "1m")
        ax.plot(scatterers.points.x, scatterers.points.z, "dm")

    fig.savefig(str(result_dir / f"tfm_model_{multifreq_key}"))

    # %%

    return tfms, tfms_large, intensities_df
Example #3
0
        patches = None
    else:
        patches = [
            mpl.patches.Rectangle(
                (reference_rect["xmin"], reference_rect["zmin"]),
                reference_rect["xmax"] - reference_rect["xmin"],
                reference_rect["zmax"] - reference_rect["zmin"],
                fill=False,
                edgecolor="magenta",
            )
        ]

    ax, _ = aplt.plot_tfm(
        tfm,
        clim=clim,
        scale="db",
        ref_db=ref_db,
        title=f"TFM {viewname}",
        savefig=False,
        patches=patches,
        draw_cbar=True,
        interpolation="none",
    )
    ax.set_adjustable("box")
    ax.axis([grid.xmin, grid.xmax, grid.zmax, 0])
    if save:
        ax.figure.savefig(str(result_dir / f"tfm_{i:02}_{viewname}"))

# Block script until windows are closed.
plt.show()
Example #4
0
#%%
size_box_x = 5e-3
size_box_z = 5e-3

reference_area = grid.points_in_rectbox(
    xmin=defect_centre["x"] - size_box_x / 2,
    xmax=defect_centre["x"] + size_box_x / 2,
    zmin=defect_centre["z"] - size_box_z / 2,
    zmax=defect_centre["z"] + size_box_z / 2,
)
scale = aplt.common_dynamic_db_scale(
    [tfm.res for tfm in tfms.values()], reference_area, db_range=40.0
)
# scale = aplt.common_dynamic_db_scale(
#    [tfm.res for tfm in tfms.values()], None, db_range=40.0
# )


for i, (viewname, tfm) in enumerate(tfms.items()):
    ref_db, clim = next(scale)

    ax, _ = aplt.plot_tfm(
        tfm,
        clim=clim,
        scale="db",
        ref_db=ref_db,
        title="TFM {viewname}".format(**locals()),
        filename="tfm_{i:02}_{viewname}".format(**locals()),
    )
    ax.plot(defect_centre["x"], defect_centre["z"], "ow")
Example #5
0
def plot_tfms(
    dataset_name, tfms, save, suffix, is_paper=False, noshow=False, db_range=40.0
):
    """
    Plot TFMs and save them in result directory
    """
    conf = arim.io.load_conf(dataset_name)
    result_dir = conf["result_dir"]

    if is_paper:
        style_context = mpl.style.context("to_pdf.mplstyle")
        figsize = (5, 2.5)
        use_cbar = False
        title = None
        interpolation = "none"
    else:
        style_context = contextlib.suppress()  # nullcontext
        figsize = (10, 5)
        use_cbar = True
        interpolation = None

    # get an element
    tfm = next(iter(tfms.values()))
    grid = tfm.grid
    try:
        reference_rect = common.reference_rect(conf)
        reference_area = grid.points_in_rectbox(**reference_rect)
    except common.NoDefect:
        reference_rect = None
        reference_area = None
    if USE_DYNAMIC_SCALE:
        scale = aplt.common_dynamic_db_scale(
            [tfm.res for tfm in tfms.values()], reference_area, db_range=db_range
        )
    else:
        scale = itertools.repeat((None, [-db_range, 0.0]))

    with style_context:
        for i, (viewname, tfm) in enumerate(tfms.items()):
            assert tfm.grid is grid

            ref_db, clim = next(scale)

            if PLOT_DEFECT_BOX and reference_rect is not None:
                patches = [common.rect_to_patch(reference_rect)]
            else:
                patches = None

            if not (is_paper):
                title = f"TFM {viewname}"

            ax, _ = aplt.plot_tfm(
                tfm,
                clim=clim,
                scale="db",
                ref_db=ref_db,
                title=title,
                savefig=False,
                figsize=figsize,
                patches=patches,
                draw_cbar=use_cbar,
                interpolation=interpolation,
            )
            ax.set_adjustable("box")
            ax.axis([grid.xmin, grid.xmax, grid.zmax, 0])
            if save:
                ax.figure.savefig(str(result_dir / f"tfm_{i:02}_{viewname}{suffix}"))
            if noshow:
                plt.close(ax.figure)
    if noshow:
        plt.close("all")
    else:
        plt.show()
Example #6
0
def locate_artefact(dataset_name, save):
    # %%
    conf = arim.io.load_conf(dataset_name)
    # conf['grid']['pixel_size'] = 2e-3  # debug
    conf["grid"]["pixel_size"] = 0.5e-3  # hardcode to make faster
    aplt.conf["savefig"] = False

    result_dir = conf["result_dir"]

    logger.info(f"dataset_name: {dataset_name}")

    # Load frame
    frame = common.load_frame(conf, apply_filter=True, expand=True)

    # Make grid
    z_backwall = conf["backwall"]["z"]
    assert not np.isnan(z_backwall)

    grid = common.make_grid_tfm(conf)
    grid_p = grid.to_oriented_points()
    probe_p = frame.probe.to_oriented_points()

    # Make views
    views = bim.make_views(
        frame.examination_object,
        probe_p,
        grid_p,
        tfm_unique_only=True,
        max_number_of_reflection=1,
    )

    # %% Plot Bscan
    bscan_ax, _ = aplt.plot_bscan_pulse_echo(frame,
                                             clim=[-60, -20],
                                             interpolation="bilinear")
    bscan_ax.figure.canvas.set_window_title("Bscan")

    # %% Perform ray tracing

    arim.ray.ray_tracing(views.values(), convert_to_fortran_order=True)

    # %% Run TFM

    tfms = OrderedDict()
    for i, view in enumerate(views.values()):
        with arim.helpers.timeit("TFM {}".format(view.name), logger=logger):
            tfms[view.name] = arim.im.tfm.tfm_for_view(frame,
                                                       grid,
                                                       view,
                                                       fillvalue=0.0)

    # %% Plot all TFM

    try:
        reference_rect = common.reference_rect(conf)
        reference_area = grid.points_in_rectbox(**reference_rect)
    except common.NoDefect:
        reference_rect = None
        reference_area = None

    if USE_DYNAMIC_SCALE:
        scale = aplt.common_dynamic_db_scale(
            [tfm.res for tfm in tfms.values()], reference_area)
    else:
        scale = itertools.repeat((None, None))

    tfm_axes = {}

    ncols = 3
    nrows = 7
    fig, axes = plt.subplots(ncols=ncols,
                             nrows=nrows,
                             figsize=(9, 12),
                             sharex=False,
                             sharey=False)
    xmin = grid.xmin
    xmax = grid.xmax
    zmin = conf["frontwall"]["z"]
    zmax = conf["backwall"]["z"]

    for i, ((viewname, tfm), ax) in enumerate(zip(tfms.items(), axes.ravel())):
        ref_db, clim = next(scale)
        clim = [-40, 0.0]
        ax, im = aplt.plot_tfm(
            tfm,
            ax=ax,
            scale="db",
            ref_db=ref_db,
            clim=clim,
            interpolation="none",
            savefig=False,
            draw_cbar=False,
        )
        ax.set_title(viewname, y=0.9, size="small")
        ax.set_adjustable("box")
        ax.axis([xmin, xmax, zmax, zmin])
        tfm_axes[viewname] = ax

        if ax in axes[-1, :]:
            ax.set_xlabel("x (mm)")
            ax.set_xticks(
                [xmin, xmax,
                 np.round((xmin + xmax) / 2, decimals=3)])
        else:
            ax.set_xlabel("")
            ax.set_xticks([])
        if ax in axes[:, 0]:
            ax.set_ylabel("z (mm)")
            ax.set_yticks(
                [zmax, zmin,
                 np.round((zmin + zmax) / 2, decimals=3)])
        else:
            ax.set_ylabel("")
            ax.set_yticks([])

    cbar = fig.colorbar(im,
                        ax=axes.ravel().tolist(),
                        location="top",
                        fraction=0.05,
                        aspect=40,
                        pad=0.03)
    cbar.ax.set_ylabel("dB")
    ax.figure.canvas.set_window_title(f"TFMs")

    return bscan_ax, tfm_axes, tfms, views
Example #7
0
def measure_tfm_intensity(dataset_name, save, noshow=False):
    conf = arim.io.load_conf(dataset_name)
    result_dir = conf["result_dir"]

    logger.info(f"dataset_name: {dataset_name}")

    frame = common.load_frame(conf, apply_filter=True, expand=True)

    grid = common.grid_near_defect(conf)
    grid_p = grid.to_oriented_points()

    probe_p = frame.probe.to_oriented_points()
    views = bim.make_views(
        frame.examination_object,
        probe_p,
        grid_p,
        max_number_of_reflection=1,
        tfm_unique_only=True,
    )
    views = common.filter_views(views, conf)

    # %%
    arim.ray.ray_tracing(views.values(), convert_to_fortran_order=True)

    # %% Run TFM
    tfms = dict()
    for viewname, view in views.items():
        tfms[viewname] = arim.im.tfm.tfm_for_view(
            frame,
            grid,
            view,
            interpolation=common.TFM_FINE_INTERP,
            fillvalue=np.nan)

    # %% Save raw TFM results
    if save:
        with open(result_dir / "tfm_experimental.pickle", "wb") as f:
            # Pickle the 'data' dictionary using the highest protocol available.
            pickle.dump(tfms, f, pickle.HIGHEST_PROTOCOL)

    # %% Plot
    scale_tfm = aplt.common_dynamic_db_scale(
        [tfm.res for tfm in tfms.values()])
    # scale_tfm = itertools.repeat((None, None))

    ncols = 6
    fig, axes = plt.subplots(
        ncols=ncols,
        nrows=math.ceil(len(tfms) / ncols),
        figsize=(16, 9),
        sharex=True,
        sharey=True,
    )

    for (viewname, tfm), ax in zip(tfms.items(), axes.ravel()):
        ref_db, clim = next(scale_tfm)
        aplt.plot_tfm(
            tfm,
            ax=ax,
            scale="db",
            ref_db=ref_db,
            clim=clim,
            interpolation="none",
            savefig=False,
        )
        ax.set_title(viewname)

        if ax in axes[-1, :]:
            ax.set_xlabel("x (mm)")
        else:
            ax.set_xlabel("")
        if ax in axes[:, 0]:
            ax.set_ylabel("z (mm)")
        else:
            ax.set_ylabel("")

    if save:
        fig.savefig(str(result_dir / "tfm_near_defect"))
    if noshow:
        plt.close("all")
    else:
        plt.show()

    # %% Measure amplitudes and save and save as csv
    data = []
    for viewname, tfm in tfms.items():
        data.append((viewname, np.max(np.abs(tfm.res))))

    intensities = pd.DataFrame(data,
                               columns=("view",
                                        "Experimental")).set_index("view")
    if save:
        intensities.to_csv(result_dir / "intensities_experimental.csv")
    return tfms, intensities
Example #8
0
def locate_defect(dataset_name, save):
    # %%
    conf = arim.io.load_conf(dataset_name)
    # conf['grid']['pixel_size'] = 2e-3
    aplt.conf["savefig"] = False

    result_dir = conf["result_dir"]

    logger.info(f"dataset_name: {dataset_name}")

    # Load frame
    frame = common.load_frame(conf, apply_filter=True, expand=True)

    # Make grid
    z_backwall = conf["backwall"]["z"]
    assert not np.isnan(z_backwall)

    grid = common.make_grid_tfm(conf)
    grid_p = grid.to_oriented_points()
    probe_p = frame.probe.to_oriented_points()

    # Make views
    views = bim.make_views(
        frame.examination_object,
        probe_p,
        grid_p,
        tfm_unique_only=True,
        max_number_of_reflection=0,
    )
    # views = {'L-L':views['L-L']}
    # if conf['views_to_use'] != 'all':
    #    views = OrderedDict([(viewname, view) for viewname, view in views.items()
    #                         if viewname in conf['views_to_use']])

    # %% Perform ray tracing

    arim.ray.ray_tracing(views.values(), convert_to_fortran_order=True)

    # %% Run TFM

    tfms = OrderedDict()
    for i, view in enumerate(views.values()):
        with arim.helpers.timeit("TFM {}".format(view.name), logger=logger):
            tfms[view.name] = arim.im.tfm.tfm_for_view(frame,
                                                       grid,
                                                       view,
                                                       fillvalue=0.0)

    # %% Matplotlib event handler
    out_file = result_dir / "conf.d/15_defect_loc.yaml"

    def save_defect_loc_on_click(event):
        if event.button != 1:
            return

        # use .item() to get a Python type instead of Numpy type
        data = dict(scatterer=dict(
            location=dict(x=event.xdata.item(), y=0.0, z=event.ydata.item())))
        out_content = "# generated by locate_defect.py\n" + yaml.dump(
            data, default_flow_style=False)

        if save:
            with out_file.open("w", encoding="utf8") as stream:
                stream.write(out_content)

        print(f"----- Output: {out_file}")
        print(out_content)
        print("-----")

    # %% Plot all TFM

    cids = []

    for i, (viewname, view) in enumerate(views.items()):
        tfm = tfms[viewname]

        ref_db = None
        clim = [-80.0, 0.0]

        ax, _ = aplt.plot_tfm(
            tfm,
            clim=clim,
            scale="db",
            ref_db=ref_db,
            title=f"TFM {viewname} - Left-click on defect to write conf",
            filename=str(result_dir / f"tfm_{i:02}_{viewname}"),
            figsize=(10, 5),
        )

        cid = ax.figure.canvas.mpl_connect("button_press_event",
                                           save_defect_loc_on_click)
        cids.append(cid)

    return cids