Ejemplo n.º 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')
Ejemplo n.º 2
0
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')
Ejemplo n.º 3
0
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')
Ejemplo n.º 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')
Ejemplo n.º 5
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')
Ejemplo n.º 6
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')
Ejemplo n.º 7
0
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')
Ejemplo n.º 8
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')
Ejemplo n.º 9
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')
Ejemplo n.º 10
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)
Ejemplo n.º 11
0
def data_transfer(regObj, opt):
    rabbitNumber = regObj.rabbitDirectory.split('/')[-2]

    # Try to read the list that comes from transferring the data
    # If it isn't there, then assume we need to transfer the data
    try:
        dicomList = rc.ReadList(regObj.rabbitDirectory +
                                '/ConfigFiles/source_volume_list.txt')

    except IOError:

        # Use subprocess to get the list of files from RAID2
        p = sp.Popen([
            "ssh", "*****@*****.**",
            f"find {opt.raw_dir}*{opt.rabbit[-2:]}* -type d"
        ],
                     stdout=sp.PIPE)
        raidDirs, _ = p.communicate()

        # There is a new line at the end which puts an empty at the end of the list
        raidDirs = raidDirs.decode('utf-8').split('\n')[:-1]
        dicomList = []

    # Get a list of the already transferrred timepoints
    transfered = sorted(glob.glob(f'{regObj.rabbitDirectory}/rawVolumes/*'))

    # Get the names of the timepoints
    transfered = [x.split('/')[-1] for x in transfered]

    # If all of the timepoints have already been transferred then break
    if all([
            opt.transfer_timepoints[x] in transfered
            for x in range(len(opt.transfer_timepoints))
    ]):
        return

    for timepoint in opt.transfer_timepoints:
        # Use subprocess to get the list of files from RAID10
        p = sp.Popen([
            "ssh", "*****@*****.**",
            f"find {opt.raw_dir}*{opt.rabbit[-2:]}* -type d"
        ],
                     stdout=sp.PIPE)
        raidDirs, _ = p.communicate()

        # There is a new line at the end which puts an empty at the end of the list
        raidDirs = raidDirs.decode('utf-8').split('\n')[:-1]
        dicomList = []
        # Initialize an empty list
        tpList = []

        # Create a selector so the ablation volumes can be selected
        Selector = rc.PathSelector(tk, sorted(raidDirs),
                                   f'Choose {timepoint} Day Files to Convert')
        convertFiles = Selector.get_files()
        Selector.root.destroy()
        tpList += convertFiles
        dicomList += convertFiles

        for i, path in enumerate(tpList, 1):
            # Get the name of the file
            filename = path.split('s0')[-1].split(' ')[-1]

            # Correct the special characters in the path string so the scp command will work
            path = path.replace("^", "\^").replace(" ", "\ ")

            rawOutName = f'{regObj.rabbitDirectory}/rawDicoms/{timepoint}/{i:03d}_----_{filename}'
            volOutName = f'{regObj.rabbitDirectory}/rawVolumes/{timepoint}/{i:03d}_----_{filename}'

            rawOutName = rawOutName.replace('\\ ', '_').replace('\ ', '_')
            volOutName = volOutName.replace('\\ ', '_').replace('\ ', '_')

            # If the volume doesn't already exist, then copy it over
            if not os.path.exists(rawOutName):
                os.makedirs(rawOutName)
                p = sp.Popen([
                    "scp", "-r", f"[email protected]:{path}/*",
                    rawOutName
                ])
                os.waitpid(p.pid, 0)

            if len(glob.glob(rawOutName + '/*')) == 0:
                p = sp.Popen([
                    "scp", "-r", f"[email protected]:{path}/*",
                    rawOutName
                ])
                os.waitpid(p.pid, 0)

            if not os.path.exists(os.path.dirname(volOutName)):
                os.makedirs(os.path.dirname(volOutName))

            # Load the DICOM into a CAMP object
            # if not os.path.exists(volOutName + '.nii.gz') and not os.path.exists(volOutName + '_00.nii.gz'):
            rcsVolume = rc.LoadDICOM(rawOutName, opt.device)
            if type(rcsVolume) == list:
                for im in rcsVolume:
                    io.SaveITKFile(
                        im, volOutName + '_{0}.nii.gz'.format(
                            str(rcsVolume.index(im)).zfill(2)))
            else:
                io.SaveITKFile(rcsVolume, volOutName + '.nii.gz')

    # Write out the dicom list that was transferred and reconstructed
    rc.WriteList(
        dicomList,
        regObj.rabbitDirectory + '/ConfigFiles/source_volume_list.txt')

    # Check if temperature data exists and if not, transfer it
    if regObj.pipelinePhase == 'temperature':
        p = sp.Popen([
            "ssh", "*****@*****.**",
            "find /v/raid2/sjohnson/Data/2018_RabbitData/{0}/TemperatureRecon/ForRegistration_Current/ -type f"
            .format(rabbitNumber)
        ],
                     stdout=sp.PIPE)
        raidDirs, _ = p.communicate()
    else:
        raidDirs = []
Ejemplo n.º 12
0
def solve_affines(block_list):

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

        if not os.path.exists(f'{block_path}/volumes/raw/'):
            os.makedirs(f'{block_path}/volumes/raw/difference/')
            os.makedirs(f'{block_path}/volumes/raw/surface/')
            os.makedirs(f'{block_path}/volumes/raw/scatter/')

        # elif sorted(glob.glob(f'{block_path}/volumes/raw/difference/*')):
        #     print('alread filtered')
        #     continue

        image_list = sorted(glob.glob(f'{block_path}/images/filtered/*'))

        if not image_list:
            print(f'No filtered image files found for {block} ... skipping')
            continue

        print(f'Solving Affines for {block} ... ')
        spacing = list(
            map(float,
                input(f'X,Y Spacing for {block}: ').strip().split(' ')))
        # spacing = [0.0163, 0.0163]

        surface_list = [x for x in image_list if 'surface' in x]
        scatter_list = [x for x in image_list if 'scatter' in x]

        ImScatter = io.LoadITKFile(scatter_list[0], device=device)
        ImScatter.set_spacing_(spacing)
        ImScatter.set_origin_(-1 * (ImScatter.size * ImScatter.spacing) / 2)
        ImScatter /= ImScatter.max()

        # Load the surface image
        ImSurface = io.LoadITKFile(surface_list[0], device=device)
        ImSurface.set_spacing_(spacing)
        ImSurface.set_origin_(-1 * (ImSurface.size * ImSurface.spacing) / 2)
        ImSurface /= ImSurface.max()

        # Save out the first image
        difference = ImScatter - ImSurface

        ImDifference = core.StructuredGrid(
            ImSurface.shape()[1:],
            tensor=difference.data[2].unsqueeze(0),
            spacing=ImSurface.spacing,
            origin=ImSurface.origin,
            device=device,
            dtype=torch.float32,
            channels=1)

        io.SaveITKFile(
            ImScatter, f'{block_path}/volumes/raw/scatter/IMG_001_scatter.mhd')
        io.SaveITKFile(
            ImSurface, f'{block_path}/volumes/raw/surface/IMG_001_surface.mhd')
        io.SaveITKFile(
            ImDifference,
            f'{block_path}/volumes/raw/difference/IMG_001_difference.mhd')

        ImPrev = ImScatter.copy()

        Adict = {
            'origin': ImPrev.origin.tolist(),
            'spacing': ImPrev.spacing.tolist(),
            scatter_list.index(scatter_list[0]): np.eye(3).tolist()
        }

        maxIter = 1000

        for scat, surf in zip(scatter_list[1:], surface_list[1:]):
            print(f'Registering {scat.split("/")[-1]} .... ')
            sys.stdout.flush()
            image_num = scat.split('/')[-1].split('_')[1]

            # Get the number the file is from the start
            dist = scatter_list.index(scat)

            # Load the next image
            ImScatter = io.LoadITKFile(scat, device=device)
            ImScatter.set_spacing_(ImPrev.spacing)
            ImScatter.set_origin_(ImPrev.origin)
            ImScatter /= ImScatter.max()

            ImSurface = io.LoadITKFile(surf, device=device)
            ImSurface.set_spacing_(ImPrev.spacing)
            ImSurface.set_origin_(ImPrev.origin)
            ImSurface /= ImSurface.max()

            difference = ImScatter - ImSurface

            ImDifference = core.StructuredGrid(
                ImSurface.shape()[1:],
                tensor=difference.data[2].unsqueeze(0),
                spacing=ImSurface.spacing,
                origin=ImSurface.origin,
                device=device,
                dtype=torch.float32,
                channels=1)

            affine = affine_register(ImPrev.copy(),
                                     ImSurface.copy(),
                                     niter=maxIter,
                                     device=device)

            # Save out the images
            aff_filter = so.AffineTransform.Create(affine=affine,
                                                   device=device)
            aff_scatter = aff_filter(ImScatter)
            aff_surface = aff_filter(ImSurface)
            aff_difference = aff_filter(ImDifference)
            # difference = (difference - difference.min()) / (difference.max() - difference.min())

            io.SaveITKFile(
                aff_scatter,
                f'{block_path}/volumes/raw/scatter/IMG_{image_num}_scatter.mhd'
            )
            io.SaveITKFile(
                aff_surface,
                f'{block_path}/volumes/raw/surface/IMG_{image_num}_surface.mhd'
            )
            io.SaveITKFile(
                aff_difference,
                f'{block_path}/volumes/raw/difference/IMG_{image_num}_difference.mhd'
            )

            Adict[dist] = affine.detach().cpu().clone().tolist()
            ImPrev = aff_scatter.copy()

        with open(f'{block_path}/volumes/raw/{block}_affine_dictionary.yaml',
                  'w') as f:
            yaml.dump(Adict, f)

        _make_volumes(block_path)
Ejemplo n.º 13
0
def RigidMatch(regObj, opt):
    # Load the points or ask where they are
    try:
        src_points = rc.load_slicer_points(regObj.rigid.sourcePointsFile)
        tar_points = rc.load_slicer_points(regObj.rigid.targetPointsFile)
    except IOError:
        regObj.rigid.sourcePointsFile = _getFilePath(
            'Source Points File ({0} rigid)'.format(regObj.pipelinePhase),
            initialdir=regObj.rabbitDirectory)
        regObj.rigid.targetPointsFile = _getFilePath(
            'Target Points File ({0} rigid)'.format(regObj.pipelinePhase),
            initialdir=regObj.rabbitDirectory)
        src_points = rc.load_slicer_points(regObj.rigid.sourcePointsFile)
        tar_points = rc.load_slicer_points(regObj.rigid.targetPointsFile)

    # Use the points to find a rigid transformation
    rigidMat = rc.SolveRigidAffine(src_points, tar_points)
    # Change to a torch tensor to use with CAMP and inverse for camp
    rigidMat = torch.tensor(rigidMat, device=opt.device,
                            dtype=torch.float32).inverse()
    regObj.rigid.rigidMatrix = rigidMat.cpu().numpy().tolist()
    regObj.rigid.outputPath = regObj.rabbitDirectory + '/rigidVolumes/' + regObj.pipelinePhase

    # Create the output directory if it doesn't exist
    if not os.path.exists(regObj.rigid.outputPath):
        os.makedirs(regObj.rigid.outputPath)

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

    # If the pipeline phase is interday, need to check for motion corrected volumes
    if regObj.pipelinePhase == 'interday':
        # Do this in a try just in case there are no motion corrected files, then it will just skip
        try:
            # Glob the directory that would contain the motion corrected volumes
            motionList = sorted(
                glob.glob(regObj.rabbitDirectory +
                          '/elastVolumes/day3_motion/*.nii.gz'))
            motionList += sorted(
                glob.glob(regObj.rabbitDirectory +
                          '/elastVolumes/day3_motion/*.nrrd'))
            origNames = [
                x.split('/')[-1][:4] + '----' + x.split('/')[-1][8:]
                for x in motionList
            ]  # these names have to exist in the source files
            # Create a list of paths as these original names would appear
            sorcNames = [
                os.path.dirname(regObj.sourceVolumes[0]) + '/' + x
                for x in origNames
            ]
            regObj.sourceVolumes = sorted(
                list(set(regObj.sourceVolumes) - set(sorcNames)))

            # Add on the motion list to form the complete list of the source volumes
            regObj.sourceVolumes += motionList
        except IOError:
            pass

    for volume in regObj.sourceVolumes:
        # Tage the file with an 'r' to indicate rigid reg
        fileName = volume.split('/')[-1]
        fileName = fileName[:5] + 'r' + fileName[6:]
        outName = os.path.join(regObj.rigid.outputPath, fileName)

        if not os.path.exists(outName) or regObj.rigid.rerun:
            src_im = io.LoadITKFile(volume, opt.device)
            aff_im = rc.SolveAffineGrid(src_im,
                                        np.array(regObj.rigid.rigidMatrix))

            # Apply and save
            if any(x in outName for x in ['MOCO', 'ADC']):
                aff_im = so.AffineTransform.Create(affine=rigidMat,
                                                   device=opt.device,
                                                   interp_mode='nearest')(
                                                       src_im, aff_im)
            else:
                aff_im = so.AffineTransform.Create(affine=rigidMat,
                                                   device=opt.device)(src_im,
                                                                      aff_im)

            io.SaveITKFile(aff_im, outName)

    print('Done')
Ejemplo n.º 14
0
def def_block(rabbit, block):
    data_dir = f'/hdscratch/ucair/microscopic/{rabbit}/registered/{block}/'
    bf_dir = f'/hdscratch/ucair/{rabbit}/blockface/{block}/'
    vol_ext = '/volumes/raw/'
    raw_ext = '/surfaces/raw/'
    def_ext = '/volumes/deformable/'

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

    # Load phi_inv
    phi_inv = io.LoadITKFile(f'{bf_dir}{vol_ext}{block}_phi_inv.mhd',
                             device=device)
    phi_inv.set_size((60, 1024, 1024))
    #
    # # Phi_inv is in z,y,x and need x,y,z
    phi_inv.data = phi_inv.data.flip(0)

    # Load the volume to apply this field to
    mic = io.LoadITKFile(f'{data_dir}{block}_histopathology_affine_volume.mhd',
                         device=device)
    # seg = io.LoadITKFile(f'{data_dir}{vol_ext}segmentation_volume.mhd', device=device)

    # aff_grid = core.StructuredGrid.FromGrid(phi_inv, channels=3)
    # aff_grid.set_to_identity_lut_()
    # aff_grid.data = aff_grid.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()

    # 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([3] + list(range(0, 3)))
    #
    # aff_grid.data = aff_grid.data.flip(0)
    #
    # aff_bf = so.ApplyGrid.Create(aff_grid, device=aff_grid.device, dtype=aff_grid.dtype)(bf, out_grid=phi_inv)

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

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

    # try:
    #     stitch_files = sorted(glob.glob(f'{data_dir}{vol_ext}{block}_phi_inv_stitch_*.mhd'))
    #     stitch_list = []
    #     for stitch_file in stitch_files:
    #         phi_stitch = io.LoadITKFile(stitch_file, device=device)
    #         phi_stitch.set_size((60, 1024, 1024))
    #         stitch_list += [phi_stitch.clone()]
    #     composer = so.ComposeGrids.Create(padding_mode='border', device=device)
    #     final_phi = composer([phi_inv] + stitch_list)
    #     phi_inv = final_phi.clone()
    # except IOError:
    #     pass

    def_mic = so.ApplyGrid.Create(phi_inv, pad_mode='zeros',
                                  device=device)(mic, phi_inv)
    # def_seg = so.ApplyGrid.Create(phi_inv, pad_mode='zeros', device=device)(seg, phi_inv)

    # Save out the deformed volumes
    io.SaveITKFile(def_mic,
                   f'{data_dir}{block}_histopathology_volume_deformable.mhd')
Ejemplo n.º 15
0
def compose_blocks(rabbit):
    data_dir = f'/hdscratch/ucair/microscopic/{rabbit}/registered/'
    bf_dir = f'/hdscratch/ucair/{rabbit}/blockface/'
    old_dir = f'/home/sci/blakez/ucair/{rabbit}/rawVolumes/ExVivo*/'
    def_ext = '/volumes/deformable/'
    block_list = [
        x.split('/')[-1] for x in sorted(glob.glob(f'{bf_dir}/block*'))
    ]

    # Load the affine
    aff = np.loadtxt(glob.glob(f'{old_dir}blocks_to_exvivo_affine.txt')[0])
    aff = torch.tensor(aff, device=device, dtype=torch.float32)

    # Load the deformation
    phi_inv = io.LoadITKFile(glob.glob(f'{old_dir}block_phi_inv.mhd')[0],
                             device=device)
    phi_inv.set_size((512, 512, 512))

    phi_inv.data = phi_inv.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()

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

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

    bf_list = []
    label_list = []

    for block in block_list:

        print(f'Deforming {block} ... ', end='')
        # if block == block_list[len(block_list) // 2]:
        #     bf = io.LoadITKFile(f'{data_dir}{block}/volumes/raw/difference_volume.mhd', device=device)
        #     # lb = io.LoadITKFile(f'{data_dir}{block}/volumes/raw/segmentation_volume.mhd', device=device)

        mic = io.LoadITKFile(
            f'{data_dir}{block}/{block}_histopathology_volume_deformable.mhd',
            device=device)
        # lb = io.LoadITKFile(f'{data_dir}{block}{def_ext}segmentation_volume_deformable.mhd', device=device)
        def_bf = so.ApplyGrid.Create(phi_inv, pad_mode='zeros',
                                     device=device)(mic, phi_inv)
        # def_lb = so.ApplyGrid.Create(phi_inv, pad_mode='zeros', device=device)(lb, phi_inv)
        def_bf.to_(device='cpu')
        # def_lb.to_(device='cpu')
        bf_list.append(def_bf.clone())
        # label_list.append(def_lb.clone())
        print('Done')

    lb_tensor = torch.stack([x.data for x in label_list], dim=0)
    lb_tensor = (lb_tensor > 0.45).float()

    bf_tensor = torch.stack([x.data for x in bf_list], dim=0)
    bf_sum = bf_tensor.sum(0)
    lb_sum = lb_tensor.sum(0)

    lb_non_zero = lb_sum.clone()
    lb_non_zero[lb_non_zero == 0.0] = 1.0

    bf_sum_scaled = bf_sum / lb_non_zero

    bf_to_exvivo = bf_list[0].clone()
    bf_to_exvivo.data = bf_sum_scaled.data.clone()

    io.SaveITKFile(bf_to_exvivo, '/home/sci/blakez/TEST_STACKED.mhd')

    print('Done')
Ejemplo n.º 16
0
def corrections(rabbit_dir, block, corr_num):

    block_path = f'{rabbit_dir}{block}/'

    image_list = sorted(glob.glob(f'{block_path}/images/filtered/*'))

    with open(f'{block_path}/volumes/raw/{block}_affine_dictionary.yaml',
              'r') as f:
        Adict = yaml.load(f, Loader=yaml.FullLoader)

    surface_list = [x for x in image_list if 'surface' in x]
    scatter_list = [x for x in image_list if 'scatter' in x]

    # Load the surface image
    ImSurface_good = io.LoadITKFile(surface_list[corr_num - 1], device=device)
    ImSurface_good.set_spacing_(Adict['spacing'])
    ImSurface_good.set_origin_(
        -1 * (ImSurface_good.size * ImSurface_good.spacing) / 2)
    ImSurface_good /= 255.0

    ImSurface_bad = io.LoadITKFile(surface_list[corr_num], device=device)
    ImSurface_bad.set_spacing_(Adict['spacing'])
    ImSurface_bad.set_origin_(-1 *
                              (ImSurface_bad.size * ImSurface_bad.spacing) / 2)
    ImSurface_bad /= 255.0

    # Apply the affines to both of the images
    aff_filter = so.AffineTransform.Create(affine=torch.tensor(Adict[corr_num -
                                                                     1],
                                                               device=device),
                                           device=device)
    ImSurface_good = aff_filter(ImSurface_good)

    aff_filter = so.AffineTransform.Create(affine=torch.tensor(Adict[corr_num],
                                                               device=device),
                                           device=device)
    ImSurface_bad = aff_filter(ImSurface_bad)

    points = torch.tensor(tools.LandmarkPicker(
        [ImSurface_bad[0].squeeze().cpu(), ImSurface_good[0].squeeze().cpu()]),
                          dtype=torch.float32,
                          device=device).permute(1, 0, 2)

    # Change to real coordinates
    points *= torch.cat([
        ImSurface_good.spacing[None, None, :], ImSurface_good.spacing[None,
                                                                      None, :]
    ], 0)
    points += torch.cat([
        ImSurface_good.origin[None, None, :], ImSurface_good.origin[None,
                                                                    None, :]
    ], 0)

    aff_filter = so.AffineTransform.Create(points[1], points[0], device=device)

    corr_affine = torch.eye(3, device=device, dtype=torch.float32)
    corr_affine[0:2, 0:2] = aff_filter.affine
    corr_affine[0:2, 2] = aff_filter.translation

    ImPrev = ImSurface_good.copy()

    for scat, surf in zip(scatter_list[corr_num:], surface_list[corr_num:]):
        print(f'Registering {scat.split("/")[-1]} .... ')
        sys.stdout.flush()
        image_num = scat.split('/')[-1].split('_')[1]

        # Get the number the file is from the start
        dist = scatter_list.index(scat)

        # Load the next image
        ImScatter = io.LoadITKFile(scat, device=device)
        ImScatter.set_spacing_(ImPrev.spacing)
        ImScatter.set_origin_(ImPrev.origin)
        ImScatter /= 255.0

        ImSurface = io.LoadITKFile(surf, device=device)
        ImSurface.set_spacing_(ImPrev.spacing)
        ImSurface.set_origin_(ImPrev.origin)
        ImSurface /= 255.0

        difference = ImScatter - ImSurface

        ImDifference = core.StructuredGrid(
            ImSurface.shape()[1:],
            tensor=difference.data[2].unsqueeze(0),
            spacing=ImSurface.spacing,
            origin=ImSurface.origin,
            device=device,
            dtype=torch.float32,
            channels=1)

        affine = torch.mm(corr_affine, torch.tensor(Adict[dist],
                                                    device=device))

        # Save out the images
        aff_filter = so.AffineTransform.Create(affine=affine, device=device)
        aff_scatter = aff_filter(ImScatter)
        aff_surface = aff_filter(ImSurface)
        aff_difference = aff_filter(ImDifference)
        # difference = (difference - difference.min()) / (difference.max() - difference.min())

        io.SaveITKFile(
            aff_scatter,
            f'{block_path}/volumes/raw/scatter/IMG_{image_num}_scatter.mhd')
        io.SaveITKFile(
            aff_surface,
            f'{block_path}/volumes/raw/surface/IMG_{image_num}_surface.mhd')
        io.SaveITKFile(
            aff_difference,
            f'{block_path}/volumes/raw/difference/IMG_{image_num}_difference.mhd'
        )

        Adict[dist] = affine.detach().cpu().clone().tolist()
        ImPrev = aff_scatter.copy()

    with open(f'{block_path}/volumes/raw/{block}_affine_dictionary.yaml',
              'w') as f:
        yaml.dump(Adict, f)
Ejemplo n.º 17
0
def register(rabbit, base_dir='/hdscratch/ucair/'):
    source_path = f'{base_dir}{rabbit}/mri/exvivo/surfaces/raw/'
    target_path = f'{base_dir}{rabbit}/mri/invivo/surfaces/raw/'

    source_file = f'{source_path}exvivo_ablation_region_decimate.obj'
    target_file = f'{target_path}invivo_ablation_region_decimate.obj'

    verts, faces = io.ReadOBJ(target_file)
    invivo_surface = core.TriangleMesh(verts, faces)
    invivo_surface.to_(device=device)

    verts, faces = io.ReadOBJ(source_file)
    exvivo_surface = core.TriangleMesh(verts, faces)
    exvivo_surface.to_(device=device)

    print('Starting Affine ... ')
    # Load or create the dictionary for registration
    try:
        with open(f'{source_path}affine_config.yaml', 'r') as f:
            params = yaml.load(f, Loader=yaml.FullLoader)
    except IOError:
        params = {
            'spatial_sigma': [15.0],
            'affine_lr': 1.0e-07,
            'translation_lr': 1.0e-06,
            'converge': 4.0
        }

    try:
        aff = np.loadtxt(f'{source_path}exvivo_to_invivo_affine.txt')
        aff = torch.tensor(aff, device=device)
    except IOError:
        aff = affine(invivo_surface.copy(),
                     exvivo_surface.copy(),
                     affine_lr=params['affine_lr'],
                     translation_lr=params['translation_lr'],
                     converge=params['converge'],
                     spatial_sigma=params['spatial_sigma'],
                     device=device)
        # Save out the parameters:
        with open(f'{source_path}affine_config.yaml', 'w') as f:
            yaml.dump(params, f)
        np.savetxt(f'{source_path}exvivo_to_invivo_affine.txt',
                   aff.cpu().numpy())

    aff_tfrom = uo.AffineTransformSurface.Create(aff, device=device)
    aff_exvivo = aff_tfrom(exvivo_surface)

    if not os.path.exists(f'{source_path}../affine/'):
        os.makedirs(f'{source_path}../affine/')

    io.WriteOBJ(
        aff_exvivo.vertices, aff_exvivo.indices,
        f'{source_path}../affine/exvivo_to_invivo_{rabbit}_affine.obj')

    print('Starting Deformable ... ')
    try:
        with open(f'{source_path}/deformable_config.yaml', 'r') as f:
            params = yaml.load(f, Loader=yaml.FullLoader)
    except IOError:
        params = {
            'currents_sigma': [5.0, 1.0],
            'propagation_sigma': [8.0, 8.0, 8.0],
            'deformable_lr': [2.0e-04, 1.0e-04],
            'converge': 4.0,
            'phi_inv_size': [32, 32, 32],
            'n_iters': 500,
        }

    def_surface, _, phi, phi_inv = tools.deformable_register(
        invivo_surface.copy(),
        aff_exvivo.copy(),
        src_excess=None,
        deformable_lr=params['deformable_lr'],
        currents_sigma=params['currents_sigma'],
        prop_sigma=params['propagation_sigma'],
        converge=params['converge'],
        grid_size=params['phi_inv_size'],
        accu_forward=True,
        accu_inverse=True,
        device=device,
        grid_device='cuda:0',
        expansion_factor=1.5,
        iters=params['n_iters'])

    # Save out the parameters:
    with open(f'{source_path}deformable_config.yaml', 'w') as f:
        yaml.dump(params, f)

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

    io.SaveITKFile(
        phi_inv,
        f'{source_path}../../volumes/raw/exvivo_to_invivo_phi_inv.mhd')
    io.SaveITKFile(phi,
                   f'{source_path}../../volumes/raw/exvivo_to_invivo_phi.mhd')
    io.WriteOBJ(def_surface.vertices, def_surface.indices,
                f'{source_path}../deformable/exvivo_to_invivo_deformable.obj')
Ejemplo n.º 18
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} ... ')
Ejemplo n.º 19
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')
Ejemplo n.º 21
0
def generate_segmentation_volume(rabbit, block, base_dir='/hdscratch/ucair/'):
    blockface_dir = f'{base_dir}{rabbit}/blockface/{block}/'
    histology_dir = f'{base_dir}{rabbit}/microscopic/{block}/'
    def_dir = f'{histology_dir}deformations/'

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

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

    raw_images = glob.glob(f'{histology_dir}/raw/*_image.tif')
    if not raw_images:
        raw_images += sorted(raw_images +
                             glob.glob(f'{histology_dir}/raw/*_image.jpg'))
    image_nums = sorted(
        [int(x.split('/')[-1].split('_')[1]) for x in raw_images])

    deformed_ablation_segs = []
    deformed_combined_segs = []
    deformed_images = []

    for im in image_nums:

        print(f'Loading and deforming image {im} ... ', end='')

        # Load the healthy segmentation as a reference
        healthy = io.LoadITKFile(
            f'{histology_dir}segmentations/IMG_{im:03d}/img_{im:03d}_healthy_tissue.nrrd',
            device=device)
        # Load the affine
        aff = np.loadtxt(
            glob.glob(f'{def_dir}img_{im:03d}_affine_to_blockface.txt')[0])
        aff = torch.tensor(aff, device=device, dtype=torch.float32)

        # Load the deformation
        deformation_data = io.LoadITKFile(
            f'{def_dir}/img_{im:03d}_deformation_to_blockface.mhd',
            device=device)

        deformation = core.StructuredGrid(
            size=deformation_data.size[0:2],
            spacing=deformation_data.spacing[1:3],
            origin=deformation_data.origin[1:3],
            device=deformation_data.device,
            tensor=deformation_data.data.squeeze().permute(2, 0, 1),
            channels=2)

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

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

        try:
            ablation = io.LoadITKFile(
                f'{histology_dir}segmentations/IMG_{im:03d}/img_{im:03d}_ablated_region.nrrd',
                device=device)
        except RuntimeError:
            ablation = (healthy * 0.0).copy()

        try:
            transition = io.LoadITKFile(
                f'{histology_dir}segmentations/IMG_{im:03d}/img_{im:03d}_uncertain_region.nrrd',
                device=device)
        except RuntimeError:
            transition = (healthy * 0.0).copy()

        # Load the actual image
        #### Apply the affine to the image
        mic_file = f'{histology_dir}hdf5/{block}_img{im:03d}_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),
                                  device=device,
                                  dtype=torch.float32,
                                  channels=3)

        mic = (mic - mic.min()) / (mic.max() - mic.min())

        if not os.path.exists(
                f'{histology_dir}deformable/img_{im:03d}_to_blockface/'):
            os.makedirs(
                f'{histology_dir}deformable/img_{im:03d}_to_blockface/')

        def_mic = so.ApplyGrid.Create(deformation, device=device)(mic,
                                                                  deformation)

        # Need to put the mic image in the right slice
        z_or = (im - 1) * 0.05
        def_mic = core.StructuredGrid(
            [2] + list(def_mic.shape()[1:]),
            tensor=def_mic.data.unsqueeze(1).repeat(1, 2, 1, 1),
            spacing=torch.tensor(
                [0.05, def_mic.spacing[0], def_mic.spacing[1]],
                dtype=torch.float32,
                device=device),
            origin=torch.tensor([z_or, def_mic.origin[0], def_mic.origin[1]],
                                dtype=torch.float32,
                                device=device),
            device=device,
            dtype=torch.float32,
            channels=3)

        io.SaveITKFile(
            def_mic,
            f'{histology_dir}deformable/img_{im:03d}_to_blockface/img_{im:03d}_to_blockface.mhd'
        )

        combined = ablation + transition
        combined.data = (combined.data >= 0.5).float()

        def_ablation = so.ApplyGrid.Create(deformation,
                                           device=device)(ablation,
                                                          deformation)
        def_combined = so.ApplyGrid.Create(deformation,
                                           device=device)(combined,
                                                          deformation)

        deformed_ablation_segs.append(def_ablation.copy())
        deformed_combined_segs.append(def_combined.copy())
        deformed_images.append(def_mic.copy())

        del def_ablation, def_combined, def_mic, combined, mic, deformation
        torch.cuda.empty_cache()

        print('done')

    # Now need to load the blockface volume
    block_vol = io.LoadITKFile(
        f'{blockface_dir}volumes/raw/difference_volume.mhd', device='cpu')
    image_vol = core.StructuredGrid(size=block_vol.size,
                                    spacing=block_vol.spacing,
                                    origin=block_vol.origin,
                                    device=block_vol.device,
                                    channels=3)

    for ii, im in enumerate(image_nums):
        image_vol.data[:, im - 1] = deformed_images[ii].data[:,
                                                             0].clone().cpu()

    io.SaveITKFile(image_vol, f'{out_dir}/{block}_image_volume.mhd')
    del image_vol, deformed_images
    torch.cuda.empty_cache()

    single_vol = core.StructuredGrid(size=block_vol.size,
                                     spacing=block_vol.spacing,
                                     origin=block_vol.origin,
                                     device=block_vol.device,
                                     channels=1)

    for ii, im in enumerate(image_nums):
        single_vol.data[:, im -
                        1] = deformed_ablation_segs[ii].data[:].clone().cpu()

    io.SaveITKFile(single_vol,
                   f'{out_dir}/{block}_ablation_segmentation_no_interp.mhd')

    del single_vol
    torch.cuda.empty_cache()

    # Now need to load the blockface volume
    ablation_vol = core.StructuredGrid(size=block_vol.size,
                                       spacing=block_vol.spacing,
                                       origin=block_vol.origin,
                                       device=device,
                                       channels=1)

    for ii, im in enumerate(image_nums):

        if ii == len(image_nums) - 1:
            continue

        next_slice = image_nums[ii + 1]

        for s, slice in enumerate(range(im, next_slice + 1)):
            step = 1.0 / (next_slice - im)
            cur_alpha = 1.0 - (s * step)
            next_alpa = 0.0 + (s * step)

            ablation_vol.data[:, slice] = (
                deformed_ablation_segs[ii].data *
                cur_alpha) + (deformed_ablation_segs[ii + 1].data * next_alpa)

    gauus_ablation = so.Gaussian.Create(1,
                                        10, [0.1, 2, 2],
                                        dim=3,
                                        device=device)(ablation_vol)

    io.SaveITKFile(gauus_ablation,
                   f'{out_dir}/{block}_ablation_segmentation.mhd')
    del gauus_ablation, deformed_ablation_segs
    torch.cuda.empty_cache()

    combined_vol = core.StructuredGrid(size=block_vol.size,
                                       spacing=block_vol.spacing,
                                       origin=block_vol.origin,
                                       device=block_vol.device,
                                       channels=1)

    for ii, im in enumerate(image_nums):

        if ii == len(image_nums) - 1:
            continue

        next_slice = image_nums[ii + 1]

        for s, slice in enumerate(range(im, next_slice + 1)):
            step = 1.0 / (next_slice - im)
            cur_alpha = 1.0 - (s * step)
            next_alpa = 0.0 + (s * step)

            combined_vol.data[:, slice] = (
                deformed_combined_segs[ii].data *
                cur_alpha) + (deformed_combined_segs[ii + 1].data * next_alpa)

    # gauus_ablation = so.Gaussian.Create(1, 10, [0.1, 2, 2], dim=3, device=device)(ablation_vol)

    io.SaveITKFile(
        combined_vol,
        f'{out_dir}/{block}_ablation_and_transition_segmentation.mhd')

    del block_vol
    del combined_vol
    torch.cuda.empty_cache()
Ejemplo n.º 22
0
def generate_image_volume(rabbit, block, base_dir='/hdscratch/ucair/'):
    blockface_dir = f'{base_dir}{rabbit}/blockface/{block}/'
    histology_dir = f'{base_dir}{rabbit}/microscopic/{block}/'
    def_dir = f'{histology_dir}deformations/'

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

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

    raw_images = glob.glob(f'{histology_dir}/raw/*_image.tif')
    if not raw_images:
        raw_images += sorted(raw_images +
                             glob.glob(f'{histology_dir}/raw/*_image.jpg'))
    image_nums = sorted(
        [int(x.split('/')[-1].split('_')[1]) for x in raw_images])

    deformed_images = []

    for im in image_nums:

        print(f'Loading and deforming image {im} ... ', end='')

        # Load the healthy segmentation as a reference
        healthy = io.LoadITKFile(
            f'{histology_dir}segmentations/IMG_{im:03d}/img_{im:03d}_healthy_tissue.nrrd',
            device=device)
        try:
            ablation = io.LoadITKFile(
                f'{histology_dir}segmentations/IMG_{im:03d}/img_{im:03d}_ablated_region.nrrd',
                device=device)
        except RuntimeError:
            ablation = (healthy * 0.0).copy()

        try:
            transition = io.LoadITKFile(
                f'{histology_dir}segmentations/IMG_{im:03d}/img_{im:03d}_uncertain_region.nrrd',
                device=device)
        except RuntimeError:
            transition = (healthy * 0.0).copy()

        combined = ablation + transition + healthy
        combined.data = (combined.data >= 0.5).float()

        # Load the affine
        aff = np.loadtxt(
            glob.glob(f'{def_dir}img_{im:03d}_affine_to_blockface.txt')[0])
        aff = torch.tensor(aff, device=device, dtype=torch.float32)

        # Load the deformation
        deformation_data = io.LoadITKFile(
            f'{def_dir}/img_{im:03d}_deformation_to_blockface.mhd',
            device=device)

        deformation = core.StructuredGrid(
            size=deformation_data.size[0:2],
            spacing=deformation_data.spacing[1:3],
            origin=deformation_data.origin[1:3],
            device=deformation_data.device,
            tensor=deformation_data.data.squeeze().permute(2, 0, 1),
            channels=2)

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

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

        # Load the actual image
        #### Apply the affine to the image
        mic_file = f'{histology_dir}hdf5/{block}_img{im:03d}_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),
                                  device=device,
                                  dtype=torch.float32,
                                  channels=3)

        mic = (mic - mic.min()) / (mic.max() - mic.min())
        mic.data = mic.data * combined.data

        def_mic = so.ApplyGrid.Create(deformation, device=device)(mic,
                                                                  deformation)

        # Need to put the mic image in the right slice
        z_or = (im - 1) * 0.05
        def_mic = core.StructuredGrid(
            [2] + list(def_mic.shape()[1:]),
            tensor=def_mic.data.unsqueeze(1).repeat(1, 2, 1, 1),
            spacing=torch.tensor(
                [0.05, def_mic.spacing[0], def_mic.spacing[1]],
                dtype=torch.float32,
                device=device),
            origin=torch.tensor([z_or, def_mic.origin[0], def_mic.origin[1]],
                                dtype=torch.float32,
                                device=device),
            device=device,
            dtype=torch.float32,
            channels=3)

        deformed_images.append(def_mic.copy())

        del def_mic, mic, deformation
        torch.cuda.empty_cache()

        print('done')

    # Now need to load the blockface volume
    block_vol = io.LoadITKFile(
        f'{blockface_dir}volumes/raw/difference_volume.mhd', device='cpu')
    # image_vol = core.StructuredGrid(
    #     size=block_vol.size,
    #     spacing=block_vol.spacing,
    #     origin=block_vol.origin,
    #     device=block_vol.device,
    #     channels=3
    # )
    image_z_spacing = np.diff(np.array(image_nums)).mean() * 0.05
    image_z_origin = image_nums[0] * 0.05

    image_vol = core.StructuredGrid(
        size=[len(image_nums)] + list(block_vol.size[-2:].numpy()),
        spacing=[image_z_spacing] + list(block_vol.spacing[-2:].numpy()),
        origin=[image_z_origin] + list(block_vol.origin[-2:].numpy()),
        device=block_vol.device,
        channels=3)

    for ii, im in enumerate(image_nums):
        image_vol.data[:, ii] = deformed_images[ii].data[:, 0].clone().cpu()

    io.SaveITKFile(image_vol, f'{out_dir}/{block}_image_volume.mhd')
    del image_vol, deformed_images, block_vol
    torch.cuda.empty_cache()
Ejemplo n.º 23
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.')
def _convert_mat_files(Obj):
    rabbitNumber = Obj.rabbitDirectory.split('/')[-1]

    matList = sorted(glob.glob(f'{Obj.rabbitDirectory}/externalRecons/AblationImaging/*'))

    # Do some string comparison to make sure that this file is a sonication file
    matList = [x for x in matList if 'Son' in x]

    # Have to keep track of the MIN and MAX of each transfor so we can know the bounding box to resample to
    size = []
    orgn = []

    if not os.path.exists(os.path.join(Obj.rabbitDirectory + '/rawVolumes/TemperatureRecon/RegVols/')):
        os.makedirs(os.path.join(Obj.rabbitDirectory + '/rawVolumes/TemperatureRecon/RegVols/'))

    for tempFile in matList:

        # Create the output folder for all of the timepoint images
        outDir = os.path.splitext(tempFile)[0]
        outName = outDir.split('/')[-1]
        dirOutName = os.path.join(Obj.rabbitDirectory + '/rawVolumes/TemperatureRecon/', outName)
        if not os.path.exists(dirOutName):
            os.makedirs(dirOutName)

        # Have to add mroe logic here because there are varying lengths of numbers FUN
        preLength = len(outName.split('_')[0])
        outName = outName[:preLength] + '_----' + outName[preLength:]

        struct = spi.loadmat(tempFile)
        imData = struct['ims']

        # Could put some logic here to make sure that they all have a 4th dimension
        timePts = np.shape(imData)[-1]

        # Get transformation and solve for the affine
        # tform = struct['PosDCS']

        # print('min: {0} .... '.format(np.min(np.min(np.min(tform, 0), 0), 0).tolist()))
        # print('max: {0} .... '.format(np.max(np.max(np.max(tform, 0), 0), 0).tolist()))

        # dim = np.shape(tform)[0:3]
        # dim = [x - 1 for x in dim]

        # print('shape: {0} .... '.format(dim))

        # Pull points from the transformation to solve for the affine
        # landmarks = []
        # landmarks.append([[0, 0, 0], tform[0, 0, 0].tolist()])
        # landmarks.append([[dim[0], 0, 0], tform[dim[0], 0, 0].tolist()])
        # landmarks.append([[0, dim[1], 0], tform[0, dim[1], 0].tolist()])
        # landmarks.append([[dim[0], dim[1], 0], tform[dim[0], dim[1], 0].tolist()])
        # landmarks.append([[0, 0, dim[2]], tform[0, 0, dim[2]].tolist()])
        # landmarks.append([[dim[0], 0, dim[2]], tform[dim[0], 0, dim[2]].tolist()])
        # landmarks.append([[0, dim[1], dim[2]], tform[0, dim[1], dim[2]].tolist()])
        # landmarks.append([[dim[0], dim[1], dim[2]], tform[dim[0], dim[1], dim[2]].tolist()])

        # Solve for the affine
        # affine = apps.SolveAffine(landmarks)
        affine = struct['geomInfo'][0,0]['AffineDCS']

        temp = core.StructuredGrid(
            [imData.shape[0], imData.shape[1], imData.shape[2]],
            tensor=torch.tensor(np.real(imData)).permute(-1, 0, 1, 2),
            origin= [0, 0, 0],
            channels=imData.shape[-1]
        )

        # temp = ca.Image3D(cc.MakeGrid(np.shape(tform)[0:3], ca.MEM_DEVICE), ca.MEM_DEVICE)
        # temp.setOrigin(ca.Vec3Df(0, 0, 0))
        # temp.setSpacing(ca.Vec3Df(1, 1, 1))

        affGrid = rc.SolveAffineGrid(temp, affine)

        size.append(affGrid.size.tolist())
        orgn.append(affGrid.origin.tolist())

        print('Converting files for {0} time series images .... '.format(timePts), end='')
        sys.stdout.flush()
        for time in range(0, timePts):

            magIm_np = np.real(imData[:, :, :, time])
            phsIm_np = np.imag(imData[:, :, :, time])

            magIm = core.StructuredGrid(
                [magIm_np.shape[0], magIm_np.shape[1], magIm_np.shape[2]],
                tensor=torch.tensor(magIm_np).unsqueeze(0).float(),
                origin=[0, 0, 0],
                channels=1
            )
            phsIm = core.StructuredGrid(
                [phsIm_np.shape[0], phsIm_np.shape[1], phsIm_np.shape[2]],
                tensor=torch.tensor(phsIm_np).unsqueeze(0).float(),
                origin=[0, 0, 0],
                channels=1
            )

            affFilt = so.AffineTransform.Create(affine=torch.tensor(affine).float())
            affMagIm = affFilt(magIm, out_grid=affGrid)
            affPhsIm = affFilt(phsIm, out_grid=affGrid)

            io.SaveITKFile(affMagIm, dirOutName + '/' + outName + '_real_{0}.nii.gz'.format(str(time).zfill(2)))
            io.SaveITKFile(affPhsIm, dirOutName + '/' + outName + '_imag_{0}.nii.gz'.format(str(time).zfill(2)))

            if time == 0:
                # We need to have the magnitude image for registration
                regIm_np = np.abs(imData[:, :, :, time])
                regIm = core.StructuredGrid(
                    [regIm_np.shape[0], regIm_np.shape[1], regIm_np.shape[2]],
                    tensor=torch.tensor(regIm_np).unsqueeze(0).float(),
                    origin=[0, 0, 0],
                    channels=1
                )
                affRegIm = affFilt(regIm, out_grid=affGrid)
                io.SaveITKFile(affRegIm, dirOutName + '/../RegVols/' + outName[0:5] + '.nii.gz')

        # print('size: {0} .... '.format(magIm_np.shape), end='')
        print('Done')

    return size, orgn
Ejemplo n.º 25
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')
def tempRecon(Obj, opt):

    if not os.path.exists(f'{Obj.rabbitDirectory}/rawVolumes/TemperatureRecon/'):
        os.makedirs(f'{Obj.rabbitDirectory}/rawVolumes/TemperatureRecon/')
        size, orgn = _convert_mat_files(Obj)

        unionOrigin = np.min(orgn, 0).tolist()
        adj = np.abs(np.max(orgn, 0) - np.min(orgn, 0))
        unionSize = (np.max(size, 0) + adj).tolist()
        unionSize = [int(x) for x in unionSize]

    # We are going to create a config file for each registration
    sonicationList = natural_sort(glob.glob(Obj.rabbitDirectory + '/rawVolumes/TemperatureRecon/*'))

    # Need to remove the resample from the list
    sonicationList = [x for x in sonicationList if '_resample' not in x]
    sonicationList = [x for x in sonicationList if 'RegVols' not in x]

    lastName = sonicationList[-1].split('/')[-1]
    preLength = len(lastName.split('_')[0])
    lastName = lastName[:preLength] + '_----' + lastName[preLength:]

    # Set up the Config directory
    if not os.path.exists(Obj.rabbitDirectory + '/ConfigFiles/temperatureConfigs/'):
        os.makedirs(Obj.rabbitDirectory + '/ConfigFiles/temperatureConfigs/')

    # Construct teh common Grid: at this point assuming isotropic spacing of 1
    if 'unionSize' in locals():
        unionSpacing = [1.0, 1.0, 1.0]
        unionIm = core.StructuredGrid(
            size=unionSize,
            origin=unionOrigin,
            spacing=unionSpacing,
            channels=1,
            device=device
        )
        def_im = unionIm.clone()

    else:
        configList = glob.glob(Obj.rabbitDirectory + '/ConfigFiles/temperatureConfigs/*')
        tmpObj = Config.Load(TempConfigSpec, configList[0])
        unionSize = tmpObj.unionSize
        unionOrigin = tmpObj.unionOrigin
        unionSpacing = tmpObj.unionSpacing
        unionIm = core.StructuredGrid(
            size=unionSize,
            origin=unionOrigin,
            spacing=unionSpacing,
            channels=1,
            device=device
        )
        def_im = unionIm.clone()

    # We need to register the last image to the VIBE
    son = sonicationList[-1]
    try:
        regObj = Config.Load(TempConfigSpec,
                             Obj.rabbitDirectory + '/ConfigFiles/temperatureConfigs/{0}_config.yaml'.format(
                                 son.split('/')[-1]))
    except IOError:
        regObj = Config.SpecToConfig(TempConfigSpec)
        regObj.Niter = [40]
        regObj.gaussSigma = [0.1]
        regObj.gaussKernel = [3]
        regObj.regWeight = [2.0]
        regObj.stepSize = [0.004]

        regObj.I0 = 'None'
        regObj.I1 = 'None'
        regObj.unionSize = unionSize
        regObj.unionSpacing = unionSpacing
        regObj.unionOrigin = unionOrigin

    # Need to get the name of the volume
    outName = son.split('/')[-1]
    preLength = len(outName.split('_')[0])
    outName = outName[:preLength] + '_----' + outName[preLength:]

    regObj.outputPath = Obj.rabbitDirectory + '/elastVolumes/TemperatureRecon/' + son.split('/')[-1]

    if not os.path.exists(regObj.outputPath):
        os.makedirs(regObj.outputPath)

    plt.close('all')
    # Get the deformation field that takes the first of the sonication images to the final
    h_post = ER.MultiscaleElast(regObj, opt)
    io.SaveITKFile(h_post, regObj.outputPath + '/final_deformation_Is_to_It.mha')
    rc.WriteConfig(TempConfigSpec, regObj,
                   Obj.rabbitDirectory + '/ConfigFiles/temperatureConfigs/{0}_config.yaml'.format(son.split('/')[-1]))

    print('Applying elast transformation to {0} volumes .... '.format(son.split('/')[-1]), end='')
    sys.stdout.flush()

    for image in glob.glob('{0}/rawVolumes/TemperatureRecon/'.format(Obj.rabbitDirectory) + son.split('/')[-1] + '/*'):
        # Update the name
        outName = image.split('/')[-1]
        outName = outName[:preLength + 4] + 'e' + outName[preLength + 5:]

        im = io.LoadITKFile(image, device=device)
        temp = so.ResampleWorld.Create(unionIm, device=device)(im)
        def_im = so.ApplyGrid.Create(h_post, device=device)(temp)
        io.SaveITKFile(def_im, regObj.outputPath + '/' + outName)

    # common.DebugHere()

    # # Need to resample the final image onto the new grid
    # for image in glob.glob('{0}/rawVolumes/TemperatureRecon/'.format(Obj.rabbitDirectory) + sonicationList[-1].split('/')[-1] + '/*'):

    # 	outputPath = Obj.rabbitDirectory + '/rawVolumes/TemperatureRecon/' + sonicationList[-1].split('/')[-1] + '_resample'

    # 	if not os.path.exists(outputPath):
    # 		os.makedirs(outputPath)

    # 	outName = image.split('/')[-1]
    # 	im = common.LoadITKImage(image, ca.MEM_DEVICE)

    # 	cc.ResampleWorld(unionIm, im, bg=3)
    # 	common.SaveITKImage(unionIm, outputPath + '/' + outName)

    for son in sonicationList[:-1]:

        # Create the registration object for elastic
        try:
            regObj = Config.Load(TempConfigSpec,
                                 Obj.rabbitDirectory + '/ConfigFiles/temperatureConfigs/{0}_config.yaml'.format(
                                     son.split('/')[-1]))
        except IOError:
            regObj = Config.SpecToConfig(TempConfigSpec)

        # Need to get the name of the volume
        outName = son.split('/')[-1]
        preLength = len(outName.split('_')[0])
        outName = outName[:preLength] + '_----' + outName[preLength:]

        # Always set the target image to the last file - have to get the first mag image!
        regObj.I0 = son + '/../RegVols/' + outName[0:5] + '.nii.gz'

        # Do we have to get the file that has been registered to the vibe??
        regObj.I1 = sonicationList[-1] + '/../RegVols/' + lastName[0:5] + '.nii.gz'

        # Set the grid parameters of the unionFOV
        regObj.unionSize = unionSize
        regObj.unionSpacing = unionSpacing
        regObj.unionOrigin = unionOrigin

        # if sonicationList.index(son) < 8:
        # 	regObj.stepSize = [0.000]
        # else:
        # 	regObj.stepSize = [0.004]

        regObj.outputPath = Obj.rabbitDirectory + '/elastVolumes/TemperatureRecon/' + son.split('/')[-1]

        if not os.path.exists(regObj.outputPath):
            os.makedirs(regObj.outputPath)

        plt.close('all')
        # Get the deformation field that takes the first of the sonication images to the final
        h = ER.MultiscaleElast(regObj, opt)

        # Need to compose the h field to get the full deformation
        h_comp = so.ComposeGrids.Create(device=device)([h, h_post])
        io.SaveITKFile(h_comp, regObj.outputPath + '/final_deformation_Is_to_It.mha')

        # Write out the config file
        if not os.path.exists(Obj.rabbitDirectory + '/ConfigFiles/temperatureConfigs'):
            os.makedirs(Obj.rabbitDirectory + '/ConfigFiles/temperatureConfigs')

        rc.WriteConfig(TempConfigSpec, regObj,
                       Obj.rabbitDirectory + '/ConfigFiles/temperatureConfigs/{0}_config.yaml'.format(
                           son.split('/')[-1]))

        # Need to itterate through all the mag and phase images and apply the deformation
        print('Applying elast transformation to {0} volumes .... '.format(son.split('/')[-1]), end='')
        sys.stdout.flush()

        for image in glob.glob(
                '{0}/rawVolumes/TemperatureRecon/'.format(Obj.rabbitDirectory) + son.split('/')[-1] + '/*'):
            # Update the name
            outName = image.split('/')[-1]
            outName = outName[:preLength + 4] + 'e' + outName[preLength + 5:]

            im = io.LoadITKFile(image, device=device)
            temp = so.ResampleWorld.Create(unionIm, device=device)(im)
            def_im = so.ApplyGrid.Create(h_post, device=device)(temp)
            io.SaveITKFile(def_im, regObj.outputPath + '/' + outName)
Ejemplo n.º 27
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')
def ExternalRecon(regObj, opt):

    rerun = False

    # If the path doesn't exists, we can make it and try to transfer the files
    if not os.path.exists(f'{regObj.rabbitDirectory}/externalRecons/'):

        for timepoint in opt.transfer_timepoints:
            # Use subprocess to get the list of files from RAID10
            p = sp.Popen([
                "ssh", "*****@*****.**",
                f"find {opt.raw_dir}*{opt.rabbit[-2:]}* -type d"
            ],
                         stdout=sp.PIPE)
            raidDirs, _ = p.communicate()

            # There is a new line at the end which puts an empty at the end of the list
            raidDirs = raidDirs.decode('utf-8').split('\n')[:-1]

            # Sort out the offline recon directories
            offlineDirs = [x for x in raidDirs if 'OfflineRecon' in x]
            offlineFiles = []

            for offDir in offlineDirs:
                # Use subprocess to get the list of files from RAID10
                p = sp.Popen([
                    "ssh", "*****@*****.**",
                    f"find {offDir.split(' ')[0]}*/OfflineRecon/"
                ],
                             stdout=sp.PIPE)
                offline_files, _ = p.communicate()

                # There is a new line at the end which puts an empty at the end of the list
                offline_files = offline_files.decode('utf-8').split('\n')[:-1]
                offlineFiles += offline_files

            tpList = []
            # Create a selector so the ablation volumes can be selected
            Selector = rc.PathSelector(
                tk, sorted(offlineFiles),
                f'Choose {timepoint} Day Offline Files to Transfer')
            convertFiles = Selector.get_files()
            Selector.root.destroy()
            tpList += convertFiles

            for i, path in enumerate(tpList, 1):
                # Get the name of the file
                filename = path.split('OfflineRecon/')[-1]

                # Correct the special characters in the path string so the scp command will work
                path = path.replace("^", "\^").replace(" ", "\ ")

                rawOutName = f'{regObj.rabbitDirectory}/externalRecons/{timepoint}/{filename}'
                rawOutName = rawOutName.replace('\\ ', '_').replace('\ ', '_')

                # Check if the folder exists or not
                if not os.path.exists(os.path.dirname(rawOutName)):
                    os.makedirs(os.path.dirname(rawOutName))

                # If the volume doesn't already exist, then copy it over
                if not os.path.exists(rawOutName):
                    p = sp.Popen([
                        "scp", "-r", f"[email protected]:{path}",
                        rawOutName
                    ])
                    os.waitpid(p.pid, 0)

        # print('No external files to recon ... skipping')
        # return
    print('Reconning External Files ... ', end='')

    # Get a list of the files
    ablation_files = sorted(
        glob.glob(
            f'{regObj.rabbitDirectory}/externalRecons/AblationImaging/*'))

    pre_files = sorted(
        [x for x in ablation_files if 'Pre' in x and 'STIR' in x])[::-1]
    post_files = sorted(
        [x for x in ablation_files if 'Post' in x and 'STIR' in x])[::-1]

    pre_dicts = [loadmat(x) for x in pre_files]
    post_dicts = [loadmat(x) for x in post_files]

    pre_vol = _get_stir_vol(pre_dicts)
    post_vol = _get_stir_vol(post_dicts)

    # Get a list of the volumes in the ablation imaging already so we can assign the right number.
    files = glob.glob(f'{regObj.rabbitDirectory}/rawVolumes/AblationImaging/*')
    start_num = len(files)
    out_dir = f'{regObj.rabbitDirectory}/rawVolumes/AblationImaging/'
    pre_name = '_----_pre_ablation_t1_map.nii.gz'
    post_name = '_----_post_ablation_t1_map.nii.gz'

    if not any([pre_name in x for x in files]) or rerun:
        io.SaveITKFile(pre_vol, f'{out_dir}{start_num + 1:03d}{pre_name}')

    if not any([post_name in x for x in files]) or rerun:
        io.SaveITKFile(post_vol, f'{out_dir}{start_num + 2:03d}{post_name}')

    long_files = sorted(
        glob.glob(f'{regObj.rabbitDirectory}/externalRecons/PostImaging/*'))
    long_files = [x for x in long_files if 'STIR' in x]
    long_dicts = [loadmat(x) for x in long_files]
    long_vol = _get_stir_vol(long_dicts)

    files = glob.glob(f'{regObj.rabbitDirectory}/rawVolumes/PostImaging/*')
    start_num = len(files)
    out_dir = f'{regObj.rabbitDirectory}/rawVolumes/PostImaging/'
    long_name = '_----_t1_map.nii.gz'

    if not any([long_name in x for x in files]) or rerun:
        io.SaveITKFile(long_vol, f'{out_dir}{start_num + 1:03d}{long_name}')

    print('Done')


#### TO DO ####
# Make it so that this recon doesn't run every time
Ejemplo n.º 29
0
def def_block(rabbit, block):
    data_dir = f'/hdscratch/ucair/{rabbit}/blockface/{block}/'
    vol_ext = '/volumes/raw/'
    raw_ext = '/surfaces/raw/'
    def_ext = '/volumes/deformable/'

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

    # Load phi_inv
    phi_inv = io.LoadITKFile(f'{data_dir}{vol_ext}{block}_phi_inv.mhd',
                             device=device)
    phi_inv.set_size((60, 1024, 1024))
    #
    # # Phi_inv is in z,y,x and need x,y,z
    phi_inv.data = phi_inv.data.flip(0)

    # Load the volume to apply this field to
    bf = io.LoadITKFile(f'{data_dir}{vol_ext}scatter_volume.mhd',
                        device=device)
    seg = io.LoadITKFile(f'{data_dir}{vol_ext}segmentation_volume.mhd',
                         device=device)

    # aff_grid = core.StructuredGrid.FromGrid(phi_inv, channels=3)
    # aff_grid.set_to_identity_lut_()
    # aff_grid.data = aff_grid.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()

    # 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([3] + list(range(0, 3)))
    #
    # aff_grid.data = aff_grid.data.flip(0)
    #
    # aff_bf = so.ApplyGrid.Create(aff_grid, device=aff_grid.device, dtype=aff_grid.dtype)(bf, out_grid=phi_inv)

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

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

    try:
        stitch_files = sorted(
            glob.glob(f'{data_dir}{vol_ext}{block}_phi_inv_stitch_*.mhd'))
        stitch_list = []
        for stitch_file in stitch_files:
            phi_stitch = io.LoadITKFile(stitch_file, device=device)
            phi_stitch.set_size((60, 1024, 1024))
            stitch_list += [phi_stitch.clone()]
        composer = so.ComposeGrids.Create(padding_mode='border', device=device)
        final_phi = composer([phi_inv] + stitch_list)
        phi_inv = final_phi.clone()
    except IOError:
        pass

    test = so.ApplyGrid.Create(stitch_list[0], pad_mode='zeros',
                               device=device)(bf, stitch_list[0])
    io.SaveITKFile(test, '/home/sci/blakez/HOPEFUL.mhd')

    # unstitch_files = sorted(glob.glob(f'{data_dir}{vol_ext}{block}_phi_stitch_*.mhd'))
    # phi_unstitch = io.LoadITKFile(unstitch_files[0], device=device)
    # phi_unstitch.set_size((60, 1024, 1024))
    # test_undone = so.ApplyGrid.Create(phi_unstitch, pad_mode='zeros', device=device)(test, phi_unstitch)
    # io.SaveITKFile(test_undone, '/home/sci/blakez/HOPEFUL_undone.mhd')

    def_bf = so.ApplyGrid.Create(phi_inv, pad_mode='zeros',
                                 device=device)(bf, phi_inv)
    def_seg = so.ApplyGrid.Create(phi_inv, pad_mode='zeros',
                                  device=device)(seg, phi_inv)

    # Save out the deformed volumes
    io.SaveITKFile(def_bf,
                   f'{data_dir}{def_ext}difference_volume_deformable.mhd')
    io.SaveITKFile(def_seg,
                   f'{data_dir}{def_ext}segmentation_volume_deformable.mhd')
Ejemplo n.º 30
0
def mr_to_block(block_path,
                rabbit,
                t1_vol,
                npv_vol=None,
                t2_vol=None,
                ext_vols=[]):

    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/{rabbit}/mri/exvivo/volumes/deformable/{block}/'
    invivo_out = f'/hdscratch/ucair/{rabbit}/mri/invivo/volumes/deformable/{block}/'
    if not os.path.exists(invivo_out):
        os.makedirs(invivo_out)

    # deformations = []

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

    # Genereate the deformation for the block
    to_block = gd.generate(rabbit,
                           block=block,
                           source_space='invivo',
                           target_space='blockface')

    # Load the Day3 MR file to be deformed
    # t2_motion = io.LoadITKFile(t2_vol, device=device)
    ce_t1 = io.LoadITKFile(t1_vol, device=device)
    # adc = io.LoadITKFile(ext_vols[0], device=device)
    npv = io.LoadITKFile(npv_vol, device=device)

    torch.cuda.empty_cache()

    # t2_to_block = so.ApplyGrid.Create(to_block, device=device, pad_mode='zeros')(t2_motion, to_block)
    # io.SaveITKFile(t2_to_block, f'{invivo_out}invivo_t2_to_{block}.mhd')

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

    # adc_to_block = so.ApplyGrid.Create(to_block, device=device, pad_mode='zeros')(adc, to_block)
    # io.SaveITKFile(adc_to_block, f'{invivo_out}invivo_adc_to_{block}.mhd')
    #
    npv_to_block = so.ApplyGrid.Create(to_block,
                                       device=device,
                                       pad_mode='zeros')(npv, to_block)
    io.SaveITKFile(npv_to_block, f'{invivo_out}invivo_npv_to_{block}.mhd')

    # # Load the exvivo
    # ex_ce_t1 = io.LoadITKFile(
    #     '/home/sci/blakez/ucair/18_047/rawVolumes/ExVivo_2018-07-26/011_----_3D_VIBE_0p5iso_cor_3ave.nii.gz',
    #     device=device
    # )
    #
    # ex_t2 = io.LoadITKFile(
    #     '/home/sci/blakez/ucair/18_047/rawVolumes/ExVivo_2018-07-26/015_----_t2_spc_0p5x0p5x1mm_iso_satBand_3p5ave'
    #     '.nii.gz',
    #     device=device
    # )

    # exvivo_to_block = so.ComposeGrids.Create(device=device)(deformations[1:][::-1])
    # t1_ex_to_block = so.ApplyGrid.Create(exvivo_to_block, device=device, pad_mode='zeros')(ex_ce_t1, exvivo_to_block)
    # io.SaveITKFile(t1_ex_to_block, f'{exvivo_out}exvivo_ce_t1_to_{block}.mhd')
    #
    # t2_ex_to_block = so.ApplyGrid.Create(exvivo_to_block, device=device, pad_mode='zeros')(ex_t2, exvivo_to_block)
    # io.SaveITKFile(t2_ex_to_block, f'{exvivo_out}exvivo_t2_to_{block}.mhd')

    print(f'Done with {block}')