Example #1
0
def reconstruct_and_save_volume_2disk(file_path: str, file_name_raw: str, bScan_strt_idx: int=110, is_return_enface: str=True, file_name_recon: str=None, file_name_json_recon_params: str="DefaultReconParams") -> np.array:
    """ @param: """
    # initialize file name for saving recon volume
    if file_name_recon is None:
        file_name_recon = "recon_" + file_name_raw
    else:
        print(f"[WARNING:] You've manually entered a target file name:\n{file_name_recon}\nCheck volume output dimensions (HF and DC cropping!)")
    # ----------- Import classes/objects for recon handling ------------
    # load recon parms from file into json-object
    JSON = ConfigDataManager(filename=file_name_json_recon_params).load_json_file()
    # recon functions
    REC = OctReconstructionManager()
    # ----------- Pre-Reconstruction steps ------------
    # create files and file paths
    full_file_path_raw = os.path.join(file_path, file_name_raw)
    dims, _ = REC.get_oct_volume_dims(full_file_path_raw)
    # get all underbar-seperated file name prefixes to generate file to save to
    def parse_prefixes_file_dims(file_name: str) -> str:
        prefix = ''
        pre_split_list = file_name.split('_')[:-1]
        for i, string in enumerate(pre_split_list):
            prefix += string + '_'
        return prefix
    # ----------- Save file prefix ------------
    # update cropped A-scan length
    dims_saving = (dims[0]-int(JSON['dc_crop_samples'])-int(JSON['hf_crop_samples']), dims[1], dims[2]) 
    # create file to save to
    full_file_path_recon = os.path.join(file_path, parse_prefixes_file_dims(file_name_recon) + str(dims_saving[0]) + 'x' + str(dims_saving[1]) + 'x' + str(dims_saving[2]) + '.bin')
    if is_return_enface:
        return process_buffer_wise(REC, JSON, dims, dims_saving, full_file_path_raw, full_file_path_recon, b_scan_start_idx=bScan_strt_idx)
    process_buffer_wise(REC, JSON, dims, dims_saving, full_file_path_raw, full_file_path_recon, is_return_enface=is_return_enface, b_scan_start_idx=bScan_strt_idx)
    return
Example #2
0
def process_test_buffer(manual_json_selection: bool) -> tuple:
    Rec = OctReconstructionManager()
    path = Rec._tk_file_selection(
    )  #"Please select a file for testing the reconstruction parameters:")
    recon_data = load_and_recon_file_from_json_params(path,
                                                      manual_json_selection)
    recon_data = cv2.resize(recon_data, (900, 1600))
    # show recon data to user
    fig = plt.figure(figsize=(5, 10))
    ax = fig.add_axes([0, 0, 1, 1])
    ax.axis('off')
    plt.title("Reconstructed and reshaped b-Scan", fontsize=15)
    ax.imshow(recon_data, cmap='gray')
    plt.draw()
    plt.pause(0.001)
    # display information and ask user if they are satisfied with the reconstructed data
    response = messagebox.askyesno(
        "Ask Question",
        "Reconstruction with current parameters has finished\nPlease select \'Yes\' if you want to continue the reconstruction for all files or \'No\' if you want to adjust the reconstruction parameters"
    )
    if response == True:
        print(
            "[INFO:] PROCESSING - Continuing with reconstruction of all buffers in folder..."
        )
        plt.close()
        return True, path
    elif response == False:
        print("\'No\' was selected - please adjust parameters in *.JSON-file")
        plt.close()
        return False, path
def plot_all_recon_data(main_path: str, aScan_range: tuple) -> None:
    """ Meant to visualize the plot in function body """
    data = stack_all_scans_from_subdir(main_path, is_ret_avrgd_scans=True)
    recon_data = []
    JSON = ConfigDataManager(filename='DefaultReconParams').load_json_file()
    REC = OctReconstructionManager()
    for scan in range(data.shape[1]):
        d3 = -15
        d2 = 4
        samples_dc_crop = 25
        recon_data.append(
            REC._run_reconstruction(
                data[:, scan],
                disp_coeffs=JSON['dispersion_coefficients'],
                wind_key=JSON['windowing_key'],
                samples_hf_crop=JSON['hf_crop_samples'],
                samples_dc_crop=JSON['dc_crop_samples'],
                blck_lvl=JSON['black_lvl_for_dis'],
                scale_fac=JSON['disp_scale_factor']))
    recon_data = np.swapaxes(recon_data, 0, 1)
    data = crop_data_range(recon_data, aScan_range)
    # recon_data = recon_data[:,:10]
    fig = plot_all_scans_in_stack(
        recon_data,
        title=
        f'Reconstructed OCT Signals (cropped DC samples = ({data.shape[0]-samples_dc_crop}/{data.shape[0]}))',
        x_label="Optical Depth [a.u.]",
        y_label="Relative Signal Strength [dB (0-255)]")
    plt.show()
    return
Example #4
0
def display_reconstructed_oct_volume( data_shape: tuple=(5312, 512, 512) ) -> np.array :
    ORM = OctReconstructionManager( dtype_loading='<u1' )
    data = np.asarray( np.fromfile(ORM._tk_file_selection(), dtype='>u1') )
    data = data.reshape( data_shape )
    fig, ax = plt.subplots(2,2)
    ax[1,0].imshow(data[:, :, data.shape[-1]//2], title="B-scan along \'fast scanning axis\'")
    ax[1,1].imshow(data[:, data.shape[-2]//2, :], title="B-scan along \'slow scanning axis\'")
    ax[0,1].imshow( np.mean(data, axis=0) )
    ax[0,1].imshow( np.mean(data, axis=0), title="En face of recon volume") 
    plt.show()
    return 
def reconstruct_aScans(data_in: np.ndarray,
                       dc_crop: int = 25,
                       nd_filter: int = 3) -> np.ndarray:
    """ Performs SS-OCT reconstruction on array """
    # average stack
    stack = np.mean(data_in, axis=1)
    aLen = stack.shape[0]
    # windowing
    REC = OctReconstructionManager()
    stack = np.multiply(stack,
                        REC.create_comp_disp_vec(aLen, (5, -30, 0, 0), 'Hann'))
    # abs of iFFT of padded array
    stack = np.abs(
        np.fft.ifft(
            np.pad(stack, (aLen, 0), mode='constant', constant_values=0)))
    # scale of first half of complex conjugate F^-1(signal) to 8Bit
    stack = 20 * np.log10(np.abs(stack[dc_crop:aLen]))
    ##snr = round(np.max(stack)-np.mean(stack[5000:11000]), 0) + (nd_filter*10)
    # return a-Scan scaled within dynamic range
    return np.asarray(stack)
Example #6
0
def reconstruct_and_save_all_buffers_in_folder(
        path: str, manual_json_selection: bool) -> None:
    Rec = OctReconstructionManager()
    raw_buffer_file_list = os.listdir(os.path.dirname(path))
    # make new dir for saving
    save_dir = os.path.join(os.path.dirname(path), "Reconstructed")
    if not os.path.isdir(save_dir):
        os.mkdir(save_dir)
    for file in tqdm(raw_buffer_file_list):
        rec_data = load_and_recon_file_from_json_params(
            os.path.join(os.path.dirname(path), file), manual_json_selection)
        save_file_name = "reconstructed_" + file
        rec_data.astype('uint8').tofile(os.path.join(save_dir, save_file_name))
    print("[INFO:] Done processing folder!")
Example #7
0
def load_and_recon_file_from_json_params(
        path: str, manual_json_selection: bool) -> np.ndarray:
    Rec = OctReconstructionManager()
    raw_data = Rec.reshape_oct_volume(Rec.load_bin_file(path),
                                      Rec.get_oct_volume_dims(path)[0])
    # load recon params
    if manual_json_selection:
        with open(Rec._tk_file_selection()) as f:
            config = json.load(f)
    else:
        with open(
                os.path.abspath(
                    os.path.join(os.path.dirname(__file__), '..', 'Config',
                                 'Config_Reconstruction_Params.json'))) as f:
            config = json.load(f)
    # reconstruct buffer
    recon_data = Rec._run_reconstruction(
        raw_data, tuple(config["dispersion_coefficients"]),
        config["windowing_key"], config["hf_crop_samples"],
        config["dc_crop_samples"], config["disp_scale_range"],
        config["black_lvl_for_dis"])
    return recon_data
def plot_ascan_and_background(
        sig_path: str = r"C:\Users\PhilippsLabLaptop\Desktop\RollOff\01",
        bg_path: str = r"C:\Users\PhilippsLabLaptop\Desktop\RollOff\23"):
    # load and pre-process OCT signal
    path = sig_path
    assert os.path.isdir(path)
    signal = load_detector_signals(path)
    signal = signal - np.mean(
        signal, axis=0)  # center arounf 0, for seemless dtype-conversion
    mean_sig = np.mean(signal - np.mean(signal, axis=0), axis=1)
    # load and pre-process BG signals
    path = bg_path
    if path is not None:
        assert os.path.isdir(path)
        background = load_detector_signals(path)
    else:
        background = np.zeros_like(signal)
    background = background - np.mean(
        background, axis=0)  # center arounf 0, for seemless dtype-conversion
    mean_bg = np.mean(background - np.mean(background, axis=0), axis=1)

    lmin_sig, lmax_sig = high_low_envelopes_idxs(mean_sig, 5, 5, split=True)
    # lmin_bg, lmax_bg = high_low_envelopes_idxs(mean_bg, 5, 5, split=True)

    subbed_sig = np.subtract(signal[:, 0], background[:, 0], dtype=np.float32)
    subbed_mean_sig = np.subtract(mean_sig, mean_bg, dtype=np.float32)

    # reconstruct A-scans
    REC = OctReconstructionManager()
    d3 = -15
    d2 = 4
    d1, d0 = 0, 0

    subbed_recon_sig = REC._run_reconstruction(subbed_mean_sig,
                                               (d3, d2, d1, d0),
                                               'Hann',
                                               samples_dc_crop=50,
                                               scale_fac=63.75,
                                               blck_lvl=85)
    recon_sig = REC._run_reconstruction(mean_sig, (d3, d2, d1, d0),
                                        'Hann',
                                        samples_dc_crop=50,
                                        scale_fac=63.75,
                                        blck_lvl=85)

    def find_nearest(array, value) -> tuple:
        array = np.asarray(array)
        idx = (np.abs(array - value)).argmin()
        return array[idx], idx

    _, peak = find_nearest(recon_sig, np.max(recon_sig))
    _, half_fwhm = find_nearest(recon_sig, np.max(recon_sig) - 3)
    fwhm = 2 * np.abs(half_fwhm - peak)
    print(
        f"peak position: {peak}, left most -3dB position: {half_fwhm}, results in FWHM: {fwhm}[pxls]"
    )

    # plot
    fig, ax = plt.subplots(2, 2)
    # raw data - SIG/BG single and averaged
    ax[0, 0].plot(signal[:, 0], label='OCT Fringe Signal')
    ax[0, 0].plot(mean_sig, label='Averaged OCT Fringe Signal')
    ax[0, 0].plot(background[:, 0], label='OCT Background Signal')
    ax[0, 0].plot(mean_bg, label='Averaged OCT Background Signal')
    ax[0, 0].legend(loc='lower left')
    # envelopes
    ax[0, 1].plot(mean_sig, label='Averaged OCT Fringe Signal')
    ax[0, 1].plot(lmax_sig, mean_sig[lmax_sig], 'g', label='Maximum Envelope')
    ax[0, 1].plot(lmin_sig, mean_sig[lmin_sig], 'r', label='Minimum Envelope')
    ax[0, 1].legend(loc='lower left')
    # zoom-in on [0,0]
    ax[1, 0].plot(signal[:recon_sig.shape[0] // 50, 0] - np.mean(signal[:, 0]),
                  label="OCT Fringe Signal")
    ax[1, 0].plot(background[:recon_sig.shape[0] // 50, 0] -
                  np.mean(background[:, 0]),
                  label="OCT Background Signal")
    ax[1, 0].plot(subbed_sig[:recon_sig.shape[0] // 50],
                  label="OCT Fringe Signal - Background subtracted")
    ax[1, 0].plot(
        subbed_mean_sig[:recon_sig.shape[0] // 50],
        label=
        "Background subtracted mean signal - mean(signal)-mean(background)")
    ax[1, 0].legend(loc='lower left')

    ax[1, 1].plot(
        recon_sig[:recon_sig.shape[0] // 10],
        label=
        f"Reconstructed Averaged A-scan\n({d3},{d2},0,0) and a\nFWHM of {fwhm*1.1}µm [{fwhm}pxls]"
    )
    ax[1, 1].plot(
        subbed_recon_sig[:1500],
        label=
        f"Reconstructed Averaged & BG-subbed A-scan\n({d3},{d2},0,0) and a\nFWHM of {fwhm*1.1}µm [{fwhm}pxls]"
    )
    ax[1, 1].legend(loc='upper left')

    plt.show()
def plot_2Ascans(
        sig_path1: str = r"C:\Users\PhilippsLabLaptop\Desktop\RollOff\01",
        sig_path2: str = r"C:\Users\PhilippsLabLaptop\Desktop\RollOff\23"):
    # load and pre-process OCT signal
    path1 = sig_path1
    assert os.path.isdir(path1)
    signal1 = load_detector_signals(path1)
    signal1 = signal1 - np.mean(
        signal1, axis=0)  # center around 0, for seemless dtype-conversion
    mean_sig1 = np.mean(signal1 - np.mean(signal1, axis=0), axis=1)

    path2 = sig_path2
    assert os.path.isdir(path2)
    signal2 = load_detector_signals(path2)
    signal2 = signal2 - np.mean(
        signal2, axis=0)  # center around 0, for seemless dtype-conversion
    mean_sig2 = np.mean(signal2 - np.mean(signal2, axis=0), axis=1)

    # reconstruct A-scans
    REC = OctReconstructionManager()
    d3 = -15
    d2 = 4
    d1, d0 = 0, 0

    recon_sig1 = REC._run_reconstruction(mean_sig1, (d3, d2, d1, d0),
                                         'Hann',
                                         samples_dc_crop=50,
                                         scale_fac=63.75,
                                         blck_lvl=85)
    recon_sig2 = REC._run_reconstruction(mean_sig2, (d3, d2, d1, d0),
                                         'Hann',
                                         samples_dc_crop=50,
                                         scale_fac=63.75,
                                         blck_lvl=85)

    def find_nearest(array, value) -> tuple:
        array = np.asarray(array)
        idx = (np.abs(array - value)).argmin()
        return array[idx], idx

    _, peak1 = find_nearest(recon_sig1, np.max(recon_sig1))
    _, half_fwhm1 = find_nearest(recon_sig1, np.max(recon_sig1) - 3)
    fwhm1 = 2 * np.abs(half_fwhm1 - peak1)
    print(
        f"Peak position for scan 1: {peak1}, left most -3dB position: {half_fwhm1}, results in FWHM: {fwhm1}[pxls]"
    )

    _, peak2 = find_nearest(recon_sig2, np.max(recon_sig2))
    _, half_fwhm2 = find_nearest(recon_sig2, np.max(recon_sig2) - 3)
    fwhm2 = 2 * np.abs(half_fwhm1 - peak2)
    print(
        f"Peak position for scan 1: {peak2}, left most -3dB position: {half_fwhm2}, results in FWHM: {fwhm2}[pxls]"
    )

    # plot
    print(mean_sig1.shape, mean_sig2.shape)
    fig, ax = plt.subplots(2, 1)
    ax[0].plot(signal1[:, 0], label='OCT Fringe Signal')
    ax[0].plot(mean_sig1, label='Averaged 1st OCT Fringe Signal')
    ax[0].plot(signal2[:, 0], label='OCT Fringe Signal')
    ax[0].plot(mean_sig2, label='Averaged 2nd OCT Fringe Signal')
    ax[0].legend(loc='lower left')
    # envelopes

    ax[1].plot(recon_sig1, label='OCT Fringe Signal No. 1')
    # ax[0,0].plot(mean_sig1, label='Averaged 1st OCT Fringe Signal')
    ax[1].plot(recon_sig2, label='OCT Fringe Signal No. 2')
    # ax[0,0].plot(mean_sig2, label='Averaged 1st OCT Fringe Signal')
    ax[1].legend(loc='lower left')
    plt.show()