def apply_resample( tensor: torch.Tensor, # (C, D, H, W) affine: np.ndarray, interpolation_order: int, target_spacing: Optional[Tuple[float, float, float]] = None, reference: Optional[Tuple[torch.Tensor, np.ndarray]] = None, ) -> Tuple[torch.Tensor, np.ndarray]: array = tensor.numpy() niis = [] arrays_resampled = [] if reference is None: for channel in array: nii = resample_to_output( nib.Nifti1Image(channel, affine), voxel_sizes=target_spacing, order=interpolation_order, ) arrays_resampled.append(nii.get_fdata(dtype=np.float32)) else: reference_tensor, reference_affine = reference reference_array = reference_tensor.numpy()[0] for channel_array in array: nii = resample_from_to( nib.Nifti1Image(channel_array, affine), nib.Nifti1Image(reference_array, reference_affine), order=interpolation_order, ) arrays_resampled.append(nii.get_fdata(dtype=np.float32)) tensor = torch.Tensor(arrays_resampled) return tensor, nii.affine
def crop_CT(filepath, volume, lungs_mask_filename, new_spacing, storage_prefix): # @TODO. Should name the lungs mask file with a specific name, otherwise will be multiple instances when ensemble... if lungs_mask_filename is None or not os.path.exists(lungs_mask_filename): script_path = '/'.join(os.path.dirname(os.path.realpath(__file__)).split('/')[:-2]) + '/main.py' #output_prefix = '/'.join(os.path.dirname(os.path.realpath(__file__)).split('/')[:-2]) + '/tmp' subprocess.call(['python3', '{script}'.format(script=script_path), '-i{input}'.format(input=filepath), '-o{output}'.format(output=storage_prefix), '-m{model}'.format(model='CT_Lungs'), '-g{gpu}'.format(gpu=os.environ["CUDA_VISIBLE_DEVICES"])]) lungs_mask_filename = storage_prefix + '-pred_Lungs.nii.gz' else: ext_split = lungs_mask_filename.split('.') extension = '.'.join(ext_split[1:]) if extension != 'nii' or extension != 'nii.gz': lungs_mask_filename = convert_and_export_to_nifti(input_filepath=lungs_mask_filename) lungs_mask_ni = load_nifti_volume(lungs_mask_filename) resampled_volume = resample_to_output(lungs_mask_ni, new_spacing, order=0) lungs_mask = resampled_volume.get_data().astype('float32') lungs_mask[lungs_mask < 0.5] = 0 lungs_mask[lungs_mask >= 0.5] = 1 lungs_mask = lungs_mask.astype('uint8') lung_region = regionprops(lungs_mask) min_row, min_col, min_depth, max_row, max_col, max_depth = lung_region[0].bbox print('cropping params', min_row, min_col, min_depth, max_row, max_col, max_depth) cropped_volume = volume[min_row:max_row, min_col:max_col, min_depth:max_depth] bbox = [min_row, min_col, min_depth, max_row, max_col, max_depth] return cropped_volume, bbox
def load_medical_image(path, crop_size=(0, 0, 0), crop=(0, 0, 0), type=None, normalization="mean", resample=None, viz3d=False, to_canonical=False): slices_crop, w_crop, h_crop = crop img_nii = nib.load(path) img_np = np.squeeze(img_nii.get_fdata(dtype=np.float32)) if viz3d: return torch.from_numpy(img_np) if to_canonical: img_nii = nib.as_closest_canonical(img_nii) img_np = img_nii.get_fdata(dtype=np.float32) if crop_size[0] != 0: img_np = img_np[slices_crop:slices_crop + crop_size[0], w_crop:w_crop + crop_size[1], h_crop:h_crop + crop_size[2]] if resample is not None: img_nii = resample_to_output(img_nii, voxel_sizes=resample) img_np = np.squeeze(img_nii.get_fdata(dtype=np.float32)) img_tensor = torch.from_numpy(img_np) # slice , width, height #print('final tensor shape', img_tensor.shape) if type != "label": img_tensor = normalize(img_tensor, normalization=normalization) return img_tensor
def load_medical_image(path, type=None, resample=None, viz3d=False, to_canonical=False, rescale=None, normalization='full_volume_mean', clip_intenisty=True, crop_size=(0, 0, 0), crop=(0, 0, 0), ): img_nii = nib.load(path) if to_canonical: img_nii = nib.as_closest_canonical(img_nii) if resample is not None: img_nii = resample_to_output(img_nii, voxel_sizes=resample) img_np = np.squeeze(img_nii.get_fdata(dtype=np.float32)) if viz3d: return torch.from_numpy(img_np) # 1. Intensity outlier clipping if clip_intenisty and type != "label": img_np = percentile_clip(img_np) # 2. Rescale to specified output shape if rescale is not None: rescale_data_volume(img_np, rescale) # 3. intensity normalization img_tensor = torch.from_numpy(img_np) MEAN, STD, MAX, MIN = 0., 1., 1., 0. if type != 'label': MEAN, STD = img_tensor.mean(), img_tensor.std() MAX, MIN = img_tensor.max(), img_tensor.min() if type != "label": img_tensor = normalize_intensity(img_tensor, normalization=normalization, norm_values=(MEAN, STD, MAX, MIN)) img_tensor = crop_img(img_tensor, crop_size, crop) return img_tensor
def apply_resample( tensor: torch.Tensor, affine: np.ndarray, interpolation_order: int, target_spacing: Optional[Tuple[float, float, float]] = None, reference: Optional[Tuple[torch.Tensor, np.ndarray]] = None, ) -> Tuple[torch.Tensor, np.ndarray]: array = tensor.numpy()[0] if reference is None: nii = resample_to_output( nib.Nifti1Image(array, affine), voxel_sizes=target_spacing, order=interpolation_order, ) else: reference_tensor, reference_affine = reference reference_array = reference_tensor.numpy()[0] nii = resample_from_to( nib.Nifti1Image(array, affine), nib.Nifti1Image(reference_array, reference_affine), order=interpolation_order, ) tensor = torch.from_numpy(nii.get_fdata(dtype=np.float32)) tensor = tensor.unsqueeze(dim=0) return tensor, nii.affine
def run_pre_processing(filename, pre_processing_parameters, lungs_mask_filename, storage_prefix): print("Extracting data...") ext_split = filename.split('.') extension = '.'.join(ext_split[1:]) if extension != 'nii' or extension != 'nii.gz': filename = convert_and_export_to_nifti(input_filepath=filename) pass nib_volume = load_nifti_volume(filename) print("Pre-processing...") # Normalize spacing new_spacing = pre_processing_parameters.output_spacing if pre_processing_parameters.output_spacing is None: tmp = np.min(nib_volume.header.get_zooms()) new_spacing = [tmp, tmp, tmp] library = pre_processing_parameters.preprocessing_library if library == 'nibabel': resampled_volume = resample_to_output(nib_volume, new_spacing, order=1) data = resampled_volume.get_data().astype('float32') crop_bbox = None # Exclude background if pre_processing_parameters.crop_background: data, crop_bbox = crop_CT(filename, data, lungs_mask_filename, new_spacing, storage_prefix) # Resize to network input size data = resize_volume(data, pre_processing_parameters.new_axial_size, pre_processing_parameters.slicing_plane, order=1) # Normalize values data = intensity_normalization(volume=data, parameters=pre_processing_parameters) return nib_volume, resampled_volume, data, crop_bbox
def test_load_spacingd_rotate(self, filename): data_dict = self.load_image(filename) affine = data_dict["image"].affine data_dict["image"].meta["original_affine"] = data_dict[ "image"].affine = (torch.tensor( [[0, 0, 1, 0], [0, 1, 0, 0], [-1, 0, 0, 0], [0, 0, 0, 1]], dtype=torch.float64) @ affine) t = time.time() res_dict = Spacingd(keys="image", pixdim=(1, 2, 3), diagonal=True, padding_mode="zeros")(data_dict) t1 = time.time() print(f"time monai: {t1 - t}") anat = nibabel.Nifti1Image(np.asarray(data_dict["image"][0]), data_dict["image"].meta["original_affine"]) ref = resample_to_output(anat, (1, 2, 3), order=1) t2 = time.time() print(f"time scipy: {t2 - t1}") self.assertTrue(t2 >= t1) np.testing.assert_allclose(res_dict["image"].affine, ref.affine) if "anatomical" not in filename: np.testing.assert_allclose(res_dict["image"].shape[1:], ref.shape) np.testing.assert_allclose(ref.get_fdata(), res_dict["image"][0], atol=0.05) else: # different from the ref implementation (shape computed by round # instead of ceil) np.testing.assert_allclose(ref.get_fdata()[..., :-1], res_dict["image"][0], atol=0.05)
def apply_resample( self, tensor, affine, voxel_sizes, interpolation: Interpolation, ): if interpolation == Interpolation.NEAREST: order = 0 elif interpolation == Interpolation.LINEAR: order = 1 elif interpolation == Interpolation.BSPLINE: order = 3 else: message = f'Interpolation not implemented yet: {interpolation}' raise NotImplementedError(message) array = tensor.numpy()[0] nii = resample_to_output( nib.Nifti1Image(array, affine), voxel_sizes=voxel_sizes, order=order, ) tensor = torch.from_numpy(nii.get_fdata(dtype=np.float32)) tensor = tensor.unsqueeze(dim=0) return tensor, nii.affine
def test_against_spm_resample(): # Test resampling against images resampled with SPM12 # anatomical.nii has a diagonal -2, 2 2 affine; # functional.nii has a diagonal -4, 4 4 affine; # These are a bit boring, so first add some rotations and translations to # the anatomical image affine, and then resample to the first volume in the # functional, and compare to the same thing in SPM. # See ``make_moved_anat.py`` script in this directory for input to SPM. anat = nib.load(pjoin(DATA_DIR, 'anatomical.nii')) func = nib.load(pjoin(DATA_DIR, 'functional.nii')) some_rotations = euler2mat(0.1, 0.2, 0.3) extra_affine = from_matvec(some_rotations, [3, 4, 5]) moved_anat = nib.Nifti1Image(anat.get_data().astype(float), extra_affine.dot(anat.affine), anat.header) one_func = nib.Nifti1Image(func.dataobj[..., 0], func.affine, func.header) moved2func = resample_from_to(moved_anat, one_func, order=1, cval=np.nan) spm_moved = nib.load(pjoin(DATA_DIR, 'resampled_anat_moved.nii')) assert_spm_resampling_close(moved_anat, moved2func, spm_moved) # Next we resample the rotated anatomical image to output space, and compare # to the same operation done with SPM (our own version of 'reorient.m' by # John Ashburner). moved2output = resample_to_output(moved_anat, 4, order=1, cval=np.nan) spm2output = nib.load(pjoin(DATA_DIR, 'reoriented_anat_moved.nii')) assert_spm_resampling_close(moved_anat, moved2output, spm2output);
def test_load_spacingd_rotate(self, filename): data = {"image": filename} data_dict = LoadNiftid(keys="image")(data) data_dict = AddChanneld(keys="image")(data_dict) affine = data_dict["image.affine"] data_dict["image.original_affine"] = data_dict["image.affine"] = ( np.array([[0, 0, 1, 0], [0, 1, 0, 0], [-1, 0, 0, 0], [0, 0, 0, 1] ]) @ affine) res_dict = Spacingd(keys="image", pixdim=(1, 2, 3), diagonal=True, mode="constant")(data_dict) np.testing.assert_allclose(data_dict["image.affine"], res_dict["image.original_affine"]) anat = nibabel.Nifti1Image(data_dict["image"][0], data_dict["image.affine"]) ref = resample_to_output(anat, (1, 2, 3)) np.testing.assert_allclose(res_dict["image.affine"], ref.affine) if "anatomical" not in filename: np.testing.assert_allclose(res_dict["image"].shape[1:], ref.shape) np.testing.assert_allclose(ref.get_fdata(), res_dict["image"][0]) else: # different from the ref implementation (shape computed by round # instead of ceil) np.testing.assert_allclose(ref.get_fdata()[..., :-1], res_dict["image"][0])
def test_load_spacingd_rotate(self, filename): data = {"image": filename} data_dict = LoadNiftid(keys="image")(data) data_dict = AddChanneld(keys="image")(data_dict) affine = data_dict["image_meta"]["affine"] data_dict["image_meta"]["original_affine"] = data_dict["image_meta"][ "affine"] = (np.array([[0, 0, 1, 0], [0, 1, 0, 0], [-1, 0, 0, 0], [0, 0, 0, 1]]) @ affine) t = time.time() res_dict = Spacingd(keys="image", pixdim=(1, 2, 3), diagonal=True, mode="zeros")(data_dict) t1 = time.time() print(f"time monai: {t1 - t}") anat = nibabel.Nifti1Image(data_dict["image"][0], data_dict["image_meta"]["original_affine"]) ref = resample_to_output(anat, (1, 2, 3), order=1) t2 = time.time() print(f"time scipy: {t2 - t1}") self.assertTrue(t2 >= t1) np.testing.assert_allclose(res_dict["image_meta"]["affine"], ref.affine) if "anatomical" not in filename: np.testing.assert_allclose(res_dict["image"].shape[1:], ref.shape) np.testing.assert_allclose(ref.get_fdata(), res_dict["image"][0], atol=0.05) else: # different from the ref implementation (shape computed by round # instead of ceil) np.testing.assert_allclose(ref.get_fdata()[..., :-1], res_dict["image"][0], atol=0.05)
def load_isotropic(self, in_fn, t=0): vol_img, vol = load_3d(in_fn, t) sep = [get_spacing(vol_img.affine, i) for i in range(3)] min_unit = np.min(np.abs(sep)) #new_units=[min_unit*np.sign(sep[0]), min_unit*np.sign(sep[1]), min_unit*np.sign(sep[2]) ] vol_img = resample_to_output(vol_img, [min_unit] * 3, order=1) vol = vol_img.get_fdata() return vol_img, vol
def kora_vol_label_allignment(file_paths): print("STARTING KORA LABEL-MAPS.") print('Reading Label Maps.....') for vol in file_paths.keys(): print(vol) if (vol_to_check_list is not None and vol not in vol_to_check_list) or (vol == "") or (vol in exclude): continue print(file_paths[vol]['LABEL_PATHS']) if len(file_paths[vol]['LABEL_PATHS']) == 0: print(f"#################### ALERT:: NO LABELPATHS IN THE DICTIONARY FOR {vol} #########################") continue volume = nb.load(file_paths[vol]['N4_2']['OPP_CORRECTED']) f_volume = nb.load(file_paths[vol]['N4_2']['F_CORRECTED']) w_volume = nb.load(file_paths[vol]['N4_2']['W_CORRECTED']) in_volume = nb.load(file_paths[vol]['N4_2']['IN_CORRECTED']) img_ras_list = [] later = [] for label_file_to_read in file_paths[vol]['LABEL_PATHS']: img_ras, lidx, labelname = read_ras(label_file_to_read, is_label=True) if labelname is None or img_ras is None: continue img_ras = makeit_3d(img_ras) if labelname in ['PANCREAS']: later.append([img_ras, lidx+LABEL_EXTENSION_FOR_OVERLAP_REMOVAL, labelname]) else: img_ras_list.append([img_ras, lidx+LABEL_EXTENSION_FOR_OVERLAP_REMOVAL, labelname]) img_ras_list.extend(later) s_label = kora_label_parts(img_ras_list) if SAMPLING: s_label = resample_to_output(s_label, TARGET_RESOLUTION, order=0, mode='nearest', cval=0) s_label = drop_overlapped_pixels(s_label, np.array(img_ras_list)[:, 1]) if vol == 'KORA2460249': volume, s_label = kora_vol_label_fix(volume, s_label, True) else: volume, s_label = kora_vol_label_fix(volume, s_label) # print('Viewing Stitched Images.....') # volume_3_view_viewer(get_volume_data(volume)) # volume_3_view_viewer(get_volume_data(f_volume)) # volume_3_view_viewer(get_volume_data(w_volume)) # volume_3_view_viewer(get_volume_data(in_volume)) # volume_3_view_viewer(get_volume_data(s_label)) print('Saving Processed & Stitched Image.....') save_volume(volume, f'{processed_dir}/volume/{vol}', np.int16) save_volume(f_volume, f'{processed_dir}/volume_f/{vol}', np.int16) save_volume(w_volume, f'{processed_dir}/volume_w/{vol}', np.int16) save_volume(in_volume, f'{processed_dir}/volume_in/{vol}', np.int16) save_volume(s_label, f'{processed_dir}/label/{vol}', np.int16) print('FINISHED.')
def test_spatial_axes_check(): for fname in MINC_3DS + OTHER_IMGS: img = nib.load(pjoin(DATA_DIR, fname)) s_img = smooth_image(img, 0) assert_array_equal(img.dataobj, s_img.dataobj) out = resample_from_to(img, img, mode='nearest') assert_almost_equal(img.dataobj, out.dataobj) if len(img.shape) > 3: continue # Resample to output does not raise an error out = resample_to_output(img, voxel_sizes(img.affine)) for fname in MINC_4DS: img = nib.load(pjoin(DATA_DIR, fname)) with pytest.raises(ValueError): smooth_image(img, 0) with pytest.raises(ValueError): resample_from_to(img, img, mode='nearest') with pytest.raises(ValueError): resample_to_output(img, voxel_sizes(img.affine))
def loadMPRAGE_nii(t1_loadPath, t1_brainMaskPath, isotropic_resample=False, lwr_thresh=1, upr_thresh=99): print('Loading pre-processed data') # Load data t1_nii = nib.load(t1_loadPath) brainMask = nib.load(t1_brainMaskPath) if isotropic_resample: t1_nii = resample_to_output(t1_nii, 1.0) brainMask = resample_to_output(brainMask, 1.0) t1_nii = t1_nii.get_data() brainMask = brainMask.get_data() t1_nii = t1_nii * brainMask t1_nii = np.abs(t1_nii) t1_nii = contrastStretching(t1_nii.astype('float64'), brainMask, lwr_thresh, upr_thresh) return t1_nii, brainMask
def test_load_spacingd(self, filename): data = {'image': filename} data_dict = LoadNiftid(keys='image')(data) data_dict = AddChanneld(keys='image')(data_dict) res_dict = Spacingd(keys='image', pixdim=(1, 2, 3), diagonal=True, mode='constant')(data_dict) np.testing.assert_allclose(data_dict['image.affine'], res_dict['image.original_affine']) anat = nibabel.Nifti1Image(data_dict['image'][0], data_dict['image.affine']) ref = resample_to_output(anat, (1, 2, 3)) np.testing.assert_allclose(res_dict['image.affine'], ref.affine) np.testing.assert_allclose(res_dict['image'].shape[1:], ref.shape) np.testing.assert_allclose(ref.get_fdata(), res_dict['image'][0])
def _plot_template(ax, style='filled', template='MNI152NLin2009cAsym', templatecolor='lightgray', alpha=0.2, voxsize=None, azim=0, elev=0, surface_detection=None, surface_resolution=2, edgethreshold=0.8, hemisphere='both'): if isinstance(template, str): if not os.path.exists(template): if surface_detection is None and style == 'surface': surface_detection = _get_surface_level_for_template(template) tf_kwargs = {} # Add kwargs to specify specific templates if 'MNI152' in template or 'OASIS' in template: tf_kwargs = { 'suffix': 'T1w', 'resolution': 1, } if 'WHS' in template: tf_kwargs = { 'resolution': 1, } template = tf.get(template=template, desc='brain', extension='.nii.gz', **tf_kwargs) # If multiple templates still remain, take the first # This may lead to suboptimal performence for some templates if isinstance(template, list): template = template[0] img = nib.load(template) elif isinstance(template, (nib.Nifti1Image, nib.Nifti2Image)): img = template if voxsize is not None: img = resample_to_output(img, [voxsize] * 3) data = img.get_fdata() data = _select_single_hemisphere_template(data, hemisphere) if style == 'filled': _plot_template_style_filled(ax, data, alpha, templatecolor) elif style == 'cloudy': _plot_template_style_cloudy(ax, data, azim, elev, edgethreshold, templatecolor, alpha) elif style == 'surface': _plot_template_style_surface(ax, data, alpha, template, templatecolor, surface_resolution, surface_detection) return img.affine
def advanced_crop_exclude_background(data, crop_mode, spacing, brain_mask_filename): brain_mask_ni = nib.load(brain_mask_filename) resampled_brain = resample_to_output(brain_mask_ni, spacing, order=0) brain_mask = resampled_brain.get_data().astype('uint8') original_data = np.copy(data) regions = regionprops(brain_mask) min_row, min_col, min_depth, max_row, max_col, max_depth = regions[0].bbox if crop_mode == 'brain_mask': original_data[brain_mask == 0] = 0 cropped_data = original_data[min_row:max_row, min_col:max_col, min_depth:max_depth] bbox = [min_row, min_col, min_depth, max_row, max_col, max_depth] return cropped_data, bbox
def apply_resample( tensor: torch.Tensor, affine: np.ndarray, target_spacing: Tuple[float, float, float], interpolation_order: int, ) -> Tuple[torch.Tensor, np.ndarray]: array = tensor.numpy()[0] nii = resample_to_output( nib.Nifti1Image(array, affine), voxel_sizes=target_spacing, order=interpolation_order, ) tensor = torch.from_numpy(nii.get_fdata(dtype=np.float32)) tensor = tensor.unsqueeze(dim=0) return tensor, nii.affine
def test_spatial_axes_check(): for fname in MINC_3DS + OTHER_IMGS: img = nib.load(pjoin(DATA_DIR, fname)) s_img = smooth_image(img, 0) assert_array_equal(img.dataobj, s_img.dataobj) out = resample_from_to(img, img, mode='nearest') assert_almost_equal(img.dataobj, out.dataobj) if len(img.shape) > 3: continue # Resample to output does not raise an error out = resample_to_output(img, voxel_sizes(img.affine)) for fname in MINC_4DS: img = nib.load(pjoin(DATA_DIR, fname)) assert_raises(ValueError, smooth_image, img, 0) assert_raises(ValueError, resample_from_to, img, img, mode='nearest') assert_raises(ValueError, resample_to_output, img, voxel_sizes(img.affine))
def load_medical_image(path, crop_size=(0, 0, 0), crop=(0, 0, 0), type=None, normalization="mean", resample=None, viz3d=False, to_canonical=False, random_rotate3D=None, rescale=None): img_nii = nib.load(path) # Medical img proccesing pipiline functions here if to_canonical: img_nii = nib.as_closest_canonical(img_nii) if resample is not None: img_nii = resample_to_output(img_nii, voxel_sizes=resample) img_np = np.squeeze(img_nii.get_fdata(dtype=np.float32)) if viz3d: return torch.from_numpy(img_np) # Numpy-based transformations/augmentations here if rescale is not None: rescale_data_volume(img_np, rescale) if random_rotate3D is not None: img_np = random_rotate3D(img_np, -random_rotate3D, random_rotate3D) if crop_size[0] != 0: slices_crop, w_crop, h_crop = crop img_np = img_np[slices_crop:slices_crop + crop_size[0], w_crop:w_crop + crop_size[1], h_crop:h_crop + crop_size[2]] # Tensor proccesing here img_tensor = torch.from_numpy(img_np) # slice , width, height # print('final tensor shape', img_tensor.shape) if type != "label": img_tensor = normalize_intensity(img_tensor, normalization=normalization) return img_tensor
def test_load_spacingd(self, filename): data_dict = self.load_image(filename) t = time.time() res_dict = Spacingd(keys="image", pixdim=(1, 0.2, 1), diagonal=True, padding_mode="zeros")(data_dict) t1 = time.time() print(f"time monai: {t1 - t}") anat = nibabel.Nifti1Image(np.asarray(data_dict["image"][0]), data_dict["image"].meta["original_affine"]) ref = resample_to_output(anat, (1, 0.2, 1), order=1) t2 = time.time() print(f"time scipy: {t2 - t1}") self.assertTrue(t2 >= t1) np.testing.assert_allclose(res_dict["image"].affine, ref.affine) np.testing.assert_allclose(res_dict["image"].shape[1:], ref.shape) np.testing.assert_allclose(ref.get_fdata(), res_dict["image"][0], atol=0.05)
def run_pre_processing(filename, pre_processing_parameters, storage_prefix, brain_mask_filename): nib_volume = load_nifti_volume(filename) new_spacing = pre_processing_parameters.output_spacing if pre_processing_parameters.output_spacing == None: tmp = np.min(nib_volume.header.get_zooms()) new_spacing = [tmp, tmp, tmp] library = pre_processing_parameters.preprocessing_library if library == 'nibabel': resampled_volume = resample_to_output(nib_volume, new_spacing, order=1) data = resampled_volume.get_data().astype('float32') elif library == 'dipy': data, aff = reslice(nib_volume.get_data(), nib_volume.affine, nib_volume.header.get_zooms(), new_zooms=new_spacing) resampled_volume = nib.Nifti1Image(data, affine=aff) crop_bbox = None data = intensity_normalization(volume=data, parameters=pre_processing_parameters) # Exclude background if pre_processing_parameters.crop_background is not None: data, crop_bbox = crop_MR_background( data, parameters=pre_processing_parameters, new_spacing=new_spacing, brain_mask_filename=brain_mask_filename) data = resize_volume(data, pre_processing_parameters.new_axial_size, pre_processing_parameters.slicing_plane, order=1) if pre_processing_parameters.swap_training_input: data = np.transpose(data, axes=(1, 0, 2)) return nib_volume, resampled_volume, data, crop_bbox
def load_medical_image(path, crop_size=(0, 0, 0), crop=(0, 0, 0), type=None, normalization="mean", resample=None, viz3d=False, to_canonical=False, rescale=None): img_nii = nib.load(path) # Medical img proccesing pipiline functions here if to_canonical: img_nii = nib.as_closest_canonical(img_nii) if resample is not None: img_nii = resample_to_output(img_nii, voxel_sizes=resample) img_np = np.squeeze(img_nii.get_fdata(dtype=np.float32)) if viz3d: return torch.from_numpy(img_np) # Numpy-based transformations/augmentations here if rescale is not None: rescale_data_volume(img_np, rescale) dim1, dim2, dim3 = crop_size if dim1 != 0: img_np = crop_img(img_np, crop_size, crop) # Tensor proccesing here img_tensor = torch.from_numpy(img_np) if type != "label": img_tensor = normalize_intensity(img_tensor, normalization=normalization) return img_tensor
def test_load_spacingd(self, filename): data = {"image": filename} data_dict = LoadNiftid(keys="image")(data) data_dict = AddChanneld(keys="image")(data_dict) t = time.time() res_dict = Spacingd(keys="image", pixdim=(1, 0.2, 1), diagonal=True, mode="zeros")(data_dict) t1 = time.time() print(f"time monai: {t1 - t}") anat = nibabel.Nifti1Image(data_dict["image"][0], data_dict["image_meta"]["original_affine"]) ref = resample_to_output(anat, (1, 0.2, 1), order=1) t2 = time.time() print(f"time scipy: {t2 - t1}") self.assertTrue(t2 >= t1) np.testing.assert_allclose(res_dict["image_meta"]["affine"], ref.affine) np.testing.assert_allclose(res_dict["image"].shape[1:], ref.shape) np.testing.assert_allclose(ref.get_fdata(), res_dict["image"][0], atol=0.05)
def process(self, element): key, dir_prefix = element fs = beam.io.gcsio.GcsIO() gcs_path = os.path.join(self._gcs_bucket, dir_prefix) files = fs.list_prefix(gcs_path) dicom_paths = [fname for fname in files if '.dcm' in fname] dicom_list = [ pydicom.dcmread(fs.open(path, 'rb'), defer_size=None, stop_before_pixels=False, force=False) for path in dicom_paths ] try: result = dicom_array_to_nifti(dicom_list, None, False)['NII'] except ConversionValidationError: dicom2nifti.settings.disable_validate_sliceincrement() result = dicom_array_to_nifti(dicom_list, None, False)['NII'] dicom2nifti.settings.enable_validate_sliceincrement() series_id = dicom_list[0].SeriesInstanceUID del dicom_list gc.collect() resampled = processing.resample_to_output(result) del result qoffset = list(resampled.header.get_sform()[:3, -1]) npy_arr = np.ascontiguousarray( np.rot90(np.swapaxes( resampled.get_fdata(dtype=np.float32).astype(np.int16), 0, 2), k=2, axes=(0, 2))) del resampled gc.collect() path = os.path.join(self._gcs_save_dir, key + '.npy') self.save_array(path, npy_arr) del npy_arr gc.collect() yield key, series_id, qoffset, path
def test_resample_to_output(): # Test routine to sample iamges to output space # Image aligned to output axes - no-op data = np.arange(24).reshape((2, 3, 4)) img = Nifti1Image(data, np.eye(4)) # Check default resampling img2 = resample_to_output(img) assert_array_equal(img2.shape, (2, 3, 4)) assert_array_equal(img2.affine, np.eye(4)) assert_array_equal(img2.dataobj, data) # Check resampling with different voxel size specifications for vox_sizes in (None, 1, [1, 1, 1]): img2 = resample_to_output(img, vox_sizes) assert_array_equal(img2.shape, (2, 3, 4)) assert_array_equal(img2.affine, np.eye(4)) assert_array_equal(img2.dataobj, data) img2 = resample_to_output(img, vox_sizes) # Check 2D works img_2d = Nifti1Image(data[0], np.eye(4)) for vox_sizes in (None, 1, (1, 1), (1, 1, 1)): img3 = resample_to_output(img_2d, vox_sizes) assert_array_equal(img3.shape, (3, 4, 1)) assert_array_equal(img3.affine, np.eye(4)) assert_array_equal(img3.dataobj, data[0][..., None]) # Even 1D img_1d = Nifti1Image(data[0, 0], np.eye(4)) img3 = resample_to_output(img_1d) assert_array_equal(img3.shape, (4, 1, 1)) assert_array_equal(img3.affine, np.eye(4)) assert_array_equal(img3.dataobj, data[0, 0][..., None, None]) # But 4D does not img_4d = Nifti1Image(data.reshape(2, 3, 2, 2), np.eye(4)) with pytest.raises(ValueError): resample_to_output(img_4d) # Run vox2vox_out tests, checking output shape, coordinate transform for in_shape, in_aff, vox, out_shape, out_aff in get_outspace_params(): # Allow for expansion of image shape from < 3D in_n_dim = len(in_shape) if in_n_dim < 3: in_shape = in_shape + (1,) * (3 - in_n_dim) if not vox is None: vox = vox + (1,) * (3 - in_n_dim) assert len(out_shape) == in_n_dim out_shape = out_shape + (1,) * (3 - in_n_dim) img = Nifti1Image(np.ones(in_shape), in_aff) out_img = resample_to_output(img, vox) assert_all_in(in_shape, in_aff, out_img.shape, out_img.affine) assert out_img.shape == out_shape assert_almost_equal(out_img.affine, out_aff) # Check data is as expected with some transforms # Flip first axis out_img = resample_to_output(Nifti1Image(data, np.diag([-1, 1, 1, 1]))) assert_array_equal(out_img.dataobj, np.flipud(data)) # Subsample voxels out_img = resample_to_output(Nifti1Image(data, np.diag([4, 5, 6, 1]))) exp_out = spnd.affine_transform(data, [1/4, 1/5, 1/6], output_shape = (5, 11, 19)) assert_array_equal(out_img.dataobj, exp_out) # Unsubsample with voxel sizes out_img = resample_to_output(Nifti1Image(data, np.diag([4, 5, 6, 1])), [4, 5, 6]) assert_array_equal(out_img.dataobj, data) # A rotation to test nearest, order, cval rot_3 = from_matvec(euler2mat(np.pi / 4), [0, 0, 0]) rot_3_img = Nifti1Image(data, rot_3) out_img = resample_to_output(rot_3_img) exp_shape = (4, 4, 4) assert out_img.shape == exp_shape exp_aff = np.array([[1, 0, 0, -2 * np.cos(np.pi / 4)], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) assert_almost_equal(out_img.affine, exp_aff) rzs, trans = to_matvec(np.dot(npl.inv(rot_3), exp_aff)) exp_out = spnd.affine_transform(data, rzs, trans, exp_shape) assert_almost_equal(out_img.dataobj, exp_out) # Order assert_almost_equal( resample_to_output(rot_3_img, order=0).dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, order=0)) # Cval assert_almost_equal( resample_to_output(rot_3_img, cval=99).dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, cval=99)) # Mode assert_almost_equal( resample_to_output(rot_3_img, mode='nearest').dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, mode='nearest')) # out_class img_ni1 = Nifti2Image(data, np.eye(4)) img_ni2 = Nifti2Image(data, np.eye(4)) # Default is Nifti1Image assert resample_to_output(img_ni2).__class__ == Nifti1Image # Can be overriden assert resample_to_output(img_ni1, out_class=Nifti2Image).__class__ == Nifti2Image # None specifies out_class from input assert resample_to_output(img_ni2, out_class=None).__class__ == Nifti2Image
def test_resample_to_output(): # Test routine to sample iamges to output space # Image aligned to output axes - no-op data = np.arange(24).reshape((2, 3, 4)) img = Nifti1Image(data, np.eye(4)) # Check default resampling img2 = resample_to_output(img) assert_array_equal(img2.shape, (2, 3, 4)) assert_array_equal(img2.affine, np.eye(4)) assert_array_equal(img2.dataobj, data) # Check resampling with different voxel size specifications for vox_sizes in (None, 1, [1, 1, 1]): img2 = resample_to_output(img, vox_sizes) assert_array_equal(img2.shape, (2, 3, 4)) assert_array_equal(img2.affine, np.eye(4)) assert_array_equal(img2.dataobj, data) img2 = resample_to_output(img, vox_sizes) # Check 2D works img_2d = Nifti1Image(data[0], np.eye(4)) for vox_sizes in (None, 1, (1, 1), (1, 1, 1)): img3 = resample_to_output(img_2d, vox_sizes) assert_array_equal(img3.shape, (3, 4, 1)) assert_array_equal(img3.affine, np.eye(4)) assert_array_equal(img3.dataobj, data[0][..., None]) # Even 1D img_1d = Nifti1Image(data[0, 0], np.eye(4)) img3 = resample_to_output(img_1d) assert_array_equal(img3.shape, (4, 1, 1)) assert_array_equal(img3.affine, np.eye(4)) assert_array_equal(img3.dataobj, data[0, 0][..., None, None]) # But 4D does not img_4d = Nifti1Image(data.reshape(2, 3, 2, 2), np.eye(4)) assert_raises(ValueError, resample_to_output, img_4d) # Run vox2vox_out tests, checking output shape, coordinate transform for in_shape, in_aff, vox, out_shape, out_aff in get_outspace_params(): # Allow for expansion of image shape from < 3D in_n_dim = len(in_shape) if in_n_dim < 3: in_shape = in_shape + (1,) * (3 - in_n_dim) if not vox is None: vox = vox + (1,) * (3 - in_n_dim) assert len(out_shape) == in_n_dim out_shape = out_shape + (1,) * (3 - in_n_dim) img = Nifti1Image(np.ones(in_shape), in_aff) out_img = resample_to_output(img, vox) assert_all_in(in_shape, in_aff, out_img.shape, out_img.affine) assert_equal(out_img.shape, out_shape) assert_almost_equal(out_img.affine, out_aff) # Check data is as expected with some transforms # Flip first axis out_img = resample_to_output(Nifti1Image(data, np.diag([-1, 1, 1, 1]))) assert_array_equal(out_img.dataobj, np.flipud(data)) # Subsample voxels out_img = resample_to_output(Nifti1Image(data, np.diag([4, 5, 6, 1]))) exp_out = spnd.affine_transform(data, [1/4, 1/5, 1/6], output_shape = (5, 11, 19)) assert_array_equal(out_img.dataobj, exp_out) # Unsubsample with voxel sizes out_img = resample_to_output(Nifti1Image(data, np.diag([4, 5, 6, 1])), [4, 5, 6]) assert_array_equal(out_img.dataobj, data) # A rotation to test nearest, order, cval rot_3 = from_matvec(euler2mat(np.pi / 4), [0, 0, 0]) rot_3_img = Nifti1Image(data, rot_3) out_img = resample_to_output(rot_3_img) exp_shape = (4, 4, 4) assert_equal(out_img.shape, exp_shape) exp_aff = np.array([[1, 0, 0, -2 * np.cos(np.pi / 4)], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) assert_almost_equal(out_img.affine, exp_aff) rzs, trans = to_matvec(np.dot(npl.inv(rot_3), exp_aff)) exp_out = spnd.affine_transform(data, rzs, trans, exp_shape) assert_almost_equal(out_img.dataobj, exp_out) # Order assert_almost_equal( resample_to_output(rot_3_img, order=0).dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, order=0)) # Cval assert_almost_equal( resample_to_output(rot_3_img, cval=99).dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, cval=99)) # Mode assert_almost_equal( resample_to_output(rot_3_img, mode='nearest').dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, mode='nearest')) # out_class img_ni1 = Nifti2Image(data, np.eye(4)) img_ni2 = Nifti2Image(data, np.eye(4)) # Default is Nifti1Image assert_equal( resample_to_output(img_ni2).__class__, Nifti1Image) # Can be overriden assert_equal( resample_to_output(img_ni1, out_class=Nifti2Image).__class__, Nifti2Image) # None specifies out_class from input assert_equal( resample_to_output(img_ni2, out_class=None).__class__, Nifti2Image)
def process(self, element): key, series_id, nii = element resampled = processing.resample_to_output(nii) qoffset = list(resampled.header.get_sform()[:3, -1]) yield key, series_id, qoffset, resampled
def _run_interface(self, runtime): import os import numpy as np import nibabel as nb from nibabel import processing subject_id = os.path.basename( self.inputs.input_ref_EPI).split('_ses-')[0] session = os.path.basename( self.inputs.input_ref_EPI).split('_ses-')[1][0] run = os.path.basename(self.inputs.input_ref_EPI).split('_run-')[1][0] filename_template = '%s_ses-%s_run-%s' % (subject_id, session, run) if self.inputs.bias_cor_script == 'Default': import rabies dir_path = os.path.dirname(os.path.realpath(rabies.__file__)) bias_cor_script_path = dir_path + '/shell_scripts/iter_bias_cor.sh' else: ''' For user-provided bias correction command. ''' if os.path.isfile(self.inputs.bias_cor_script): bias_cor_script_path = self.inputs.bias_cor_script else: msg = 'THE BIASCOR PATH %s DOES NOT EXISTS' % self.inputs.bias_cor_script raise ValueError(msg) if self.inputs.reg_script == 'Rigid': import rabies dir_path = os.path.dirname(os.path.realpath(rabies.__file__)) reg_script_path = dir_path + '/shell_scripts/Rigid_registration.sh' else: ''' For user-provided reg script. ''' if os.path.isfile(self.inputs.reg_script): reg_script_path = self.inputs.reg_script else: msg = 'THE BIASCOR PATH %s DOES NOT EXISTS' % self.inputs.reg_script raise ValueError(msg) cwd = os.getcwd() warped_image = '%s/%s_output_warped_image.nii.gz' % (cwd, filename_template) resampled_mask = '%s/%s_resampled_mask.nii.gz' % (cwd, filename_template) biascor_EPI = '%s/%s_bias_cor.nii.gz' % (cwd, filename_template) #resample to isotropic resolution based on lowest dimension dim = nb.load(self.inputs.input_ref_EPI).header.get_zooms() low_dim = np.asarray(dim).min() processing.resample_to_output(nb.load(self.inputs.input_ref_EPI), voxel_sizes=(low_dim, low_dim, low_dim), order=4).to_filename(cwd + '/resampled.nii.gz') os.system( 'bash %s %s %s %s %s %s' % (bias_cor_script_path, cwd + '/resampled.nii.gz', self.inputs.anat, self.inputs.anat_mask, filename_template, reg_script_path)) #resample to anatomical image resolution dim = nb.load(self.inputs.anat).header.get_zooms() low_dim = np.asarray(dim).min() processing.resample_to_output(nb.load(cwd + '/iter_corrected.nii.gz'), voxel_sizes=(low_dim, low_dim, low_dim), order=4).to_filename(biascor_EPI) setattr(self, 'corrected_EPI', biascor_EPI) setattr(self, 'warped_EPI', warped_image) setattr(self, 'resampled_mask', resampled_mask) return runtime
for Path in [AMBMC_template_path] + AMBMC_annotation_path_list: print(Path) input_image = nib.load(Path) input_image.set_qform(correct_qform, 1) print(nib.aff2axcodes(input_image.affine)) output_image = nib.as_closest_canonical(input_image) print(nib.aff2axcodes(output_image.affine)) output_path = Path.split('.')[0] + '_reoriented.nii.gz' nib.save(output_image, Path.split('.')[0] + '_reoriented.nii.gz') output_resampled_path = Path.split('.')[0] + '_50_reoriented.nii.gz' output_resampled_image = nib_processing.resample_to_output( output_image, voxel_size) nib.save(output_resampled_image, output_resampled_path) AMBMC_path_list.append(output_resampled_path) AMBMC_template_path = AMBMC_path_list[0] # Load AMBMC_template_image = nib.load(AMBMC_template_path) print(nib.aff2axcodes(AMBMC_template_image.affine)) AMBMC_template = AMBMC_template_image.get_fdata() # AMBMC zero padding AMBMC_template_zeropadded, crop_index = zeroPadImage(AMBMC_template, AMBMC_template, 0.1) AMBMC_template_zeropadded_image = nib.Nifti1Image(AMBMC_template_zeropadded, AMBMC_template_image.affine)
def voxels_for_comparison(img1_path, img2_path, mask_path='/usr/share/mouse-brain-templates/dsurqec_200micron_mask.nii', resample_voxel_size=[], replace_nan_with=0., ): """Return (optionally resampled) voxelwise values from two images, constrained to a mask region and voxels which are not NaN in any of the images. Parameters ---------- img1_path : str Path to NIfTI file. img2_path : str Path to NIfTI file co-registered with `img1_path`. mask_path : str Path to NIfTI file co-registered with `mask_path`. resample_voxel_site : list, optional Length-3 list with the desired voxel dimensions. replace_nan_with : float, optional Value with which to replace NaN values in `img1_path` and `img2_path`. This is only an internal operation, and should in no way modify the output, since voxels with NaN values in either `img1_path` and `img2_path` will always be masked. """ import numpy as np from scipy import stats from nibabel import processing img1_path = path.abspath(path.expanduser(img1_path)) img2_path = path.abspath(path.expanduser(img2_path)) mask_path = path.abspath(path.expanduser(mask_path)) img1 = nib.load(img1_path) img2 = nib.load(img2_path) mask = nib.load(mask_path) img1_data = img1.get_data() img2_data = img2.get_data() mask_data = mask.get_data() # Query NaN voxels in input images img1_nans = np.isnan(img1_data) img2_nans = np.isnan(img2_data) mask_data = np.array(mask_data, dtype=bool) mask_data = np.all([~img1_nans ,~img2_nans, mask_data], axis=0) if resample_voxel_size: # Set NaN values to numeric (this is just to permit resampling, as all NaN voxels will already be masked for the actual correlation measurement). img1_data[img1_nans] = replace_nan_with img2_data[img2_nans] = replace_nan_with img1 = nib.Nifti1Image(img1_data, img1.affine, img1.header) img2 = nib.Nifti2Image(img2_data, img2.affine, img2.header) mask = nib.Nifti2Image(mask_data, mask.affine, mask.header) img1 = processing.resample_to_output(img1, voxel_sizes=resample_voxel_size) img2 = processing.resample_to_output(img2, voxel_sizes=resample_voxel_size) mask = processing.resample_to_output(mask, voxel_sizes=resample_voxel_size) img1_data = img1.get_data() img2_data = img2.get_data() mask_data = mask.get_data() mask_data = np.array(mask_data, dtype=bool) img1_masked = img1_data[mask_data] img2_masked = img2_data[mask_data] return img1_masked, img2_masked