def stack_hitology_volumes(rabbit, block_paths): def_ablations = [] def_combineds = [] out_dir = f'/hdscratch/ucair/{rabbit}/microscopic/recons/' if not os.path.exists(out_dir): os.makedirs(out_dir) for block_path in block_paths: block = block_path.split('/')[-1] histology_dir = f'/hdscratch/ucair/{rabbit}/microscopic/{block}/' def_dir = f'{histology_dir}/volume/deformable/' # Load the deformed volume def_ablation = io.LoadITKFile(f'{def_dir}/{block}_ablation_segmentation_to_exvivo.mhd', device=device) # def_combined = io.LoadITKFile(f'{def_dir}/{block}_ablation_and_transition_segmentation_to_invivo.mhd', # device=device) # Threshold the volume def_ablation.data = (def_ablation.data >= 0.8).float() # def_combined.data = (def_combined.data >= 0.8).float() def_ablations.append(def_ablation) # def_combineds.append(def_combined) full_ablation = def_ablations[0].copy() full_ablation = full_ablation * 0.0 for i, v in enumerate(def_ablations, 1): if v.sum() != 0.0: io.SaveITKFile(v, f'/home/sci/blakez/test_outs/volume{i}.nii.gz') full_ablation = full_ablation + v full_ablation.data = (full_ablation.data > 0.0).float() io.SaveITKFile(full_ablation, f'{out_dir}all_ablation_segs_to_exvivo.mhd')
def stack_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')
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')
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')
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')
def main(rabbit, base_dir='/hdscratch/ucair/'): device = 'cuda:1' in_path = f'{base_dir}{rabbit}/mri/exvivo/volumes/raw/' out_base = f'{base_dir}{rabbit}/mri/exvivo/volumes/deformable/invivo/' if not os.path.exists(out_base): os.makedirs(out_base) to_invivo = generate(rabbit, source_space='exvivo', target_space='invivo', base_dir=base_dir) t2_file = sorted(glob.glob(f'{in_path}*t2*')) t1_file = sorted(glob.glob(f'{in_path}*VIBE*')) if len(t1_file) > 1: t1_file = [x for x in t1_file if '0p5' in x] exvivo_t2 = io.LoadITKFile(t2_file[0], device=device) exvivo_t1 = io.LoadITKFile(t1_file[0], device=device) def_t2 = so.ApplyGrid.Create(to_invivo, device=device)(exvivo_t2, to_invivo) def_t1 = so.ApplyGrid.Create(to_invivo, device=device)(exvivo_t1, to_invivo) io.SaveITKFile(def_t2, f'{out_base}exvivo_t2_def_to_invivo_{rabbit}.nii.gz') io.SaveITKFile(def_t1, f'{out_base}exvivo_t1_def_to_invivo_{rabbit}.nii.gz') # # # to_exvivo = generate(rabbit, source_space='invivo', target_space='exvivo') # to_exvivo_affine = generate_affine_only(rabbit, source_space='invivo', target_space='exvivo') # # invivo = io.LoadITKFile(sorted(glob.glob(f'/hdscratch/ucair/{rabbit}/mri/invivo/volumes/raw/*t2*'))[0], device=device) # aff_invivo = so.ApplyGrid.Create(to_exvivo_affine, device=device)(invivo, to_exvivo_affine) # def_invivo = so.ApplyGrid.Create(to_exvivo, device=device)(invivo, to_exvivo) # # io.SaveITKFile(aff_invivo, f'/home/sci/blakez/test_outs/invivo_aff_to_exvivo_npv_{rabbit}.nii.gz') # io.SaveITKFile(def_invivo, f'/home/sci/blakez/test_outs/invivo_def_to_exvivo_npv_{rabbit}.nii.gz') # # io.SaveITKFile(def_exvivo, f'{out_base}/invivo/{exvivo_name}_to_invivo.nii.gz') print('done')
def deform_image_volumes(rabbit, block, base_dir='/hdscratch/ucair/'): histology_dir = f'{base_dir}{rabbit}/microscopic/{block}/' raw_dir = f'{histology_dir}/volume/raw/' out_dir = f'{histology_dir}/volume/deformable/' if not os.path.exists(out_dir): os.makedirs(out_dir) deformation = generate(rabbit, block, source_space='blockface', target_space='invivo', base_dir=base_dir, pad_mode='zeros') def_file = f'/home/sci/blakez/ucair/longitudinal/{rabbit}/' def_file += 'deformation_fields/Day3_non_contrast_VIBE_interday_deformation_incomp.nii.gz' day0 = io.LoadITKFile( f'/hdscratch/ucair/AcuteBiomarker/Data/{rabbit}/{rabbit}_day3_to_day0_phi_inv.nii.gz', device=device) deformation = so.ComposeGrids.Create( device=device, padding_mode='zeros')([day0, deformation]) deformation.to_(device=device) deformation.set_size((512, 512, 512)) # Load the original volume image_vol = io.LoadITKFile(f'{raw_dir}/{block}_image_volume.mhd', device=device) def_image = so.ApplyGrid.Create(deformation, device=device)(image_vol, deformation) test_diff_z = np.diff(deformation.data[0, :].cpu().numpy()) test_diff_y = np.diff(deformation.data[1, :].cpu().numpy()) test_diff_x = np.diff(deformation.data[2, :].cpu().numpy()) test_diff_z_small = np.abs(test_diff_z) >= 0.5 test_diff_y_small = np.abs(test_diff_y) >= 0.5 test_diff_x_small = np.abs(test_diff_x) >= 0.5 mask = np.logical_and(np.logical_and(test_diff_x == 0, test_diff_y == 0), test_diff_z == 0) mask_small = np.logical_and( np.logical_and(test_diff_x_small == 0, test_diff_y_small == 0), test_diff_z_small == 0) final_mask = np.logical_and(mask == False, mask_small == True) mask = torch.zeros_like(def_image.data)[0, None] mask[:, :, :, :-1] = torch.tensor(final_mask) def_image.data = def_image.data * mask io.SaveITKFile(def_image, f'{out_dir}/{block}_image_volume_to_invivo.mhd')
def 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')
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')
def generate_label_volume(rabbit, block): data_dir = f'/hdscratch/ucair/{rabbit}/blockface/{block}/' tif_files = sorted(glob.glob(f'{data_dir}volumes/raw/labels_tif/*')) hdr = read_mhd_header(f'{data_dir}volumes/raw/difference_volume.mhd') hdr['ElementDataFile'] = hdr['ElementDataFile'].replace( 'difference', 'segmentation') hdr['ElementNumberOfChannels'] = 1 # Load each of the tif images and then dump it into the label dir for tif_file in tif_files: tif_name = tif_file.split('/')[-1].split('.')[0] if os.path.exists( f'{data_dir}volumes/raw/segmentation/{tif_name}.mhd'): continue tif = io.LoadITKFile(tif_file) io.SaveITKFile(tif, f'{data_dir}volumes/raw/segmentation/{tif_name}.mhd') write_mhd_header(f'{data_dir}volumes/raw/segmentation_volume.mhd', hdr)
def 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 = []
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)
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')
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')
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')
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)
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')
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} ... ')
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')
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()
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()
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
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)
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
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')
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}')