Example #1
0
def stack_hitology_volumes(rabbit, block_paths):

    def_ablations = []
    def_combineds = []
    out_dir = f'/hdscratch/ucair/{rabbit}/microscopic/recons/'
    if not os.path.exists(out_dir):
        os.makedirs(out_dir)

    for block_path in block_paths:
        block = block_path.split('/')[-1]
        histology_dir = f'/hdscratch/ucair/{rabbit}/microscopic/{block}/'
        def_dir = f'{histology_dir}/volume/deformable/'

        # Load the deformed volume
        def_ablation = io.LoadITKFile(f'{def_dir}/{block}_ablation_segmentation_to_exvivo.mhd', device=device)
        # def_combined = io.LoadITKFile(f'{def_dir}/{block}_ablation_and_transition_segmentation_to_invivo.mhd',
        #                               device=device)

        # Threshold the volume
        def_ablation.data = (def_ablation.data >= 0.8).float()
        # def_combined.data = (def_combined.data >= 0.8).float()

        def_ablations.append(def_ablation)
        # def_combineds.append(def_combined)

    full_ablation = def_ablations[0].copy()
    full_ablation = full_ablation * 0.0
    for i, v in enumerate(def_ablations, 1):
        if v.sum() != 0.0:
            io.SaveITKFile(v, f'/home/sci/blakez/test_outs/volume{i}.nii.gz')
        full_ablation = full_ablation + v

    full_ablation.data = (full_ablation.data > 0.0).float()

    io.SaveITKFile(full_ablation, f'{out_dir}all_ablation_segs_to_exvivo.mhd')
def stack_image_volumes(rabbit, block_paths, base_dir='/hdscratch/ucair/'):

    def_images = []
    out_dir = f'{base_dir}{rabbit}/microscopic/recons/'
    if not os.path.exists(out_dir):
        os.makedirs(out_dir)

    for block_path in block_paths:
        block = block_path.split('/')[-1]
        histology_dir = f'{base_dir}{rabbit}/microscopic/{block}/'
        def_dir = f'{histology_dir}/volume/deformable/'

        # Load the deformed volume
        if not os.path.exists(f'{def_dir}/{block}_image_volume_to_invivo.mhd'):
            continue
        def_image = io.LoadITKFile(
            f'{def_dir}/{block}_image_volume_to_invivo.mhd', device=device)

        def_images.append(def_image.copy())

    full_ablation = def_images[0].copy()
    full_ablation = full_ablation * 0.0
    for v in def_images:
        full_ablation.data = torch.stack([full_ablation.data, v.data],
                                         dim=0).max(0)[0]

    io.SaveITKFile(full_ablation, f'{out_dir}all_images_to_invivo.mhd')
Example #3
0
def blocks_to_exvivo(rabbit, base_dir='/hdscratch/ucair/'):
    # import RabbitCommon as rc

    base_path = f'{base_dir}{rabbit}/blockface/'
    block_list = sorted(glob.glob(f'{base_path}block*'))

    device = 'cuda:1'
    rerun = True

    # Deform all of the blocks
    for block_path in block_list:
        block = block_path.split('/')[-1]
        print(f'Deforming {block} ... ', end='')
        out_path = f'{base_path}{block}/'

        if not os.path.exists(f'{out_path}/volumes/deformable/'):
            os.makedirs(f'{out_path}/volumes/deformable/')

        bf_name = f'{block_path}/volumes/raw/scatter_volume.mhd'
        block_vol = io.LoadITKFile(bf_name, device=device)

        # generate the deformation to the stacked block
        if not os.path.exists(f'{out_path}/volumes/deformable/{block}_to_exvivo.nii.gz') or rerun:
            to_exvivo = generate(rabbit, block=block, source_space='blockface', target_space='exvivo', base_dir=base_dir)
            block_as_exvivo = so.ApplyGrid.Create(to_exvivo, device=device)(block_vol, to_exvivo)
            io.SaveITKFile(block_as_exvivo, f'{out_path}/volumes/deformable/{block}_to_exvivo.nii.gz')
            del block_as_exvivo, to_exvivo
            torch.cuda.empty_cache()

        print('done')
Example #4
0
def deform_histology_volumes(rabbit, block):

    rerun = True

    blockface_dir = f'/hdscratch/ucair/{rabbit}/blockface/{block}/'
    histology_dir = f'/hdscratch/ucair/{rabbit}/microscopic/{block}/'

    raw_dir = f'{histology_dir}/volume/raw/'
    out_dir = f'{histology_dir}/volume/deformable/'

    if not os.path.exists(out_dir):
        os.makedirs(out_dir)

    if os.path.exists(f'{out_dir}/{block}_ablation_segmentation_to_exvivo.mhd') and not rerun:
        return

    deformation = generate(rabbit, block, source_space='blockface', target_space='exvivo')
    deformation.to_(device=device)
    # Load the original volume
    ablation_vol = io.LoadITKFile(f'{raw_dir}/{block}_ablation_segmentation.mhd', device=device)
    ablation_vol.data = (ablation_vol.data >= 0.5).float()
    # combined_vol = io.LoadITKFile(f'{raw_dir}/{block}_ablation_and_transition_segmentation.mhd', device=device)
    def_ablation = so.ApplyGrid.Create(deformation, device=device)(ablation_vol, deformation)
    # def_combined = so.ApplyGrid.Create(deformation, device=device)(combined_vol, deformation)
    io.SaveITKFile(def_ablation, f'{out_dir}/{block}_ablation_segmentation_to_exvivo.mhd')
Example #5
0
def convert_hdf5(block_path, raw_mic_dir):

    block = block_path.split('/')[-1]

    mic_list = sorted(glob.glob(f'{block_path}/raw/*_image.tif'))
    # if mic_list == []:
    mic_list += sorted(glob.glob(f'{block_path}/raw/*_image.jpg'))

    img_nums = [x.split('/')[-1].split('_')[1] for x in mic_list]

    # Load the image
    for img in img_nums:
        print(f'Processing {block}, {img} ... ', end='')
        mic_file = f'{raw_mic_dir}{block}/hdf5/{block}_img{img}_image.hdf5'

        try:
            mic = io.LoadITKFile(
                f'{raw_mic_dir}{block}/raw/IMG_{img}_histopathology_image.tif')
        except RuntimeError:
            mic = io.LoadITKFile(
                f'{raw_mic_dir}{block}/raw/IMG_{img}_histopathology_image.jpg')

        with h5py.File(mic_file, 'w') as f:
            g = f.create_group('RawImage')
            g.create_dataset('ImageData', data=mic.data.numpy())

        print('Done')
def deform_image_volumes(rabbit, block, base_dir='/hdscratch/ucair/'):

    histology_dir = f'{base_dir}{rabbit}/microscopic/{block}/'

    raw_dir = f'{histology_dir}/volume/raw/'
    out_dir = f'{histology_dir}/volume/deformable/'

    if not os.path.exists(out_dir):
        os.makedirs(out_dir)

    deformation = generate(rabbit,
                           block,
                           source_space='blockface',
                           target_space='invivo',
                           base_dir=base_dir,
                           pad_mode='zeros')

    def_file = f'/home/sci/blakez/ucair/longitudinal/{rabbit}/'
    def_file += 'deformation_fields/Day3_non_contrast_VIBE_interday_deformation_incomp.nii.gz'
    day0 = io.LoadITKFile(
        f'/hdscratch/ucair/AcuteBiomarker/Data/{rabbit}/{rabbit}_day3_to_day0_phi_inv.nii.gz',
        device=device)

    deformation = so.ComposeGrids.Create(
        device=device, padding_mode='zeros')([day0, deformation])

    deformation.to_(device=device)
    deformation.set_size((512, 512, 512))
    # Load the original volume
    image_vol = io.LoadITKFile(f'{raw_dir}/{block}_image_volume.mhd',
                               device=device)
    def_image = so.ApplyGrid.Create(deformation, device=device)(image_vol,
                                                                deformation)

    test_diff_z = np.diff(deformation.data[0, :].cpu().numpy())
    test_diff_y = np.diff(deformation.data[1, :].cpu().numpy())
    test_diff_x = np.diff(deformation.data[2, :].cpu().numpy())

    test_diff_z_small = np.abs(test_diff_z) >= 0.5
    test_diff_y_small = np.abs(test_diff_y) >= 0.5
    test_diff_x_small = np.abs(test_diff_x) >= 0.5

    mask = np.logical_and(np.logical_and(test_diff_x == 0, test_diff_y == 0),
                          test_diff_z == 0)
    mask_small = np.logical_and(
        np.logical_and(test_diff_x_small == 0, test_diff_y_small == 0),
        test_diff_z_small == 0)

    final_mask = np.logical_and(mask == False, mask_small == True)

    mask = torch.zeros_like(def_image.data)[0, None]
    mask[:, :, :, :-1] = torch.tensor(final_mask)

    def_image.data = def_image.data * mask

    io.SaveITKFile(def_image, f'{out_dir}/{block}_image_volume_to_invivo.mhd')
def stack_hitology_volumes(rabbit, block_paths, base_dir='/hdscratch/ucair/'):

    def_ablations = []
    def_combineds = []
    out_dir = f'{base_dir}{rabbit}/microscopic/recons/'
    if not os.path.exists(out_dir):
        os.makedirs(out_dir)

    for block_path in block_paths:
        block = block_path.split('/')[-1]
        histology_dir = f'{base_dir}{rabbit}/microscopic/{block}/'
        def_dir = f'{histology_dir}/volume/deformable/'

        # Load the deformed volume
        if not os.path.exists(
                f'{def_dir}/{block}_ablation_segmentation_to_invivo.mhd'):
            continue
        def_ablation = io.LoadITKFile(
            f'{def_dir}/{block}_ablation_segmentation_to_invivo.mhd',
            device=device)
        def_combined = io.LoadITKFile(
            f'{def_dir}/{block}_ablation_and_transition_segmentation_to_invivo.mhd',
            device=device)

        # Threshold the volume
        def_ablation.data = (def_ablation.data >= 0.8).float()
        def_combined.data = (def_combined.data >= 0.8).float()

        def_ablations.append(def_ablation)
        def_combineds.append(def_combined)

    full_ablation = def_ablations[0].copy()
    full_ablation = full_ablation * 0.0
    for v in def_ablations:
        full_ablation = full_ablation + v

    full_ablation.data = (full_ablation.data > 0.0).float()

    io.SaveITKFile(full_ablation, f'{out_dir}all_ablation_segs_to_invivo.mhd')

    full_combined = def_ablations[0].copy()
    full_combined = full_combined * 0.0
    for v in def_combineds:
        full_combined = full_combined + v

    full_combined.data = (full_combined.data > 0.0).float()

    io.SaveITKFile(full_combined,
                   f'{out_dir}all_ablation_and_transition_segs_to_invivo.mhd')
Example #8
0
def recon_prediction(pred, rabbit, region='test'):
    # Load the target volume
    data_dir = f'/hdscratch2/NoncontrastBiomarker/Data/'
    if region == 'train':
        mask = io.LoadITKFile(f'{data_dir}{rabbit}/{rabbit}_train_mask.nrrd')
    else:
        mask = io.LoadITKFile(f'{data_dir}{rabbit}/{rabbit}_thermal_tissue.nrrd')

    out_vol = mask.clone()
    if hasattr(pred, 'float'):
        out_vol.data[mask.data.bool()] = pred.float()
    else:
        out_vol.data[mask.data.bool()] = torch.tensor(pred).float()

    return out_vol
Example #9
0
def main(rabbit, base_dir='/hdscratch/ucair/'):

    device = 'cuda:1'

    in_path = f'{base_dir}{rabbit}/mri/exvivo/volumes/raw/'
    out_base = f'{base_dir}{rabbit}/mri/exvivo/volumes/deformable/invivo/'
    if not os.path.exists(out_base):
        os.makedirs(out_base)

    to_invivo = generate(rabbit,
                         source_space='exvivo',
                         target_space='invivo',
                         base_dir=base_dir)

    t2_file = sorted(glob.glob(f'{in_path}*t2*'))
    t1_file = sorted(glob.glob(f'{in_path}*VIBE*'))
    if len(t1_file) > 1:
        t1_file = [x for x in t1_file if '0p5' in x]

    exvivo_t2 = io.LoadITKFile(t2_file[0], device=device)
    exvivo_t1 = io.LoadITKFile(t1_file[0], device=device)

    def_t2 = so.ApplyGrid.Create(to_invivo, device=device)(exvivo_t2,
                                                           to_invivo)
    def_t1 = so.ApplyGrid.Create(to_invivo, device=device)(exvivo_t1,
                                                           to_invivo)

    io.SaveITKFile(def_t2,
                   f'{out_base}exvivo_t2_def_to_invivo_{rabbit}.nii.gz')
    io.SaveITKFile(def_t1,
                   f'{out_base}exvivo_t1_def_to_invivo_{rabbit}.nii.gz')
    # #
    # to_exvivo = generate(rabbit, source_space='invivo', target_space='exvivo')
    # to_exvivo_affine = generate_affine_only(rabbit, source_space='invivo', target_space='exvivo')
    #
    # invivo = io.LoadITKFile(sorted(glob.glob(f'/hdscratch/ucair/{rabbit}/mri/invivo/volumes/raw/*t2*'))[0], device=device)
    # aff_invivo = so.ApplyGrid.Create(to_exvivo_affine, device=device)(invivo, to_exvivo_affine)
    # def_invivo = so.ApplyGrid.Create(to_exvivo, device=device)(invivo, to_exvivo)
    #
    # io.SaveITKFile(aff_invivo, f'/home/sci/blakez/test_outs/invivo_aff_to_exvivo_npv_{rabbit}.nii.gz')
    # io.SaveITKFile(def_invivo, f'/home/sci/blakez/test_outs/invivo_def_to_exvivo_npv_{rabbit}.nii.gz')
    #
    # io.SaveITKFile(def_exvivo, f'{out_base}/invivo/{exvivo_name}_to_invivo.nii.gz')

    print('done')
def block_stitch(block_path):
    block = block_path.split('/')[-1]

    # Load the deformabale transformation
    phi = io.LoadITKFile(f'{block_path}/volumes/raw/{block}_phi_stitch.mhd',
                         device=device)
    phi.set_size((60, 1024, 1024))

    return phi
Example #11
0
def get_day0_to_day3(data_path):

    # Load the deformabale transformation
    phi_inv = io.LoadITKFile(
        f'{data_path}/volumes/raw/day0_to_day3_phi_inv.mhd', device=device
    )
    phi_inv.set_size((256, 256, 256))

    return phi_inv
def stacked_blocks_to_block(block_path):

    block = block_path.split('/')[-1]

    # Need to determine the output grid
    output_grid = io.LoadITKFile(
        f'{block_path}/volumes/raw/difference_volume.mhd', device=device)
    aff_grid = core.StructuredGrid.FromGrid(output_grid, channels=3)
    del output_grid
    torch.cuda.empty_cache()
    aff_grid.set_size((60, 1024, 1024), inplace=True)
    aff_grid.set_to_identity_lut_()

    # Load the affine
    aff = np.loadtxt(f'{block_path}/surfaces/raw/{block}_rigid_tform.txt')
    aff = torch.tensor(aff, device=device, dtype=torch.float32)

    # Apply the FORWARD affine to the deformation
    # aff = aff.inverse()
    a = aff[0:3, 0:3].float()
    t = aff[-0:3, 3].float()

    # Create a deformation from the affine that lives in the stacked blocks space

    aff_grid.data = aff_grid.data.flip(0)

    aff_grid.data = torch.matmul(
        a,
        aff_grid.data.permute(list(range(1, 3 + 1)) + [0]).unsqueeze(-1))
    aff_grid.data = (aff_grid.data.squeeze() + t).permute([-1] +
                                                          list(range(0, 3)))

    aff_grid.data = aff_grid.data.flip(0)

    # Load the deformabale transformation
    phi = io.LoadITKFile(f'{block_path}/volumes/raw/{block}_phi_stacking.mhd',
                         device=device)
    phi.set_size((60, 1024, 1024))

    # Compose the grids
    deformation = so.ComposeGrids.Create(device=device)([aff_grid, phi])

    return deformation
def mr_to_exvivo(day3_dir):

    output_grid = io.LoadITKFile(
        '/home/sci/blakez/ucair/18_047/rawVolumes/ExVivo_2018-07-26/011_----_3D_VIBE_0p5iso_cor_3ave.nii.gz',
        device=device)

    aff_grid = core.StructuredGrid.FromGrid(output_grid, channels=3)
    del output_grid
    torch.cuda.empty_cache()
    aff_grid.set_size((256, 256, 256), inplace=True)
    aff_grid.set_to_identity_lut_()

    # Load the affine
    aff = np.loadtxt(f'{day3_dir}surfaces/raw/exvivo_to_invivo_affine.txt')
    aff = torch.tensor(aff, device=device, dtype=torch.float32)

    # Apply the FORWARD affine to the deformation
    # aff = aff.inverse()
    a = aff[0:3, 0:3].float()
    t = aff[-0:3, 3].float()

    # Create a deformation from the affine that lives in the stacked blocks space

    aff_grid.data = aff_grid.data.flip(0)

    aff_grid.data = torch.matmul(
        a,
        aff_grid.data.permute(list(range(1, 3 + 1)) + [0]).unsqueeze(-1))
    aff_grid.data = (aff_grid.data.squeeze() + t).permute([-1] +
                                                          list(range(0, 3)))

    aff_grid.data = aff_grid.data.flip(0)

    # Load the defromabale transformation
    phi = io.LoadITKFile(f'{day3_dir}volumes/deformable/invivo_phi.mhd',
                         device=device)
    phi.set_size((256, 256, 256))

    deformation = so.ComposeGrids.Create(device=device)([aff_grid, phi])

    return deformation
def block_stitch(rabbit, block, direction, base_dir='/hdscratch/ucair/'):

    # block = block_path.split('/')[-1]
    block_path = f'{base_dir}{rabbit}/blockface/{block}/'

    # Load the deformabale transformation
    stitch_block = io.LoadITKFile(
        f'{block_path}/volumes/raw/{block}_{direction}_stitch.mhd', device=device
    )
    stitch_block.set_size((60, 1024, 1024))

    return stitch_block
Example #15
0
def generate_hist_label(rabbit, base_dir, out_path):

    rerun = True
    device = 'cuda:1'

    # if os.path.exists(f'{out_path}/{rabbit}_hist_label.nii.gz') and not rerun:
    #     print(f'Processing label for {rabbit} ... done')
    #     return

    print(f'Processing label for {rabbit} ... ', end='')
    # Get the path for the
    # try:
    deform = io.LoadITKFile(f'{out_path}/{rabbit}_day3_to_day0_phi_inv.nii.gz',
                            device=device)
    # except:
    #     def_file = f'/home/sci/blakez/ucair/longitudinal/{rabbit}/'
    #     def_file += 'deformation_fields/Day3_non_contrast_VIBE_interday_deformation_incomp.nii.gz'
    #     deform = io.LoadITKFile(def_file, device=device)
    #     io.SaveITKFile(deform, f'{out_path}/{rabbit}_day3_to_day0_phi_inv.nii.gz')

    # Load the ablation to day3 segmentation
    hist_file = f'{base_dir}/{rabbit}/microscopic/recons/all_ablation_segs_to_invivo.nrrd'
    if not os.path.exists(hist_file):
        hist_file = f'{base_dir}/{rabbit}/microscopic/recons/all_ablation_segs_to_invivo.mhd'

    hist_seg = io.LoadITKFile(hist_file, device=device)
    def_hist = so.ApplyGrid.Create(deform, device=device)(hist_seg, deform)
    def_hist.to_('cpu')

    def_hist.data = (def_hist.data >= 0.5).float()

    def_hist_np = binary_erosion(binary_dilation(def_hist.data.squeeze(),
                                                 iterations=4),
                                 iterations=4)
    def_hist.data = torch.tensor(def_hist_np).unsqueeze(0).float()

    io.SaveITKFile(def_hist, f'{out_path}/{rabbit}_hist_label.nii.gz')

    print('done')
Example #16
0
def process_mrti_data(rabbit, out_path):
    rerun = False
    if os.path.exists(f'{out_path}/{rabbit}_thermal_vol.nii.gz') and not rerun:
        print(f'Processing MRTI for {rabbit} ... done')
        return
    print(f'Processing MRTI for {rabbit} ... ', end='')
    data_dir = f'/hdscratch/ucair/AcuteBiomarker/Data/mrti/'
    files = sorted(glob.glob(f'{data_dir}/*'))
    mat_file = [x for x in files if rabbit in x][0]

    mrti_dict = loadmat(mat_file)

    cs_data = np.transpose(mrti_dict['PosDCS'][:, :, :, 0:3], (2, 1, 0, 3))
    mrti_data = np.transpose(mrti_dict['temps'], (2, 1, 0, 3))
    ctd_map = np.nan_to_num(np.transpose(mrti_dict['CTD_Map'], (2, 1, 0)),
                            nan=1.0)
    ctd_map = np.log(ctd_map)
    origin = np.ascontiguousarray(cs_data[0, 0, 0, ::-1])

    thermal_vol = core.StructuredGrid(size=mrti_data.shape[0:3],
                                      origin=origin,
                                      spacing=torch.tensor([1.0, 1.0, 1.0]),
                                      tensor=torch.tensor(mrti_data).permute(
                                          3, 0, 1, 2),
                                      channels=mrti_data.shape[-1])

    log_ctd_map = core.StructuredGrid(
        size=mrti_data.shape[0:3],
        origin=origin,
        spacing=torch.tensor([1.0, 1.0, 1.0]),
        tensor=torch.tensor(ctd_map).unsqueeze(0),
        channels=1)

    io.SaveITKFile(thermal_vol, f'{out_path}/{rabbit}_thermal_vol.nii.gz')
    io.SaveITKFile(log_ctd_map, f'{out_path}/{rabbit}_log_ctd_map.nii.gz')
    print('done')
Example #17
0
def generate_label_volume(rabbit, block):
    data_dir = f'/hdscratch/ucair/{rabbit}/blockface/{block}/'

    tif_files = sorted(glob.glob(f'{data_dir}volumes/raw/labels_tif/*'))

    hdr = read_mhd_header(f'{data_dir}volumes/raw/difference_volume.mhd')
    hdr['ElementDataFile'] = hdr['ElementDataFile'].replace(
        'difference', 'segmentation')
    hdr['ElementNumberOfChannels'] = 1

    # Load each of the tif images and then dump it into the label dir
    for tif_file in tif_files:
        tif_name = tif_file.split('/')[-1].split('.')[0]

        if os.path.exists(
                f'{data_dir}volumes/raw/segmentation/{tif_name}.mhd'):
            continue

        tif = io.LoadITKFile(tif_file)

        io.SaveITKFile(tif,
                       f'{data_dir}volumes/raw/segmentation/{tif_name}.mhd')

    write_mhd_header(f'{data_dir}volumes/raw/segmentation_volume.mhd', hdr)
def get_mr_slice(mr_file, blockface, slice_num, sample_device='cpu'):

    orig_device = blockface.device

    mr_data = io.LoadITKFile(mr_file, device=sample_device)
    blockface.to_(sample_device)
    mr_resamp = so.ResampleWorld.Create(blockface, device=sample_device)(mr_data)
    mr_slice = mr_resamp.extract_slice(slice_num - 1, dim=0)

    mr_slice.to_(orig_device)
    blockface.to_(orig_device)

    del mr_data, mr_resamp
    torch.cuda.empty_cache()

    return mr_slice
Example #19
0
def sort_and_label(in_dir, rabbit):

    out_base_dir = f'/hdscratch/ucair/{rabbit}/microscopic/'

    files = sorted(glob.glob(in_dir + '*'))
    label_files = [x for x in files if 'label' in x]
    image_files = [x for x in files if 'label' not in x]

    for im in range(0, len(image_files)):
        label = io.LoadITKFile(label_files[im])
        plt.figure()
        plt.imshow(label.data.permute(1, 2, 0) / 255.0)
        plt.axis('off')
        plt.pause(1)

        block_num = input('Please input the block number [xx]: ')
        if block_num == 'skip':
            continue
        else:
            block_num = int(block_num)
        depth = int(input('Please input the depth of the section [xxx]: '))

        image_num = int(depth / 50.0) + 1

        out_image_dir = f'{out_base_dir}block{block_num:02d}/raw/'
        out_label_dir = f'{out_base_dir}block{block_num:02d}/raw_labels/'
        if not os.path.exists(out_image_dir):
            os.makedirs(out_image_dir)
            os.makedirs(out_label_dir)

        out_label = f'IMG_{image_num:03d}_histopathology_label.tif'
        out_image = f'IMG_{image_num:03d}_histopathology_image.tif'

        shutil.copy(label_files[im], f'{out_label_dir}{out_label}')

        if os.path.exists(f'{out_image_dir}{out_image}'):
            pass
        else:
            shutil.copy(image_files[im], f'{out_image_dir}{out_image}')
        plt.close('all')
Example #20
0
def block_stacking(rabbit):

    rabbit_dir = f'/hdscratch2/{rabbit}/blockface/'
    raw_ext = '/surfaces/raw/'
    rigid_ext = '/surfaces/rigid/'
    deform_ext = '/surfaces/deformable/'
    vol_ext = '/volumes/raw/'
    stitch_ext = '/surfaces/raw/stitching/deformable/'

    # Get a list of the blocks
    block_list = sorted(glob.glob(f'{rabbit_dir}block*'))

    # for block_path in block_list:
    #     block = block_path.split('/')[-1]
    #     with open(f'{rabbit_dir}{block}{raw_ext}{block}_deformable_config.yaml', 'r') as f:
    #         params = yaml.load(f, Loader=yaml.FullLoader)
    #     params['propagation_sigma'] = [8.0, 8.0, 3.0]
    #     params['currents_sigma'] = [3.0, 1.5]
    #     with open(f'{rabbit_dir}{block}{raw_ext}{block}_deformable_config.yaml', 'w') as f:
    #         yaml.dump(params, f)

    # Determine the middle block
    # middle_block = block_list[9]
    middle_block = block_list[5]
    foot_blocks = block_list[block_list.index(middle_block):]
    head_blocks = block_list[:block_list.index(middle_block) + 1][::-1]

    rerun = True
    rigid = False
    # skip_blocks = ['block01', 'block02', 'block03', 'block04', 'block05', 'block06', 'block07', 'block08']

    skip_blocks = []

    # Go ahead and just delete any deformable surfaces to make sure that everything resets
    # for block_path in block_list:
    #     filelist = glob.glob(f'{block_path}/surfaces/deformable/*')
    #     for f in filelist:
    #         os.remove(f)

    if rerun or not os.path.exists(
            f'{middle_block}{vol_ext}{middle_block.split("/")[-1]}_phi_stacking.mhd'
    ):
        mid_block = middle_block.split('/')[-1]
        # middle = io.LoadITKFile(f'{middle_block}{vol_ext}difference_volume.mhd')
        middle = io.LoadITKFile(
            f'{middle_block}{vol_ext}difference_volume.nii.gz')
        # middle = io.LoadITKFile(f'{middle_block}{vol_ext}{mid_block}_volume.nrrd')
        middle.set_size((60, 1024, 1024))
        deformation = core.StructuredGrid.FromGrid(middle, channels=3)
        deformation.set_to_identity_lut_()
        io.SaveITKFile(
            deformation,
            f'{middle_block}{vol_ext}{middle_block.split("/")[-1]}_phi_inv_stacking.mhd'
        )
        io.SaveITKFile(
            deformation,
            f'{middle_block}{vol_ext}{middle_block.split("/")[-1]}_phi_stacking.mhd'
        )

        affine_tform = torch.eye(4)
        np.savetxt(
            f'{rabbit_dir}{mid_block}{raw_ext}{mid_block}_rigid_tform.txt',
            affine_tform.numpy())
        np.savetxt(
            f'{rabbit_dir}{mid_block}{vol_ext}{mid_block}_rigid_tform.txt',
            affine_tform.numpy())

        # Copy the files from raw to deformable for the middle surface
        # if os.path.exists(f'{rabbit_dir}{mid_block}{stitch_ext}'):
        #     mid_path = f'{mid_block}{stitch_ext}'
        # else:
        mid_path = f'{mid_block}{raw_ext}'

        files = [
            f'{rabbit_dir}{mid_path}{mid_block}_decimate.obj',
            f'{rabbit_dir}{mid_path}{mid_block}_ext.obj',
        ]
        if os.path.exists(f'{rabbit_dir}{mid_path}{mid_block}_foot.obj'):
            files += [f'{rabbit_dir}{mid_path}{mid_block}_foot.obj']
        if os.path.exists(f'{rabbit_dir}{mid_path}{mid_block}_head.obj'):
            files += [f'{rabbit_dir}{mid_path}{mid_block}_head.obj']
        if os.path.exists(
                f'{rabbit_dir}{mid_path}{mid_block}_foot_support.obj'):
            files += [f'{rabbit_dir}{mid_path}{mid_block}_foot_support.obj']
        if os.path.exists(
                f'{rabbit_dir}{mid_path}{mid_block}_head_support.obj'):
            files += [f'{rabbit_dir}{mid_path}{mid_block}_head_support.obj']

        out_names = []
        out_path = f'{rabbit_dir}{mid_block}{deform_ext}{mid_block}'
        for path in files:
            name = path.split('/')[-1].split(f'{mid_block}')[-1].replace(
                '.', '_deformable.')
            out_names += [f'{out_path}{name}']

        if not os.path.exists(out_path):
            os.makedirs(out_path)

        for in_file, out_file in zip(files, out_names):
            shutil.copy(in_file, out_file)

    # Loop over the foot blocks
    for i, block_path in enumerate(foot_blocks, 1):

        if i == len(foot_blocks):
            break

        target_block = block_path.split('/')[-1]
        source_block = foot_blocks[i].split('/')[-1]

        if source_block in skip_blocks:
            continue

        # if os.path.exists(f'{rabbit_dir}{source_block}{stitch_ext}'):
        #     mid_path = f'{source_block}{stitch_ext}'
        # else:
        mid_path = f'{source_block}{raw_ext}'

        target_surface_path = f'{rabbit_dir}{target_block}{deform_ext}{target_block}_foot_deformable.obj'
        source_surface_path = f'{rabbit_dir}{mid_path}{source_block}_head.obj'
        # if os.path.exists(f'{rabbit_dir}{mid_path}{source_block}_head_stitched.obj'):
        #     source_surface_path = f'{rabbit_dir}{source_block}{raw_ext}{source_block}_head_stitched.obj'

        extras_paths = [
            f'{rabbit_dir}{mid_path}{source_block}_decimate.obj',
            f'{rabbit_dir}{mid_path}{source_block}_ext.obj',
        ]

        if i < len(foot_blocks) - 1:
            extras_paths += [f'{rabbit_dir}{mid_path}{source_block}_foot.obj']

        if os.path.exists(
                f'{rabbit_dir}{mid_path}{source_block}_foot_support.obj'):
            extras_paths += [
                f'{rabbit_dir}{mid_path}{source_block}_foot_support.obj'
            ]

        if os.path.exists(
                f'{rabbit_dir}{source_block}{deform_ext}{source_block}_head_deformable.obj'
        ) and not rerun:
            print(
                f'The deformed surface for {source_block} already exists ... Next block'
            )
            continue

        try:
            verts, faces = io.ReadOBJ(target_surface_path)
            tar_surface = core.TriangleMesh(verts, faces)
            tar_surface.to_(device)
        except IOError:
            print(
                f'The deformed foot surface for {target_block} was not found ... Next block'
            )
            continue

        # Need to see if the target needs any support
        support_block = block_list[block_list.index(block_path) -
                                   1].split('/')[-1]
        if os.path.exists(
                f'{rabbit_dir}{support_block}{deform_ext}{support_block}_foot_support_deformable.obj'
        ):
            verts, faces = io.ReadOBJ(
                f'{rabbit_dir}{support_block}{deform_ext}{support_block}_foot_support_deformable.obj'
            )
            tar_surface.add_surface_(verts.to(device=device),
                                     faces.to(device=device))

        try:
            verts, faces = io.ReadOBJ(source_surface_path)
            src_surface = core.TriangleMesh(verts, faces)
            src_surface.to_(device)
            src_surface.flip_normals_()
        except IOError:
            print(
                f'The raw head surface for {source_block} was not found ... Next block'
            )
            continue

        extra_surfaces = []
        for path in extras_paths:
            try:
                verts, faces = io.ReadOBJ(path)
            except IOError:
                extra_name = path.split('/')[-1]
                print(
                    f'{extra_name} not found as an extra ... removing from list'
                )
                _ = extras_paths.pop(extras_paths.index(path))
                continue

            extra_surfaces += [core.TriangleMesh(verts, faces)]
            extra_surfaces[-1].to_(device)

        # Load or create the dictionary for registration
        try:
            if rerun:
                raise IOError
            with open(
                    f'{rabbit_dir}{source_block}{raw_ext}{source_block}_affine_config.yaml',
                    'r') as f:
                params = yaml.load(f, Loader=yaml.FullLoader)
        except IOError:
            params = {
                'spatial_sigma': [2.0, 0.5],
                'affine_lr': 1.0e-08,
                'translation_lr': 1.0e-05,
                'converge': 1.0,
                'rigid_transform': True
            }

        print(f'Registering {source_block} to {target_block}:')

        affine_tform = tools.affine_register(
            tar_surface.copy(),
            src_surface.copy(),
            spatial_sigma=params['spatial_sigma'],
            affine_lr=params['affine_lr'],
            translation_lr=params['translation_lr'],
            rigid=params['rigid_transform'],
            converge=params['converge'],
            device=device)

        # Apply the affine to the source element and the excess
        aff_tformer = uo.AffineTransformSurface.Create(affine_tform,
                                                       device=device)
        aff_src_surface = aff_tformer(src_surface)

        aff_extra_surface = []
        for surface in extra_surfaces:
            aff_extra_surface += [aff_tformer(surface)]

        out_path = f'{rabbit_dir}{source_block}{rigid_ext}{source_block}'
        if not os.path.exists(out_path):
            os.makedirs(out_path)
        for extra_path, extra_surface in zip(extras_paths, aff_extra_surface):
            name = extra_path.split('/')[-1].split(
                f'{source_block}')[-1].replace('.', '_rigid.')
            # if '_stitched' in name:
            #     name = name.replace('_stitched', '')
            if not os.path.exists(f'{out_path}{name}') or rerun:
                io.WriteOBJ(extra_surface.vertices, extra_surface.indices,
                            f'{out_path}{name}')

        if rigid:
            continue

        # Save out the parameters:
        with open(
                f'{rabbit_dir}{source_block}{raw_ext}{source_block}_affine_config.yaml',
                'w') as f:
            yaml.dump(params, f)

        # Save out all of the affine transformed surfaces and the transformation
        out_path = f'{rabbit_dir}{source_block}{rigid_ext}{source_block}'

        # Save the affine in the volumes and in the surfaces location
        np.savetxt(
            f'{rabbit_dir}{source_block}{raw_ext}{source_block}_rigid_tform.txt',
            affine_tform.numpy())
        np.savetxt(
            f'{rabbit_dir}{source_block}{vol_ext}{source_block}_rigid_tform.txt',
            affine_tform.numpy())

        if not os.path.exists(f'{out_path}_head_rigid.obj') or rerun:
            io.WriteOBJ(aff_src_surface.vertices, aff_src_surface.indices,
                        f'{out_path}_head_rigid.obj')

        for extra_path, extra_surface in zip(extras_paths, aff_extra_surface):
            name = extra_path.split('/')[-1].split(
                f'{source_block}')[-1].replace('.', '_rigid.')
            if not os.path.exists(f'{out_path}{name}') or rerun:
                io.WriteOBJ(extra_surface.vertices, extra_surface.indices,
                            f'{out_path}{name}')

        try:
            if rerun:
                raise IOError
            with open(
                    f'{rabbit_dir}{source_block}{raw_ext}{source_block}_deformable_config.yaml',
                    'r') as f:
                params = yaml.load(f, Loader=yaml.FullLoader)
        except IOError:
            params = {
                'currents_sigma': [3.0, 0.5],
                'propagation_sigma': [6.0, 6.0, 3.0],
                'deformable_lr': [1.0e-04, 0.5e-04],
                'converge': 1.0,
                'grid_size': [20, 100, 100],
                'niter': 500
            }
            # params = {
            #     'currents_sigma': [3.0, 1.5],
            #     'propagation_sigma': [6.0, 6.0, 3.0],
            #     'deformable_lr': [2.0e-04, 1.0e-04],
            #     'converge': 1.0,
            #     'grid_size': [20, 100, 100],
            #     'niter': 500
            # }

        # Account for some old parameter names - can be deleted later
        if 'spatial_sigma' in params.keys():
            params['currents_sigma'] = params['spatial_sigma']
            del params['spatial_sigma']
        if 'phi_inv_size' in params.keys():
            params['grid_size'] = params['phi_inv_size']
            del params['phi_inv_size']
        if 'rigid_transform' in params.keys():
            del params['rigid_transform']
        if 'smoothing_sigma' in params.keys():
            params['propagation_sigma'] = params['smoothing_sigma']
            del params['smoothing_sigma']
        if type(params['deformable_lr']) is not list:
            params['deformable_lr'] = [params['deformable_lr']] * len(
                params['spatial_sigma'])

        # Do the deformable registration
        def_surface, def_extras, phi, phi_inv = tools.deformable_register(
            tar_surface.copy(),
            aff_src_surface.copy(),
            currents_sigma=params['currents_sigma'],
            prop_sigma=params['propagation_sigma'],
            deformable_lr=params['deformable_lr'],
            converge=params['converge'],
            grid_size=params['grid_size'],
            src_excess=aff_extra_surface,
            accu_forward=True,
            accu_inverse=True,
            device=device,
            grid_device='cuda:1',
            iters=params['niter'])

        # Save out the parameters:
        with open(
                f'{rabbit_dir}{source_block}{raw_ext}{source_block}_deformable_config.yaml',
                'w') as f:
            yaml.dump(params, f)

        # Save out all of the deformable transformed surfaces and phi inv
        io.SaveITKFile(
            phi_inv,
            f'{rabbit_dir}{source_block}{vol_ext}{source_block}_phi_inv_stacking.mhd'
        )
        io.SaveITKFile(
            phi,
            f'{rabbit_dir}{source_block}{vol_ext}{source_block}_phi_stacking.mhd'
        )
        out_path = f'{rabbit_dir}{source_block}{deform_ext}{source_block}'
        if not os.path.exists(out_path):
            os.makedirs(out_path)
        if not os.path.exists(f'{out_path}_head_deformable.obj') or rerun:
            io.WriteOBJ(def_surface.vertices, def_surface.indices,
                        f'{out_path}_head_deformable.obj')

        for extra_path, extra_surface in zip(extras_paths, def_extras):
            name = extra_path.split('/')[-1].split(
                f'{source_block}')[-1].replace('.', '_deformable.')
            # if '_stitched' in name:
            #     name = name.replace('_stitched', '')
            if not os.path.exists(f'{out_path}{name}') or rerun:
                io.WriteOBJ(extra_surface.vertices, extra_surface.indices,
                            f'{out_path}{name}')

    print('Done registering foots blocks to middle block.')

    # Loop over the head blocks
    for i, block_path in enumerate(head_blocks, 1):

        if i == len(head_blocks):
            break

        target_block = block_path.split('/')[-1]
        source_block = head_blocks[i].split('/')[-1]

        if source_block in skip_blocks:
            continue

        if os.path.exists(f'{rabbit_dir}{source_block}{stitch_ext}'):
            mid_path = f'{source_block}{stitch_ext}'
        else:
            mid_path = f'{source_block}{raw_ext}'

        target_surface_path = f'{rabbit_dir}{target_block}{deform_ext}{target_block}_head_deformable.obj'
        source_surface_path = f'{rabbit_dir}{mid_path}{source_block}_foot.obj'
        if os.path.exists(
                f'{rabbit_dir}{mid_path}{source_block}_foot_stitched.obj'):
            source_surface_path = f'{rabbit_dir}{mid_path}{source_block}_foot_stitched.obj'

        extras_paths = [
            f'{rabbit_dir}{mid_path}{source_block}_decimate.obj',
            f'{rabbit_dir}{mid_path}{source_block}_ext.obj'
        ]

        if i < len(head_blocks) - 1:
            extras_paths += [f'{rabbit_dir}{mid_path}{source_block}_head.obj']

        if os.path.exists(
                f'{rabbit_dir}{mid_path}{source_block}_head_support.obj'):
            extras_paths += [
                f'{rabbit_dir}{mid_path}{source_block}_head_support.obj'
            ]

        if os.path.exists(
                f'{rabbit_dir}{source_block}{deform_ext}{source_block}_foot_deformable.obj'
        ) and not rerun:
            print(
                f'The deformed surface for {source_block} already exists ... Next block'
            )
            continue

        try:
            verts, faces = io.ReadOBJ(target_surface_path)
            tar_surface = core.TriangleMesh(verts, faces)
            tar_surface.to_(device)
        except IOError:
            print(
                f'The deformed foot surface for {target_block} was not found ... Next block'
            )
            continue

        # Need to see if the target needs any support
        support_block = block_list[block_list.index(block_path) +
                                   1].split('/')[-1]
        if os.path.exists(
                f'{rabbit_dir}{support_block}{deform_ext}{support_block}_head_support_deformable.obj'
        ):
            verts, faces = io.ReadOBJ(
                f'{rabbit_dir}{support_block}{deform_ext}{support_block}_head_support_deformable.obj'
            )
            tar_surface.add_surface_(verts.to(device=device),
                                     faces.to(device=device))

        try:
            verts, faces = io.ReadOBJ(source_surface_path)
            src_surface = core.TriangleMesh(verts, faces)
            src_surface.to_(device)
            src_surface.flip_normals_()
        except IOError:
            print(
                f'The raw foot surface for {source_block} was not found ... Next block'
            )
            continue

        extra_surfaces = []
        for path in extras_paths:
            try:
                verts, faces = io.ReadOBJ(path)
            except IOError:
                extra_name = path.split('/')[-1]
                print(
                    f'{extra_name} not found as an extra ... removing from list'
                )
                _ = extras_paths.pop(extras_paths.index(path))
                continue

            extra_surfaces += [core.TriangleMesh(verts, faces)]
            extra_surfaces[-1].to_(device)

        # Load or create the dictionary for registration
        try:
            if rerun:
                raise IOError
            with open(
                    f'{rabbit_dir}{source_block}{raw_ext}{source_block}_affine_config.yaml',
                    'r') as f:
                params = yaml.load(f, Loader=yaml.FullLoader)
        except IOError:
            params = {
                'spatial_sigma': [2.0, 0.5],
                'affine_lr': 1.0e-08,
                'translation_lr': 1.0e-05,
                'converge': 1.0,
                'rigid_transform': True
            }

        print(f'Registering {source_block} to {target_block}:')

        affine_tform = tools.affine_register(
            tar_surface.copy(),
            src_surface.copy(),
            spatial_sigma=params['spatial_sigma'],
            affine_lr=params['affine_lr'],
            translation_lr=params['translation_lr'],
            rigid=params['rigid_transform'],
            converge=params['converge'],
            device=device)

        # Apply the affine to the source element and the excess
        aff_tformer = uo.AffineTransformSurface.Create(affine_tform,
                                                       device=device)
        aff_src_surface = aff_tformer(src_surface)

        aff_extra_surface = []
        for surface in extra_surfaces:
            aff_extra_surface += [aff_tformer(surface)]

        out_path = f'{rabbit_dir}{source_block}{rigid_ext}{source_block}'
        if not os.path.exists(out_path):
            os.makedirs(out_path)
        for extra_path, extra_surface in zip(extras_paths, aff_extra_surface):
            name = extra_path.split('/')[-1].split(
                f'{source_block}')[-1].replace('.', '_rigid.')
            if '_stitched' in name:
                name = name.replace('_stitched', '')
            if not os.path.exists(f'{out_path}{name}') or rerun:
                io.WriteOBJ(extra_surface.vertices, extra_surface.indices,
                            f'{out_path}{name}')

        if rigid:
            continue

        # Save out the parameters:
        with open(
                f'{rabbit_dir}{source_block}{raw_ext}{source_block}_affine_config.yaml',
                'w') as f:
            yaml.dump(params, f)

        # Save out all of the affine transformed surfaces and the transformation
        out_path = f'{rabbit_dir}{source_block}{rigid_ext}{source_block}'

        # Save the affine in the volumes and in the surfaces location
        np.savetxt(
            f'{rabbit_dir}{source_block}{raw_ext}{source_block}_rigid_tform.txt',
            affine_tform.numpy())
        np.savetxt(
            f'{rabbit_dir}{source_block}{vol_ext}{source_block}_rigid_tform.txt',
            affine_tform.numpy())

        if not os.path.exists(f'{out_path}_foot_rigid.obj') or rerun:
            io.WriteOBJ(aff_src_surface.vertices, aff_src_surface.indices,
                        f'{out_path}_foot_rigid.obj')

        for extra_path, extra_surface in zip(extras_paths, aff_extra_surface):
            name = extra_path.split('/')[-1].split(
                f'{source_block}')[-1].replace('.', '_rigid.')
            if not os.path.exists(f'{out_path}{name}') or rerun:
                io.WriteOBJ(extra_surface.vertices, extra_surface.indices,
                            f'{out_path}{name}')

        try:
            if rerun:
                raise IOError
            with open(
                    f'{rabbit_dir}{source_block}{raw_ext}{source_block}_deformable_config.yaml',
                    'r') as f:
                params = yaml.load(f, Loader=yaml.FullLoader)
        except IOError:
            params = {
                'currents_sigma': [3.0, 0.5],
                'propagation_sigma': [6.0, 6.0, 3.0],
                'deformable_lr': [1.0e-04, 0.5e-04],
                'converge': 1.0,
                'grid_size': [20, 100, 100],
                'niter': 500
            }

        # if 'spatial_sigma' in params.keys():
        #     params['currents_sigma'] = params['spatial_sigma']
        #     del params['spatial_sigma']
        # if 'phi_inv_size' in params.keys():
        #     params['grid_size'] = params['phi_inv_size']
        #     del params['phi_inv_size']
        # if 'rigid_transform' in params.keys():
        #     del params['rigid_transform']
        # if 'smoothing_sigma' in params.keys():
        #     params['propagation_sigma'] = params['smoothing_sigma']
        #     del params['smoothing_sigma']
        #
        # if type(params['deformable_lr']) is not list:
        #     params['deformable_lr'] = [params['deformable_lr']] * len(params['spatial_sigma'])

        # Do the deformable registration
        def_surface, def_extras, phi, phi_inv = tools.deformable_register(
            tar_surface.copy(),
            aff_src_surface.copy(),
            currents_sigma=params['currents_sigma'],
            prop_sigma=params['propagation_sigma'],
            deformable_lr=params['deformable_lr'],
            converge=params['converge'],
            grid_size=params['grid_size'],
            src_excess=aff_extra_surface,
            accu_forward=True,
            accu_inverse=True,
            device=device,
            grid_device='cuda:1',
            iters=params['niter'])

        # Save out the parameters:
        with open(
                f'{rabbit_dir}{source_block}{raw_ext}{source_block}_deformable_config.yaml',
                'w') as f:
            yaml.dump(params, f)

        # Save out all of the deformable transformed surfaces and phi inv
        io.SaveITKFile(
            phi_inv,
            f'{rabbit_dir}{source_block}{vol_ext}{source_block}_phi_inv_stacking.mhd'
        )
        io.SaveITKFile(
            phi,
            f'{rabbit_dir}{source_block}{vol_ext}{source_block}_phi_stacking.mhd'
        )
        out_path = f'{rabbit_dir}{source_block}{deform_ext}{source_block}'
        if not os.path.exists(out_path):
            os.makedirs(out_path)
        if not os.path.exists(f'{out_path}_foot_deformable.obj') or rerun:
            io.WriteOBJ(def_surface.vertices, def_surface.indices,
                        f'{out_path}_foot_deformable.obj')

        for extra_path, extra_surface in zip(extras_paths, def_extras):
            name = extra_path.split('/')[-1].split(
                f'{source_block}')[-1].replace('.', '_deformable.')
            # if '_stitched' in name:
            #     name = name.replace('_stitched', '')
            if not os.path.exists(f'{out_path}{name}') or rerun:
                io.WriteOBJ(extra_surface.vertices, extra_surface.indices,
                            f'{out_path}{name}')

    print('Done registering head blocks to middle block.')
Example #21
0
def process_mic(rabbit):

    raw_mic_dir = f'/hdscratch/ucair/{rabbit}/microscopic/'
    bf_dir = f'/hdscratch/ucair/{rabbit}/blockface/'
    raw_bf_dir = f'/hdscratch/ucair/blockface/{rabbit}/'

    block_list = sorted(glob.glob(f'{raw_mic_dir}/*'))

    # for block_path in block_list:
    #     block = block_path.split('/')[-1]
    #
    #     mic_list = sorted(glob.glob(f'{block_path}/raw/*_image.tif'))
    #
    #     img_nums = [x.split('/')[-1].split('_')[1] for x in mic_list]
    #
    #     # Load the image
    #     for img in img_nums:
    #         print(f'Processing {block}, {img} ... ', end='')
    #         mic_file = f'{raw_mic_dir}{block}/hdf5/{block}_img{img}_image.hdf5'
    #
    #         mic = io.LoadITKFile(f'{raw_mic_dir}{block}/raw/IMG_{img}_histopathology_image.tif')
    #
    #         with h5py.File(mic_file, 'w') as f:
    #             g = f.create_group('RawImage')
    #             g.create_dataset('ImageData', data=mic.data.numpy())
    #
    #         print('Done')

    for block_path in block_list:
        block = block_path.split('/')[-1]

        mic_list = sorted(glob.glob(f'{block_path}/raw/*_image.tif'))

        img_nums = [x.split('/')[-1].split('_')[1] for x in mic_list]

        for img in img_nums:

            mic_file = f'{raw_mic_dir}{block}/hdf5/{block}_img{img}_image.hdf5'
            mic_seg = f'{raw_mic_dir}{block}/hdf5/{block}_img{img}_label.hdf5'
            blockface_image = f'{bf_dir}{block}/volumes/raw/difference/IMG_{img}_difference.mhd'
            blockface_label = f'{bf_dir}{block}/volumes/raw/segmentation/IMG_{img}_segmentation.mhd'

            meta_dict = {}
            with h5py.File(mic_file, 'r') as f:
                for key in f['RawImage'].attrs:
                    meta_dict[key] = f['RawImage'].attrs[key]

            if 'Affine' in meta_dict.keys():
                continue

            blockface = io.LoadITKFile(blockface_image, device=device)
            label_data = io.LoadITKFile(blockface_label, device=device)

            blockface = (blockface - blockface.min()) / (blockface.max() -
                                                         blockface.min())
            label = blockface.clone()
            label.data = label_data.data.clone()

            print(f'Affine Registering ... ')
            aff_mic, aff_mic_seg, affine = tools.process_mic(mic_file,
                                                             mic_seg,
                                                             blockface,
                                                             label,
                                                             device=device)
            print(f'Done')

            aff_mic *= aff_mic_seg
            blockface *= label

            blockface_s = core.StructuredGrid.FromGrid(
                blockface, tensor=blockface[0].unsqueeze(0), channels=1)
            aff_mic = (aff_mic - aff_mic.min()) / (aff_mic.max() -
                                                   aff_mic.min())

            print(f'Deformable Registering Labels ... ')
            def_label, label_deformation = match_bf_mic(aff_mic_seg,
                                                        label,
                                                        steps=[0.01, 0.005],
                                                        scales=[4, 1],
                                                        gauss=True)
            print(f'Done')

            label_def_mic = so.ApplyGrid(label_deformation,
                                         device=device)(aff_mic,
                                                        label_deformation)

            print(f'Deformable Registering Images ... ')
            def_image, image_deformation = match_bf_mic(
                label_def_mic,
                blockface_s,
                steps=[0.01, 0.01],
                scales=[2, 1],
            )
            print(f'Done')

            composer = so.ComposeGrids(device=device,
                                       dtype=torch.float32,
                                       padding_mode='border')
            deformation = composer([image_deformation, label_deformation])

            def_mic = so.ApplyGrid(deformation, device=device)(aff_mic,
                                                               deformation)

            try:
                with h5py.File(mic_file, 'r') as f:
                    mic = f['ImageData'][:]
            except KeyError:
                with h5py.File(mic_file, 'r') as f:
                    mic = f['RawImage/ImageData'][:]

            mic = core.StructuredGrid(mic.shape[1:],
                                      tensor=torch.tensor(mic,
                                                          dtype=torch.float32,
                                                          device=device),
                                      device=device,
                                      dtype=torch.float32,
                                      channels=3)

            print('Saving ... ')

            with h5py.File(mic_file, 'w') as f:
                g = f.create_group('RawImage')
                d = f.create_group('Deformation')
                g.create_dataset('ImageData', data=mic.data.cpu().numpy())
                d.create_dataset('Phi', data=deformation.data.cpu().numpy())
                g.attrs['Shape'] = list(mic.shape())
                g.attrs['Spacing'] = mic.spacing.tolist()
                g.attrs['Origin'] = mic.origin.tolist()
                g.attrs['Affine'] = affine.tolist()
                d.attrs['Shape'] = list(deformation.shape())
                d.attrs['Spacing'] = deformation.spacing.tolist()
                d.attrs['Origin'] = deformation.origin.tolist()

            io.SaveITKFile(
                def_mic,
                f'{raw_mic_dir}{block}/volume/images/IMG_{img}_def_histopathology.mhd'
            )

            print('Done')

            plt.close('all')

    print('All Done')
Example #22
0
def stitch_surfaces(rabbit):

    rabbit_dir = f'/hdscratch/ucair/{rabbit}/blockface/'
    raw_ext = '/surfaces/raw/'
    vol_ext = '/volumes/raw/'

    # Get a list of the blocks
    block_list = sorted(glob.glob(f'{rabbit_dir}block*'))

    # complete = ['block08']
    complete = ['block06', 'block09']

    for i, block_path in enumerate(block_list):

        block = block_path.split('/')[-1]
        stitching_dir = f'{rabbit_dir}{block}{raw_ext}/stitching/'

        if block in complete:
            continue

        if not os.path.exists(stitching_dir):
            print(f'No stitching surfaces found for {block}.')
            continue

        target_surface_path = f'{stitching_dir}/raw/{block}_target_faces.obj'
        source_surface_path = f'{stitching_dir}/raw/{block}_source_faces.obj'

        # Load the target surface
        try:
            verts, faces = io.ReadOBJ(target_surface_path)
            tar_surface = core.TriangleMesh(verts, faces)
            tar_surface.to_(device)
        except IOError:
            print(
                f'The target stitching surface for {block} was not found ... skipping'
            )
            continue

        try:
            verts, faces = io.ReadOBJ(source_surface_path)
            src_surface = core.TriangleMesh(verts, faces)
            src_surface.to_(device)
            src_surface.flip_normals_()
        except IOError:
            print(
                f'The source stitching surface for {block} was not found ... skipping'
            )
            continue

        # Need to load the exterior to drag along
        try:
            verts, faces = io.ReadOBJ(
                f'{rabbit_dir}/{block}/{raw_ext}/{block}_decimate.obj')
            surface_ext = core.TriangleMesh(verts, faces)
            surface_ext.to_(device)
        except IOError:
            print(
                f'The source stitching surface for {block} was not found ... skipping'
            )
            continue

        # Determine the surface half way between the source and the target
        try:
            with open(
                    f'{stitching_dir}/raw/{block}_middle_surface_config.yaml',
                    'r') as f:
                params = yaml.load(f, Loader=yaml.FullLoader)
        except IOError:
            params = {
                'currents_sigma': [5.0, 0.25, 0.05],
                'propagation_sigma': [1.0, 1.0, 1.0],
                'deformable_lr': [0.0008, 0.01, 0.01],
                'converge': 0.05,
                'mid_offset': 0.5
            }

        # Do the deformable registration
        def_src_surface, def_ext = tools.deformable_register(
            tar_surface.copy(),
            src_surface.copy(),
            src_excess=None,
            deformable_lr=params['deformable_lr'],
            currents_sigma=params['currents_sigma'],
            prop_sigma=params['propagation_sigma'],
            grid_size=None,
            converge=params['converge'],
            accu_forward=False,
            accu_inverse=False,
            device=device,
        )

        new_verts = src_surface.vertices.clone() + (
            (def_src_surface.vertices - src_surface.vertices) *
            params['mid_offset'])
        mid_surface = src_surface.copy()
        mid_surface.vertices = new_verts.clone()
        mid_surface.calc_normals()
        mid_surface.calc_centers()

        io.WriteOBJ(
            def_src_surface.vertices, def_src_surface.indices,
            f'{stitching_dir}/deformable_pieces/{block}_source_faces.obj')
        io.WriteOBJ(
            mid_surface.vertices, mid_surface.indices,
            f'{stitching_dir}/deformable_pieces/{block}_source_middle.obj')

        with open(f'{stitching_dir}/raw/{block}_middle_surface_config.yaml',
                  'w') as f:
            yaml.dump(params, f)

        # Load the binary volume for the block
        mask = io.LoadITKFile(
            f'{rabbit_dir}/{block}/{vol_ext}/segmentation_volume.mhd',
            device='cuda:0')

        # Load the other surfaces to drag along
        extras_paths = [
            f'{rabbit_dir}{block}{raw_ext}{block}_decimate.obj',
            f'{rabbit_dir}{block}{raw_ext}{block}_ext.obj'
        ]

        if os.path.exists(f'{rabbit_dir}{block}{raw_ext}{block}_head.obj'):
            extras_paths += [f'{rabbit_dir}{block}{raw_ext}{block}_head.obj']

        if os.path.exists(f'{rabbit_dir}{block}{raw_ext}{block}_foot.obj'):
            extras_paths += [f'{rabbit_dir}{block}{raw_ext}{block}_foot.obj']

        if os.path.exists(
                f'{rabbit_dir}{block}{raw_ext}{block}_head_support.obj'):
            extras_paths += [
                f'{rabbit_dir}{block}{raw_ext}{block}_head_support.obj'
            ]

        if os.path.exists(
                f'{rabbit_dir}{block}{raw_ext}{block}_foot_support.obj'):
            extras_paths += [
                f'{rabbit_dir}{block}{raw_ext}{block}_foot_support.obj'
            ]

        extra_surfaces = []
        for path in extras_paths:
            try:
                verts, faces = io.ReadOBJ(path)
            except IOError:
                extra_name = path.split('/')[-1]
                print(
                    f'{extra_name} not found as an extra ... removing from list'
                )
                _ = extras_paths.pop(extras_paths.index(path))
                continue

            extra_surfaces += [core.TriangleMesh(verts, faces)]
            extra_surfaces[-1].to_(device)

        # Define the diffusion parameters for the registration
        try:
            with open(f'{stitching_dir}/raw/{block}_diffusion_config.yaml',
                      'r') as f:
                diff_params = yaml.load(f, Loader=yaml.FullLoader)
        except IOError:
            diff_params = {
                'z_diff_c': 5.0,
                'y_diff_c': 200.0,
                'x_diff_c': 30.0,
                'background_c': 0.5,
                'niter': 10000,
                'gamma': 0.0005,
                'propegation_sigma': [0.2, 0.2, 0.2],
                'grad_amp': 300.0
            }

        try:
            with open(
                    f'{stitching_dir}/raw/{block}_stitch_surface_config.yaml',
                    'r') as f:
                params = yaml.load(f, Loader=yaml.FullLoader)
        except IOError:
            params = {
                'currents_sigma': [2.0, 1.0],
                'smoothing_sigma': [2.0, 2.0, 2.0],
                'deformable_lr': [0.0001, 0.001],
                'grid_size': [40, 256, 256],
                'converge': 0.05,
                'grid_device': 'cpu',
                'niters': 25
            }

        # Do the deformable registration with the source to the mid
        def_src_surface, def_tar_surface, def_extra_surfaces, phi, phi_inv = deformable_register(
            tar_surface.copy(),
            src_surface.copy(),
            mid_surface.copy(),
            src_excess=extra_surfaces,
            deformable_lr=params['deformable_lr'],
            currents_sigma=params['currents_sigma'],
            prop_sigma=params['smoothing_sigma'],
            grid_size=params['grid_size'],
            converge=params['converge'],
            accu_forward=True,
            accu_inverse=True,
            grid_device=params['grid_device'],
            device=device,
            mask=mask,
            diff_params=diff_params,
            iters=params['niters'])

        with open(f'{stitching_dir}/raw/{block}_stitch_surface_config.yaml',
                  'w') as f:
            yaml.dump(params, f)

        with open(f'{stitching_dir}/raw/{block}_diffusion_config.yaml',
                  'w') as f:
            yaml.dump(diff_params, f)

        io.WriteOBJ(
            def_src_surface.vertices, def_src_surface.indices,
            f'{stitching_dir}/deformable/{block}_whole_stitched_decimate.obj')

        io.SaveITKFile(phi,
                       f'{stitching_dir}/deformable/{block}_stitch_phi.mhd')
        io.SaveITKFile(
            phi_inv, f'{stitching_dir}/deformable/{block}_stitch_phi_inv.mhd')

        out_path = f'{stitching_dir}/deformable/'
        for extra_path, extra_surface in zip(extras_paths, def_extra_surfaces):
            name = extra_path.split('/')[-1]
            io.WriteOBJ(extra_surface.vertices, extra_surface.indices,
                        f'{out_path}{name}')

        vol = io.LoadITKFile(
            '/hdscratch/ucair/18_047/blockface/block08/volumes/raw/difference_volume.mhd',
            device='cuda:0')

        # phi_inv.set_size((60, 1024, 1024))
        # phi.set_size((60, 1024, 1024))
        # resampled_stitched = so.ApplyGrid.Create(phi_inv, device='cuda:0')(vol, phi_inv)
        # resampled_unstitched = so.ApplyGrid.Create(phi, device='cuda:0')(resampled_stitched, phi)
        # io.SaveITKFile(resampled_stitched, '/home/sci/blakez/stitched_block08.mhd')
        # io.SaveITKFile(resampled_unstitched, '/home/sci/blakez/unstitched_block08.mhd')

        print(f'Done stitching {block} ... ')
Example #23
0
def register_histopathology_to_blockface(rabbit, block, img_num, bf_slice):

    blockface_dir = f'/hdscratch/ucair/{rabbit}/blockface/{block}/'
    histology_dir = f'/hdscratch/ucair/{rabbit}/microscopic/{block}/'
    out_dir = f'{histology_dir}deformations/'

    if not os.path.exists(out_dir):
        os.makedirs(out_dir)

    # if os.path.exists(f'{out_dir}/img_{img_num}_deformation_to_blockface.mhd'):
    #     return

    # Load and make the histopathology segmentation
    segs = []
    segs += [
        io.LoadITKFile(
            f'{histology_dir}segmentations/IMG_{img_num}/img_{img_num}_healthy_tissue.nrrd',
            device=device)
    ]
    if os.path.exists(
            f'{histology_dir}segmentations/IMG_{img_num}/img_{img_num}_ablated_region.nrrd'
    ):
        segs += [
            io.LoadITKFile(
                f'{histology_dir}segmentations/IMG_{img_num}/img_{img_num}_ablated_region.nrrd',
                device=device)
        ]
    if os.path.exists(
            f'{histology_dir}segmentations/IMG_{img_num}/img_{img_num}_uncertain_region.nrrd'
    ):
        segs += [
            io.LoadITKFile(
                f'{histology_dir}segmentations/IMG_{img_num}/img_{img_num}_uncertain_region.nrrd',
                device=device)
        ]

    histology_seg = core.StructuredGrid.FromGrid(segs[0], channels=1)
    for seg in segs:
        histology_seg += seg

    try:
        blockface_seg = io.LoadITKFile(
            f'{blockface_dir}volumes/raw/hd_labels/{block}_hdlabel_volume.nrrd',
            device=device)
    except:
        blockface_seg = io.LoadITKFile(
            f'{blockface_dir}volumes/raw/segmentation_volume.nrrd',
            device=device)

    # # Load the surface slice and get the difference
    # blockface_surf = io.LoadITKFile(f'{blockface_dir}volumes/raw/surface/IMG_{bf_slice:03d}_surface.mhd',
    #                                device=device)
    #
    # blockface_surf_p1 = io.LoadITKFile(f'{blockface_dir}volumes/raw/surface/IMG_{bf_slice + 1:03d}_surface.mhd',
    #                                    device=device)
    #
    # diff = (blockface_surf - blockface_surf_p1).data[2]
    #
    # diff = (diff - diff.min()) / (diff.max() - diff.min())

    # Extract the slice
    blockface_seg = blockface_seg.extract_slice(bf_slice - 1, dim=0)

    aff_seg, affine = solve_affine(histology_seg,
                                   blockface_seg,
                                   img_num,
                                   out_dir=out_dir,
                                   device=device)
    np.savetxt(f'{out_dir}/img_{img_num}_affine_to_blockface.txt',
               affine.cpu().numpy())

    #### Apply the affine to the image
    mic_file = f'{histology_dir}hdf5/{block}_img{img_num}_image.hdf5'

    meta_dict = {}
    with h5py.File(mic_file, 'r') as f:
        mic = f['RawImage/ImageData'][:, ::10, ::10]
        for key in f['RawImage'].attrs:
            meta_dict[key] = f['RawImage'].attrs[key]

    mic = core.StructuredGrid(mic.shape[1:],
                              tensor=torch.tensor(mic,
                                                  dtype=torch.float32,
                                                  device=device),
                              spacing=torch.tensor([10.0, 10.0],
                                                   dtype=torch.float32,
                                                   device=device),
                              origin=histology_seg.origin,
                              device=device,
                              dtype=torch.float32,
                              channels=3)

    mic = (mic - mic.min()) / (mic.max() - mic.min())
    aff_mic = so.AffineTransform.Create(affine=affine)(mic, blockface_seg)
    # plt.figure()
    # plt.imshow(aff_mic.data.permute(1,2,0).cpu())
    # plt.axis('off')
    # plt.gca().invert_yaxis()
    # plt.savefig(f'/home/sci/blakez/ucair/Animations/Scrolls/Mic/Images/{blockface_slice}_image.png', dpi=500, bbox_inches='tight', pad_inches=0)

    def_histology, deformation = deformable_histology_to_blockface(
        aff_seg,
        blockface_seg,
        steps=[0.01, 0.005],
        scales=[4, 1],
        gauss=True,
        mic=aff_mic)

    # Save out the deformation
    io.SaveITKFile(deformation,
                   f'{out_dir}/img_{img_num}_deformation_to_blockface.mhd')
Example #24
0
def draw_contours(rabbit):

    raw_mic_dir = f'/hdscratch/ucair/{rabbit}/microscopic/'
    block_list = sorted(glob.glob(f'{raw_mic_dir}/*'))

    for block_path in block_list:
        block = block_path.split('/')[-1]
        mic_list = glob.glob(f'{block_path}/raw/*_image.tif')
        mic_list += glob.glob(f'{block_path}/raw/*_image.jpg')
        mic_list = sorted(mic_list)
        img_nums = [x.split('/')[-1].split('_')[1] for x in mic_list]

        for img in img_nums:

            mic_file = f'{raw_mic_dir}{block}/segmentations/IMG_{img}/img_{img}_color.nii.gz'
            healthy_file = f'{raw_mic_dir}{block}/segmentations/IMG_{img}/img_{img}_healthy_tissue.nrrd'
            uncertain_file = f'{raw_mic_dir}{block}/segmentations/IMG_{img}/img_{img}_uncertain_region.nrrd'
            ablation_file = f'{raw_mic_dir}{block}/segmentations/IMG_{img}/img_{img}_ablated_region.nrrd'

            # meta_dict = {}
            # with h5py.File(mic_file, 'r') as f:
            #     mic = f['RawImage/ImageData'][:, ::10, ::10]
            #     for key in f['RawImage'].attrs:
            #         meta_dict[key] = f['RawImage'].attrs[key]

            # mic = core.StructuredGrid(
            #     mic.shape[1:],
            #     tensor=torch.tensor(mic, dtype=torch.float32, device=device),
            #     spacing=torch.tensor([10.0, 10.0], dtype=torch.float32, device=device),
            #     device=device,
            #     dtype=torch.float32,
            #     channels=3
            # )
            save = True
            contour_width = 1.0
            mic = io.LoadITKFile(mic_file, device=device)
            parts = [io.LoadITKFile(healthy_file, device=device)]
            if os.path.exists(uncertain_file):
                parts += [io.LoadITKFile(uncertain_file, device=device)]
            if os.path.exists(ablation_file):
                parts += [io.LoadITKFile(ablation_file, device=device)]

            # mic = (mic - mic.min()) / (mic.max() - mic.min())
            # labels = seg.slic(mic.data.cpu().permute(1, 2, 0).double().numpy(), 4, multichannel=True)

            part_contours = []
            for p in parts:
                part_contours += [measure.find_contours(p.data.squeeze().cpu().numpy(), 0.5)]

            plt.figure()
            plt.imshow(mic.data.permute(1, 2, 0).cpu())
            for contour in part_contours[0]:
                plt.plot(contour[:, 1], contour[:, 0], color='orange', linestyle='dashed', linewidth=contour_width)
            try:
                for contour in part_contours[1]:
                    plt.plot(contour[:, 1], contour[:, 0], 'b-.', linewidth=contour_width)
            except IndexError:
                pass

            try:
                for contour in part_contours[2]:
                    plt.plot(contour[:, 1], contour[:, 0], 'r:', linewidth=1.5)
            except IndexError:
                pass

            plt.axis('off')
            plt.show()
            plt.pause(1.0)

            out_path = f'{raw_mic_dir}{block}/segmentations/IMG_{img}/'
            if save:
                plt.savefig(f'{out_path}img_{img}_region_outlines.png', dpi=600, bbox_inches='tight', pad_inches=0)

            plt.figure()
            plt.imshow(mic.data.permute(1, 2, 0).cpu())
            plt.axis('off')

            if save:
                plt.savefig(f'{out_path}img_{img}_original.png', dpi=600, bbox_inches='tight', pad_inches=0)

            plt.close('all')
            print(f'Done with {block}: {img}')
def exvivo_to_stacked_blocks(rabbit, block, direction, affine_only=False, base_dir='/hdscratch/ucair/'):

    # This is registered from blocks to exvivo, so phi is needed to bring the exvivo MR image to the block images
    # Need to determine the grid to sample the MR onto
    # rabbit_dir = f'/hdscratch/ucair/{rabbit}/blockface/'
    block_dir = f'{base_dir}{rabbit}/blockface/{block}/'
    exvivo_dir = f'{base_dir}{rabbit}/mri/exvivo/'
    # block_list = sorted(glob.glob(f'{rabbit_dir}block*'))
    # orig_dir = f'/home/sci/blakez/ucair/{rabbit}/rawVolumes/ExVivo_2018-07-26/'

    # Load the affine
    # try:
    #     aff = np.loadtxt(f'{exvivo_dir}/surfaces/raw/blocks_to_exvivo_affine.txt')
    #     aff = torch.tensor(aff, device=device, dtype=torch.float32)
    # except IOError:
    aff = np.loadtxt(os.path.normpath(f'{block_dir}../recons/surfaces/raw/blocks_to_exvivo_affine.txt'))
    aff = torch.tensor(aff, device=device, dtype=torch.float32)

    # if affine_only:
    #     if direction == 'phi':
    #         return aff.inverse()
    #     else:
    #         return aff

    # Load the deformation
    # try:
    #     deformation = io.LoadITKFile(
    #         f'{exvivo_dir}/volumes/raw/blocks_{direction}_to_exvivo.mhd', device=device
    #     )
    #     deformation.set_size((256, 256, 256))
    # except RuntimeError:
    deformation = io.LoadITKFile(
        os.path.normpath(f'{block_dir}../recons/surfaces/raw/blocks_{direction}_to_exvivo.mhd'), device=device
    )
    deformation.set_size((256, 256, 256))

    if affine_only:
        deformation.set_to_identity_lut_()

    if direction == 'phi':

        spacing = []
        origin = []
        size = []

        # if 'block07' in block_path:
        #     hdr = tools.read_mhd_header(f'{block_path}/volumes/raw/difference_volume.mhd')
        # else:
        hdr = tools.read_mhd_header(f'{block_dir}/volumes/raw/{block}_phi_inv_stacking.mhd')
        spacing.append(np.array([float(x) for x in hdr['ElementSpacing'].split(' ')]))
        origin.append(np.array([float(x) for x in hdr['Offset'].split(' ')]))
        size.append(np.array([float(x) for x in hdr['DimSize'].split(' ')]))

        spacing = np.stack(spacing)
        origin = np.stack(origin)
        size = np.stack(size)

        extent = size * spacing + origin
        aff_grid_size = np.array((512, 512, 512))
        aff_grid_origin = np.min(origin, axis=0)
        aff_grid_spacing = (np.max(extent, axis=0) - aff_grid_origin) / aff_grid_size

        aff_grid = core.StructuredGrid(
            size=aff_grid_size.tolist()[::-1],
            spacing=aff_grid_spacing.tolist()[::-1],
            origin=aff_grid_origin.tolist()[::-1],
            device=device,
            channels=3
        )

        aff_grid.set_size(size=(512, 512, 512), inplace=True)
        aff_grid.set_to_identity_lut_()

        # Apply the FORWARD affine to the deformation
        a = aff[0:3, 0:3].float()
        t = aff[-0:3, 3].float()

        # Create a deformation from the affine that lives in the stacked blocks space
        aff_grid.data = aff_grid.data.flip(0)
        aff_grid.data = torch.matmul(a, aff_grid.data.permute(list(range(1, 3 + 1)) + [0]).unsqueeze(-1))
        aff_grid.data = (aff_grid.data.squeeze() + t).permute([-1] + list(range(0, 3)))
        aff_grid.data = aff_grid.data.flip(0)

        # Compose the grids
        exvivo_to_blocks = so.ComposeGrids.Create(device=device)([aff_grid, deformation])

    else:

        deformation.data = deformation.data.flip(0)

        # Apply the inverse affine to the grid
        aff = aff.inverse()
        a = aff[0:3, 0:3].float()
        t = aff[-0:3, 3].float()

        deformation.data = torch.matmul(a.unsqueeze(0).unsqueeze(0),
                                        deformation.data.permute(list(range(1, 3 + 1)) + [0]).unsqueeze(-1))
        deformation.data = (deformation.data.squeeze() + t).permute([-1] + list(range(0, 3)))

        # Flip phi_inv back to the way it was
        deformation.data = deformation.data.flip(0)

        exvivo_to_blocks = deformation.copy()

    return exvivo_to_blocks
def mr_to_exvivo(rabbit, block, direction, affine_only=False, base_dir='/hdscratch/ucair/'):

    invivo_dir = f'{base_dir}{rabbit}/mri/invivo/'
    exvivo_dir = f'{base_dir}{rabbit}/mri/exvivo/'

    # Load the affine
    aff = np.loadtxt(f'{exvivo_dir}surfaces/raw/exvivo_to_invivo_affine.txt')
    aff = torch.tensor(aff, device=device, dtype=torch.float32)

    # if affine_only:
    #     if direction == 'phi':
    #         return aff.inverse()
    #     else:
    #         return aff

    # Load the deformation
    deformation = io.LoadITKFile(
        f'{exvivo_dir}volumes/raw/exvivo_to_invivo_{direction}.mhd', device=device
    )
    deformation.set_size((256, 256, 256))

    if affine_only:
        deformation.set_to_identity_lut_()

    if direction == 'phi':
        output_grid = io.LoadITKFile(f'{exvivo_dir}volumes/raw/reference_volume.nii.gz', device=device)
        aff_grid = core.StructuredGrid.FromGrid(output_grid, channels=3)
        del output_grid
        torch.cuda.empty_cache()
        aff_grid.set_size((256, 256, 256), inplace=True)
        aff_grid.set_to_identity_lut_()

        # Apply the FORWARD affine to the deformation
        a = aff[0:3, 0:3].float()
        t = aff[-0:3, 3].float()

        # Create a deformation from the affine that lives in the stacked blocks space
        aff_grid.data = aff_grid.data.flip(0)
        aff_grid.data = torch.matmul(a, aff_grid.data.permute(list(range(1, 3 + 1)) + [0]).unsqueeze(-1))
        aff_grid.data = (aff_grid.data.squeeze() + t).permute([-1] + list(range(0, 3)))
        aff_grid.data = aff_grid.data.flip(0)

        invivo_exvivo = so.ComposeGrids.Create(device=device)([aff_grid, deformation])

    else:

        deformation.data = deformation.data.flip(0)

        # Apply the inverse affine to the grid
        aff = aff.inverse()
        a = aff[0:3, 0:3].float()
        t = aff[-0:3, 3].float()

        deformation.data = torch.matmul(a.unsqueeze(0).unsqueeze(0),
                                        deformation.data.permute(list(range(1, 3 + 1)) + [0]).unsqueeze(-1))
        deformation.data = (deformation.data.squeeze() + t).permute([-1] + list(range(0, 3)))

        # Flip phi_inv back to the way it was
        deformation.data = deformation.data.flip(0)

        invivo_exvivo = deformation.copy()

    return invivo_exvivo
def stacked_blocks_to_block(rabbit, block, direction, affine_only=False, base_dir='/hdscratch/ucair/'):

    block_dir = f'{base_dir}{rabbit}/blockface/{block}/'

    # Load the affine
    aff = np.loadtxt(os.path.normpath(f'{block_dir}/surfaces/raw/{block}_rigid_tform.txt'))
    aff = torch.tensor(aff, device=device, dtype=torch.float32)

    # if affine_only:
    #     if direction == 'phi':
    #         return aff.inverse()
    #     else:
    #         return aff

    # Load the deformabale transformation
    deformation = io.LoadITKFile(
        f'{block_dir}/volumes/raw/{block}_{direction}_stacking.mhd', device=device
    )
    deformation.set_size((60, 1024, 1024))

    if affine_only:
        deformation.set_to_identity_lut_()

    if direction == 'phi':
        # Need to determine the output grid
        output_grid = io.LoadITKFile(f'{block_dir}/volumes/raw/difference_volume.mhd', device=device)
        aff_grid = core.StructuredGrid.FromGrid(output_grid, channels=3)
        del output_grid
        torch.cuda.empty_cache()
        aff_grid.set_size((60, 1024, 1024), inplace=True)
        aff_grid.set_to_identity_lut_()

        # Apply the FORWARD affine to the deformation
        a = aff[0:3, 0:3].float()
        t = aff[-0:3, 3].float()

        # Create a deformation from the affine that lives in the stacked blocks space
        aff_grid.data = aff_grid.data.flip(0)
        aff_grid.data = torch.matmul(a, aff_grid.data.permute(list(range(1, 3 + 1)) + [0]).unsqueeze(-1))
        aff_grid.data = (aff_grid.data.squeeze() + t).permute([-1] + list(range(0, 3)))
        aff_grid.data = aff_grid.data.flip(0)

        # Compose the grids
        stackblocks_to_block = so.ComposeGrids.Create(device=device)([aff_grid, deformation])

    else:

        deformation.data = deformation.data.flip(0)

        # Apply the inverse affine to the grid
        aff = aff.inverse()
        a = aff[0:3, 0:3].float()
        t = aff[-0:3, 3].float()

        deformation.data = torch.matmul(a.unsqueeze(0).unsqueeze(0),
                                        deformation.data.permute(list(range(1, 3 + 1)) + [0]).unsqueeze(-1))
        deformation.data = (deformation.data.squeeze() + t).permute([-1] + list(range(0, 3)))

        # Flip phi_inv back to the way it was
        deformation.data = deformation.data.flip(0)

        stackblocks_to_block = deformation.copy()

    return stackblocks_to_block
Example #28
0
def exvivo_to_blocks(stacked_blocks_dir):

    # This is registered from blocks to exvivo, so phi is needed to bring the exvivo MR image to the block images
    # Need to determine the grid to sample the MR onto
    rabbit_dir = f'/hdscratch/ucair/{rabbit}/blockface/'
    block_list = sorted(glob.glob(f'{rabbit_dir}block*'))
    orig_dir = f'/home/sci/blakez/ucair/{rabbit}/rawVolumes/ExVivo_2018-07-26/'
    spacing = []
    origin = []
    size = []
    for block_path in block_list:

        if 'block07' in block_path:
            hdr = tools.read_mhd_header(f'{block_path}/volumes/raw/difference_volume.mhd')
        else:
            hdr = tools.read_mhd_header(f'{block_path}/volumes/deformable/difference_volume_deformable.mhd')
        spacing.append(np.array([float(x) for x in hdr['ElementSpacing'].split(' ')]))
        origin.append(np.array([float(x) for x in hdr['Offset'].split(' ')]))
        size.append(np.array([float(x) for x in hdr['DimSize'].split(' ')]))
    spacing = np.stack(spacing)
    origin = np.stack(origin)
    size = np.stack(size)

    extent = size * spacing + origin
    aff_grid_size = np.array((512, 512, 512))
    aff_grid_origin = np.min(origin, axis=0)
    aff_grid_spacing = (np.max(extent, axis=0) - aff_grid_origin) / aff_grid_size

    aff_grid = core.StructuredGrid(
        size=aff_grid_size.tolist()[::-1],
        spacing=aff_grid_spacing.tolist()[::-1],
        origin=aff_grid_origin.tolist()[::-1],
        device=device,
        channels=3
    )

    aff_grid.set_size(size=(512, 512, 512), inplace=True)
    aff_grid.set_to_identity_lut_()

    # Load the affine
    aff = np.loadtxt(f'{orig_dir}blocks_to_exvivo_affine.txt')
    aff = torch.tensor(aff, device=device, dtype=torch.float32)

    # Apply the FORWARD affine to the deformation
    # aff = aff.inverse()
    a = aff[0:3, 0:3].float()
    t = aff[-0:3, 3].float()

    # Create a deformation from the affine that lives in the stacked blocks space

    aff_grid.data = aff_grid.data.flip(0)

    aff_grid.data = torch.matmul(a, aff_grid.data.permute(list(range(1, 3 + 1)) + [0]).unsqueeze(-1))
    aff_grid.data = (aff_grid.data.squeeze() + t).permute([-1] + list(range(0, 3)))

    aff_grid.data = aff_grid.data.flip(0)

    # Load the defromabale transformation
    phi = io.LoadITKFile(
        f'{orig_dir}blocks_phi_to_exvivo.mhd', device=device
    )
    phi.set_size((256, 256, 256))

    # Compose the grids
    deformation = so.ComposeGrids.Create(device=device)([aff_grid, phi])

    return deformation
Example #29
0
def mr_to_block(block_path, rabbit):

    day0_dir = f'/hdscratch/ucair/{rabbit}/mri/day0/'
    day3_dir = f'/hdscratch/ucair/{rabbit}/mri/invivo/'
    stacked_blocks_dir = f'/hdscratch/ucair/{rabbit}/blockface/recons/'
    block = block_path.split('/')[-1]
    # exvivo_out = f'/hdscratch/ucair/18_047/mri/exvivo/volumes/deformable/{block}/'
    invivo_out = f'/hdscratch/ucair/18_062/mri/day0/volumes/deformable/{block}/'
    if not os.path.exists(invivo_out):
        os.makedirs(invivo_out)

    deformations = []

    # # Get the transformation from day0 to day3
    # day0_to_day3 = get_day0_to_day3(day0_dir)
    # deformations.append(day0_to_day3)

    in_path = f'/hdscratch/ucair/{rabbit}/'

    # Need to load and deform the day 0 NPV volume
    day0_files = sorted(glob.glob(f'/scratch/rabbit_data/{rabbit}/rawVolumes/Ablation*/*'))
    # day3_files = sorted(glob.glob(f'{in_path}/mri/invivo/volumes/raw/*'))

    # hist_file = f'{in_path}/microscopic/recons/all_ablation_segs_to_invivo.nrrd'
    # if not os.path.exists(hist_file):
    #     hist_file = f'{in_path}/microscopic/recons/all_ablation_segs_to_invivo.mhd'
    interday_file = sorted(glob.glob(f'{in_path}/mri/day0/volumes/raw/*'))
    log_ctd = '/hdscratch/ucair/AcuteBiomarker/Data/18_062/18_062_log_ctd_map.nii.gz'
    t1_nc_file = '/home/sci/blakez/ucair/longitudinal/18_062/Day0_non_contrast_VIBE.nii.gz'

    day0_npv_file = [x for x in day0_files if 'npv' in x or 'NPV' in x and '.nrrd' in x][0]
    day0_t1_file = [x for x in day0_files if '0.5x' in x][-1]
    # day3_npv_file = [x for x in day3_files if 'npv' in x or 'NPV' in x and '.nrrd' in x][0]
    interday = [x for x in interday_file if 'phi' in x and '.mhd' in x][0]

    day0_npv = io.LoadITKFile(day0_npv_file, device)
    day0_t1 = io.LoadITKFile(day0_t1_file, device)
    deform = io.LoadITKFile(interday, device)
    log_ctd = io.LoadITKFile(log_ctd, device)
    day0_nc_t1 = io.LoadITKFile(t1_nc_file, device)

    def_day0 = so.ApplyGrid.Create(deform, device=device)(day0_npv, deform)
    def_day0_t1 = so.ApplyGrid.Create(deform, device=device)(day0_t1, deform)
    def_log_ctd = so.ApplyGrid.Create(deform, device=device)(log_ctd, deform)
    def_nc_t1 = so.ApplyGrid.Create(deform, device=device)(day0_nc_t1, deform)

    to_block = gd.generate(rabbit, block=block, source_space='invivo', target_space='blockface')

    # Get the transformation with the affine included from invivo to exvivo
    # invivo_to_exvivo = mr_to_exvivo(day3_dir)
    # deformations.append(invivo_to_exvivo)

    # Get the transformation with the affine included from exvivo to the stacked blocks
    # exvivo_to_stacked = exvivo_to_blocks(stacked_blocks_dir)
    # deformations.append(exvivo_to_stacked)
    #
    # # Load the transformation from the stacked blocks to the block of interest
    # stacked_to_block = stacked_blocks_to_block(block_path)
    # deformations.append(stacked_to_block)

    # # Load the transformation for stitching if there is one
    # if os.path.exists(f'{block_path}/volumes/raw/{block}_phi_stitch.mhd'):
    #     block_stitching = block_stitch(block_path)
    #     deformations.append(block_stitching)

    # Load the Day3 MR file to be deformed
    # t2_motion = io.LoadITKFile(
    #     '/home/sci/blakez/ucair/18_047/rawVolumes/Ablation_2018-06-28/089_----_t2_spc_1mm_iso_cor_post20min.nii.gz',
    #     device=device
    # )
    #
    # ce_t1 = io.LoadITKFile(
    #     '/home/sci/blakez/ucair/18_047/rawVolumes/Ablation_2018-06-28/102_----_3D_VIBE_1mmIso_NoGrappa_1avg_fatsat_cor_00.nii.gz',
    #     device=device
    # )

    # npv = io.LoadITKFile(
    #     '/hdscratch/ucair/18_062/mri/invivo/volumes/raw/028_----_Day3_lr_NPV_Segmentation_062.nrrd',
    #     device=device
    # )

    # ctd = io.LoadITKFile(
    #     '/home/sci/blakez/ucair/18_047/rawVolumes/Ablation_2018-06-28/CTD_map.nrrd',
    #     device=device
    # )
    # ctd.data[ctd.data < 240] = 0.0
    # ctd.data[ctd.data > 0.0] = 1.0

    torch.cuda.empty_cache()

    # t2_to_block = so.ApplyGrid.Create(invivo_to_block, device=device, pad_mode='zeros')(t2_motion, invivo_to_block)
    # io.SaveITKFile(t2_to_block, f'{invivo_out}day0_t2_to_{block}.mhd')
    #
    # t1_to_block = so.ApplyGrid.Create(invivo_to_block, device=device, pad_mode='zeros')(ce_t1, invivo_to_block)
    # io.SaveITKFile(t1_to_block, f'{invivo_out}day0_ce_t1_to_{block}.mhd')

    npv_to_block = so.ApplyGrid.Create(to_block, device=device, pad_mode='zeros')(def_day0, to_block)
    io.SaveITKFile(npv_to_block, f'{invivo_out}day0_npv_to_{block}.mhd')

    t1_to_block = so.ApplyGrid.Create(to_block, device=device, pad_mode='zeros')(def_day0_t1, to_block)
    io.SaveITKFile(t1_to_block, f'{invivo_out}day0_t1_to_{block}.mhd')

    log_ctd_block = so.ApplyGrid.Create(to_block, device=device, pad_mode='zeros')(def_log_ctd, to_block)
    io.SaveITKFile(log_ctd_block, f'{invivo_out}day0_log_ctd_to_{block}.mhd')

    def_nc_t1 = so.ApplyGrid.Create(to_block, device=device, pad_mode='zeros')(def_nc_t1, to_block)
    io.SaveITKFile(def_nc_t1, f'{invivo_out}day0_t1_nc_to_{block}.mhd')

    # ctd_to_block = so.ApplyGrid.Create(invivo_to_block, device=device, pad_mode='zeros')(ctd, invivo_to_block)
    # io.SaveITKFile(ctd_to_block, f'{invivo_out}day0_ctd_to_{block}.mhd')

    print(f'Done with {block}')
def TPS(regObj, opt):
    import matplotlib
    matplotlib.use('qt5agg')
    import matplotlib.pyplot as plt
    plt.ion()
    # Load the points or ask where they are

    if not os.path.exists(f'{regObj.tps.outputPath}/tps_deformation.nii.gz'
                          ) or regObj.tps.rerun:

        regObj.tps.outputPath = regObj.rabbitDirectory + '/tpsVolumes/' + regObj.pipelinePhase
        if not os.path.exists(regObj.tps.outputPath):
            os.makedirs(regObj.tps.outputPath)

        try:
            src_points = rc.load_slicer_points(regObj.tps.sourcePointsDir)
            tar_points = rc.load_slicer_points(regObj.tps.targetPointsDir)
        except IOError:
            regObj.tps.sourcePointsDir = _getFilePath(
                'Source Points File ({0} TPS)'.format(regObj.pipelinePhase),
                initialdir=regObj.rabbitDirectory)
            regObj.tps.targetPointsDir = _getFilePath(
                'Target Points File ({0} TPS)'.format(regObj.pipelinePhase),
                initialdir=regObj.rabbitDirectory)
            src_points = rc.load_slicer_points(regObj.tps.sourcePointsDir)
            tar_points = rc.load_slicer_points(regObj.tps.targetPointsDir)

        try:
            source_image = io.LoadITKFile(regObj.tps.source_image, opt.device)
            target_image = io.LoadITKFile(regObj.tps.target_image, opt.device)
        except RuntimeError:
            regObj.tps.source_image = _getFilePath(
                'Source Image File (TPS)', initialdir=regObj.rabbitDirectory)
            regObj.tps.target_image = _getFilePath(
                'Target Image File (TPS)', initialdir=regObj.rabbitDirectory)
            source_image = io.LoadITKFile(regObj.tps.source_image, opt.device)
            target_image = io.LoadITKFile(regObj.tps.target_image, opt.device)

        rbf_filter = so.RadialBasis.Create(tar_points,
                                           src_points,
                                           sigma=1.0,
                                           device=opt.device)

        # Solve for the rigid transform for determining the grid to sample onto
        rigidMat = rc.SolveRigidAffine(np.array(src_points),
                                       np.array(tar_points))

        # Solve for the radial basis funtion deformation
        if regObj.tps.incompressible:
            rbf_source, rbf_grid = rbf_filter.filter_incompressible(
                in_grid=source_image,
                out_grid=target_image,
                t_step=10000,
                conv=0.8,
                step=0.03)
        else:
            rbf_source, rbf_grid = rbf_filter(in_grid=source_image,
                                              out_grid=target_image)

        io.SaveITKFile(rbf_grid,
                       f'{regObj.tps.outputPath}/tps_deformation.nii.gz')

    else:
        rbf_grid = io.LoadITKFile(
            f'{regObj.tps.outputPath}/tps_deformation.nii.gz',
            device=opt.device)

    # Check if there are rigid volumes, if not, get them from the source
    volumes = sorted(glob.glob(regObj.rigid.outputPath + '/*'))
    if volumes == []:
        volumes = regObj.sourceVolumes

    print('Applying TPS transformation to source volumes .... ', end='')
    sys.stdout.flush()

    for volume in volumes:
        # Tag the file with 't' to indicate it had thin plate splines applied
        fileName = volume.split('/')[-1]
        fileName = fileName[:6] + 't' + fileName[7:]
        outName = os.path.join(regObj.tps.outputPath, fileName)

        if not os.path.exists(outName) or regObj.tps.rerun:
            # Load the source image
            src_im = io.LoadITKFile(volume, device=opt.device)
            aff_im = rc.SolveAffineGrid(src_im, np.array(rigidMat))

            # Determine the subvol onto which the image needs to be resampled
            try:
                h_resample = so.ResampleWorld.Create(
                    aff_im, device=opt.device)(rbf_grid)
            except RuntimeError:
                h_resample = so.ResampleWorld.Create(
                    target_image, device=opt.device)(rbf_grid)

            # Apply and save
            if any(x in outName for x in ['MOCO', 'ADC', 't1_map']):
                def_im = so.ApplyGrid.Create(h_resample,
                                             device=opt.device,
                                             interp_mode='nearest')(src_im,
                                                                    h_resample)
            else:
                def_im = so.ApplyGrid.Create(h_resample,
                                             device=opt.device)(src_im,
                                                                h_resample)
            io.SaveITKFile(def_im, outName)

    print('Done')