def test_reconstruct_volume_from_slices(self): filename = "SRR_stacks3_TK1_lsmr_alpha0p02_itermax5.nii.gz" output = os.path.join(self.dir_output, filename) dir_reference = os.path.join(self.dir_data, "reconstruct_volume_from_slices") dir_input_mc = os.path.join(self.dir_data, "reconstruct_volume_from_slices", "motion_correction") path_to_reference = os.path.join(dir_reference, filename) iter_max = 5 alpha = 0.02 intensity_correction = 1 cmd_args = [] cmd_args.append("--filenames %s" % " ".join(self.filenames)) cmd_args.append("--dir-input-mc %s" % dir_input_mc) cmd_args.append("--output %s" % output) cmd_args.append("--iter-max %d" % iter_max) cmd_args.append("--intensity-correction %d" % intensity_correction) cmd_args.append("--alpha %f" % alpha) cmd_args.append("--reconstruction-space %s" % path_to_reference) cmd = "niftymic_reconstruct_volume_from_slices %s" % ( " ").join(cmd_args) self.assertEqual(ph.execute_command(cmd), 0) # Check whether identical reconstruction has been created reconstruction_sitk = sitkh.read_nifti_image_sitk(output) reference_sitk = sitkh.read_nifti_image_sitk(path_to_reference) difference_sitk = reconstruction_sitk - reference_sitk error = np.linalg.norm(sitk.GetArrayFromImage(difference_sitk)) self.assertAlmostEqual(error, 0, places=self.precision)
def _run(self): super(RegF3D, self)._run() nreg = nipype.interfaces.niftyreg.RegF3D() nreg.inputs.ref_file = self._fixed_str nreg.inputs.flo_file = self._moving_str nreg.inputs.res_file = self._warped_moving_str nreg.inputs.cpp_file = self._registration_control_point_grid_str nreg.inputs.omp_core_val = self._omp nreg.inputs.args = self._options if self._fixed_sitk_mask is not None: nreg.inputs.rmask_file = self._fixed_mask_str if self._moving_sitk_mask is not None: nreg.inputs.fmask_file = self._moving_mask_str if self._transform_init is not None: nreg.inputs.aff_file = self._transform_init_str # Execute registration if self._verbose: ph.print_execution(nreg.cmdline) nreg.run() # Read warped image self._warped_moving_sitk = sitkh.read_nifti_image_sitk( self._warped_moving_str) # Has not been used. Thus, not tested! self._registration_transform_sitk = sitkh.read_nifti_image_sitk( self._registration_control_point_grid_str)
def from_filename(cls, file_path, slice_number, slice_thickness, file_path_mask=None, verbose=False, ): slice = cls() if not ph.file_exists(file_path): raise exceptions.FileNotExistent(file_path) slice._dir_input = os.path.dirname(file_path) slice._filename = os.path.basename(file_path).split(".")[0] slice._slice_number = slice_number slice._slice_thickness = slice_thickness # Append stacks as SimpleITK and ITK Image objects slice.sitk = sitkh.read_nifti_image_sitk(file_path, sitk.sitkFloat64) slice.itk = sitkh.get_itk_from_sitk_image(slice.sitk) # Append masks (if provided) if file_path_mask is None: slice.sitk_mask = slice._generate_identity_mask() if verbose: ph.print_info( "Identity mask created for '%s'." % (file_path)) else: if not ph.file_exists(file_path_mask): raise exceptions.FileNotExistent(file_path_mask) slice.sitk_mask = sitkh.read_nifti_image_sitk( file_path_mask, sitk.sitkUInt8) try: # ensure mask occupies the same physical space slice.sitk_mask.CopyInformation(slice.sitk) except RuntimeError as e: raise IOError( "Given image and its mask do not occupy the same space: %s" % e.message) slice.itk_mask = sitkh.get_itk_from_sitk_image(slice.sitk_mask) # Store current affine transform of image slice._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image( slice.sitk) # Prepare history of affine transforms, i.e. encoded spatial # position+orientation of slice, and motion estimates of slice # obtained in the course of the registration/reconstruction process slice._history_affine_transforms = [] slice._history_affine_transforms.append(slice._affine_transform_sitk) slice._history_motion_corrections = [] slice._history_motion_corrections.append(sitk.Euler3DTransform()) return slice
def test_estimate_motion(self): filename = "SRR_reference.nii.gz" output = os.path.join(self.dir_output, filename) dir_reference = os.path.join(self.dir_data, "estimate_motion") dir_reference_mc = os.path.join(dir_reference, "motion_correction") path_to_reference = os.path.join(dir_reference, filename) path_to_reference_mask = ph.append_to_filename( os.path.join(dir_reference, filename), self.suffix_mask) two_step_cycles = 1 iter_max = 5 exe = os.path.abspath(rsfmri_estimate_motion.__file__) cmd_args = ["python %s" % exe] cmd_args.append("--filename %s" % self.filename) cmd_args.append("--filename-mask %s" % ph.append_to_filename( self.filename, self.suffix_mask)) cmd_args.append("--dir-output %s" % self.dir_output) cmd_args.append("--two-step-cycles %s" % two_step_cycles) cmd_args.append("--iter-max %d" % iter_max) cmd = (" ").join(cmd_args) self.assertEqual(ph.execute_command(cmd), 0) # Check SRR volume res_sitk = sitkh.read_nifti_image_sitk(output) ref_sitk = sitkh.read_nifti_image_sitk(path_to_reference) diff_sitk = res_sitk - ref_sitk error = np.linalg.norm(sitk.GetArrayFromImage(diff_sitk)) self.assertAlmostEqual(error, 0, places=self.precision) # Check SRR mask volume res_sitk = sitkh.read_nifti_image_sitk( ph.append_to_filename(output, self.suffix_mask)) ref_sitk = sitkh.read_nifti_image_sitk(path_to_reference_mask) diff_sitk = res_sitk - ref_sitk error = np.linalg.norm(sitk.GetArrayFromImage(diff_sitk)) self.assertAlmostEqual(error, 0, places=self.precision) # Check transforms pattern = REGEX_FILENAMES + "[.]tfm" p = re.compile(pattern) dir_res_mc = os.path.join(self.dir_output, "motion_correction") trafos_res = sorted( [os.path.join(dir_res_mc, t) for t in os.listdir(dir_res_mc) if p.match(t)]) trafos_ref = sorted( [os.path.join(dir_reference_mc, t) for t in os.listdir(dir_reference_mc) if p.match(t)]) self.assertEqual(len(trafos_res), len(trafos_ref)) for i in range(len(trafos_ref)): nda_res = sitkh.read_transform_sitk(trafos_res[i]).GetParameters() nda_ref = sitkh.read_transform_sitk(trafos_ref[i]).GetParameters() nda_diff = np.linalg.norm(np.array(nda_res) - nda_ref) self.assertAlmostEqual(nda_diff, 0, places=self.precision)
def from_mask(cls, file_path_mask): template_stack_estimator = cls() mask_sitk = sitkh.read_nifti_image_sitk(file_path_mask, sitk.sitkUInt8) mask_nda = sitk.GetArrayFromImage(mask_sitk) # get largest connected region (if more than one connected region) mask_nda = TemplateStackEstimator.get_largest_connected_region_mask( mask_nda) spacing = np.array(mask_sitk.GetSpacing()) volume = len(np.where(mask_nda > 0)[0]) * spacing.prod() # Read in template info path_to_template_info = os.path.join(DIR_TEMPLATES, TEMPLATES_INFO) with open(path_to_template_info) as json_file: dic = json.load(json_file) # Get gestational ages as list of integers gestational_ages = sorted([int(gw) for gw in dic.keys()]) # Get matching gestational age template_volumes = np.array( [dic[str(k)]["volume_mask"] for k in gestational_ages]) index = np.argmin(np.abs(template_volumes - volume)) template_stack_estimator._estimated_gw = int(gestational_ages[index]) template_stack_estimator._template_path = os.path.join( DIR_TEMPLATES, dic[str(gestational_ages[index])]["image"]) return template_stack_estimator
def get_deformed_image_sitk(self, fixed_sitk, moving_sitk, interpolation_order): # REMARK: # Not possible to write registration transform that way since # some header information gets lost! Therefore, read again the one # which was the output of NiftyReg (and hope that file is not been # deleted) # Create and delete all possibly existing files in the directory # ph.create_directory(self._dir_tmp, delete_files=True) # sitkh.write_nifti_image_sitk(self.get_registration_transform_sitk(), # self._registration_control_point_grid_str) sitkh.write_nifti_image_sitk(fixed_sitk, self._fixed_str) sitkh.write_nifti_image_sitk(moving_sitk, self._moving_str) nreg = nipype.interfaces.niftyreg.RegResample() nreg.inputs.ref_file = self._fixed_str nreg.inputs.flo_file = self._moving_str nreg.inputs.trans_file = self._registration_control_point_grid_str nreg.inputs.out_file = self._warped_moving_str nreg.inputs.omp_core_val = self._omp nreg.inputs.args = "-inter " + str(interpolation_order) # Execute registration if self._verbose: ph.print_execution(nreg.cmdline) nreg.run() return sitkh.read_nifti_image_sitk(self._warped_moving_str, moving_sitk.GetPixelIDValue())
def _run(self): super(RegAladin, self)._run() nreg = nipype.interfaces.niftyreg.RegAladin() nreg.inputs.ref_file = self._fixed_str nreg.inputs.flo_file = self._moving_str nreg.inputs.res_file = self._warped_moving_str nreg.inputs.aff_file = self._registration_transform_str nreg.inputs.omp_core_val = self._omp nreg.inputs.args = self._options if self._fixed_sitk_mask is not None: nreg.inputs.rmask_file = self._fixed_mask_str if self._moving_sitk_mask is not None: nreg.inputs.fmask_file = self._moving_mask_str if self._transform_init is not None: nreg.inputs.in_aff_file = self._transform_init_str # Execute registration if self._verbose: ph.print_execution(nreg.cmdline) nreg.run() # Read warped image self._warped_moving_sitk = sitkh.read_nifti_image_sitk( self._warped_moving_str, sitk.sitkFloat64) # Convert to sitk affine transform self._registration_transform_sitk = self._convert_to_sitk_transform()
def from_masks(cls, file_paths_masks): target_stack_estimator = cls() masks_sitk = [sitkh.read_nifti_image_sitk(str(f), sitk.sitkUInt8) for f in file_paths_masks] # Compute volumes of all masks volumes = np.zeros(len(masks_sitk)) for i, mask_sitk in enumerate(masks_sitk): mask_nda = sitk.GetArrayFromImage(mask_sitk) spacing = np.array(mask_sitk.GetSpacing()) volumes[i] = np.sum(mask_nda) * spacing.prod() # find index to smallest "valid" volume, i.e. volume > q * median index = np.argmax( volumes[np.argsort(volumes)] > 0.7 * np.median(volumes)) index = np.argsort(volumes)[index] # Get index corresponding to maximum volume stack mask # index = np.argmax(volumes) # index = np.argmin(volumes) # Get index corresponding to median volume stack mask # index = np.argsort(volumes)[len(volumes)//2] target_stack_estimator._target_stack_index = index return target_stack_estimator
def _run_bet_for_brain_stripping(self, debug=0): filename_out = "image" self._dir_tmp = ph.create_directory(self._dir_tmp, delete_files=True) path_to_image = os.path.join(self._dir_tmp, filename_out + ".nii.gz") path_to_res = os.path.join(self._dir_tmp, filename_out + "_bet.nii.gz") path_to_res_mask = os.path.join(self._dir_tmp, filename_out + "_bet_mask.nii.gz") path_to_res_skull = os.path.join(self._dir_tmp, filename_out + "_bet_skull.nii.gz") sitkh.write_nifti_image_sitk(self._sitk, path_to_image) bet = nipype.interfaces.fsl.BET() bet.inputs.in_file = path_to_image bet.inputs.out_file = path_to_res options = "" if not self._compute_brain_image: options += "-n " if self._compute_brain_mask: options += "-m " if self._compute_skull_image: options += "-s " options += self._bet_options bet.inputs.args = options if debug: print(bet.cmdline) bet.run() if self._compute_brain_image: self._sitk_brain_image = sitkh.read_nifti_image_sitk( path_to_res, sitk.sitkFloat64) if self._compute_brain_mask: self._sitk_brain_mask = sitkh.read_nifti_image_sitk( path_to_res_mask, sitk.sitkUInt8) if self._compute_skull_image: self._sitk_skull_image = sitkh.read_nifti_image_sitk( path_to_res_skull)
def _compute_volume(file_path): mask_sitk = sitkh.read_nifti_image_sitk(str(file_path), sitk.sitkUInt8) # Compute mask volume mask_nda = sitk.GetArrayFromImage(mask_sitk) spacing = np.array(mask_sitk.GetSpacing()) volume = np.sum(mask_nda) * spacing.prod() return volume
def test_read_write_nifti_image_sitk(self): image_sitk = sitk.ReadImage(os.path.join( self.dir_test_data, self.filename + ".nii.gz")) foo = os.path.join(DIR_TMP, "foo.nii.gz") sitkh.write_nifti_image_sitk(image_sitk, foo) foo_sitk = sitkh.read_nifti_image_sitk(foo) nda = sitk.GetArrayFromImage(image_sitk - foo_sitk) error = np.linalg.norm(nda) self.assertAlmostEqual(error, 0, places=self.accuracy)
def from_mask(cls, file_path_mask): template_stack_estimator = cls() mask_sitk = sitkh.read_nifti_image_sitk(file_path_mask, sitk.sitkUInt8) mask_nda = sitk.GetArrayFromImage(mask_sitk) spacing = np.array(mask_sitk.GetSpacing()) volume = len(np.where(mask_nda > 0)[0]) * spacing.prod() # Read in template info path_to_template_info = os.path.join(DIR_TEMPLATES, TEMPLATES_INFO) with open(path_to_template_info) as json_file: dic = json.load(json_file) # Get gestational ages as list of integers gestational_ages = sorted([int(gw) for gw in dic.keys()]) # # Get matching gestational age # template_volumes = np.array([dic[str(k)]["volume_mask"] # for k in gestational_ages]) # index = np.argmin(np.abs(template_volumes - volume)) # # Ensure valid index after correction # index = np.max([0, index - 1]) # # index = np.min([index + 1, len(template_volumes)-1]) # # Matching gestational age/week # gw_match = str(gestational_ages[index]) # template_stack_estimator._template_path = os.path.join( # DIR_TEMPLATES, dic[gw_match]["image"]) # return template_stack_estimator # Find template which has slightly smaller mask volume for k in gestational_ages: if dic[str(k)]["volume_mask_dil"] > volume: key = str(np.max([gestational_ages[0], k - 1])) template_stack_estimator._estimated_gw = int(key) template_stack_estimator._template_path = os.path.join( DIR_TEMPLATES, dic[key]["image"]) return template_stack_estimator # Otherwise, return path to oldest template image available template_stack_estimator._estimated_gw = int(gestational_ages[-1]) template_stack_estimator._template_path = os.path.join( DIR_TEMPLATES, dic[str(gestational_ages[-1])]["image"]) return template_stack_estimator
def from_filename(cls, dir_input, filename, compute_brain_image=False, compute_brain_mask=True, compute_skull_image=False, dir_tmp=os.path.join(DIR_TMP, "BrainExtractionTool")): self = cls(compute_brain_image=compute_brain_image, compute_brain_mask=compute_brain_mask, compute_skull_image=compute_skull_image, dir_tmp=dir_tmp) self._sitk = sitkh.read_nifti_image_sitk( os.path.join(dir_input, "%s.nii.gz" % filename), sitk.sitkFloat64) return self
def test_02_brain_mask(self): path_to_reference = os.path.join(DIR_TEST, "case-studies", "fetal-brain", "brain_stripping", "axial_seg.nii.gz") brain_stripping = bs.BrainStripping.from_filename( self.dir_data, self.filename) brain_stripping.compute_brain_image(0) brain_stripping.compute_brain_mask(1) brain_stripping.compute_skull_image(0) # brain_stripping.set_bet_options("-f 0.3") brain_stripping.run() original_sitk = brain_stripping.get_input_image_sitk() res_sitk = brain_stripping.get_brain_mask_sitk() ref_sitk = sitkh.read_nifti_image_sitk(path_to_reference) diff_sitk = res_sitk - ref_sitk error = np.linalg.norm(sitk.GetArrayFromImage(diff_sitk)) self.assertAlmostEqual(error, 0, places=self.precision)
def _run(self): # Create and delete all possibly existing files in the directory ph.create_directory(self._dir_tmp, delete_files=True) sitkh.write_nifti_image_sitk(self._fixed_sitk, self._fixed_str) sitkh.write_nifti_image_sitk(self._moving_sitk, self._moving_str) flt = nipype.interfaces.fsl.FLIRT() flt.inputs.in_file = self._moving_str flt.inputs.reference = self._fixed_str flt.inputs.out_file = self._warped_moving_str flt.inputs.out_matrix_file = self._registration_transform_str flt.inputs.output_type = "NIFTI_GZ" if self._fixed_sitk_mask is not None: sitkh.write_nifti_image_sitk(self._fixed_sitk_mask, self._fixed_mask_str) flt.inputs.ref_weight = self._fixed_mask_str if self._moving_sitk_mask is not None: sitkh.write_nifti_image_sitk(self._moving_sitk_mask, self._moving_mask_str) flt.inputs.in_weight = self._moving_mask_str flt.inputs.args = self._options # Execute registration if self._verbose: ph.print_execution(flt.cmdline) flt.run() # Read warped image self._warped_moving_sitk = sitkh.read_nifti_image_sitk( self._warped_moving_str) # Convert to sitk affine transform self._registration_transform_sitk = self._convert_to_sitk_transform()
def from_filename( cls, file_path, file_path_mask=None, extract_slices=True, verbose=False, slice_thickness=None, ): stack = cls() if not ph.file_exists(file_path): raise exceptions.FileNotExistent(file_path) path_to_directory = os.path.dirname(file_path) # Strip extension from filename and remove potentially included "." filename = [ re.sub("." + ext, "", os.path.basename(file_path)) for ext in ALLOWED_EXTENSIONS if file_path.endswith(ext) ][0] # filename = filename.replace(".", "p") stack._dir = os.path.dirname(file_path) stack._filename = filename # Append stacks as SimpleITK and ITK Image objects stack.sitk = sitkh.read_nifti_image_sitk(file_path, sitk.sitkFloat64) stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk) # Set slice thickness of acquisition if slice_thickness is None: stack._slice_thickness = stack.sitk.GetSpacing()[-1] else: stack._slice_thickness = slice_thickness # Append masks (either provided or binary mask) if file_path_mask is None: stack.sitk_mask = stack._generate_identity_mask() if verbose: ph.print_info("Identity mask created for '%s'." % (file_path)) else: if not ph.file_exists(file_path_mask): raise exceptions.FileNotExistent(file_path_mask) stack.sitk_mask = sitkh.read_nifti_image_sitk( file_path_mask, sitk.sitkUInt8) try: # ensure masks occupy same physical space stack.sitk_mask.CopyInformation(stack.sitk) except RuntimeError as e: raise IOError( "Given image and its mask do not occupy the same space: %s" % e.message) stack._is_unity_mask = False # Append itk object stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask) # Store current affine transform of image stack._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image( stack.sitk) # Prepare history of affine transforms, i.e. encoded spatial # position+orientation of stack, and motion estimates of stack # obtained in the course of the registration/reconstruction process stack._history_affine_transforms = [] stack._history_affine_transforms.append(stack._affine_transform_sitk) stack._history_motion_corrections = [] stack._history_motion_corrections.append(sitk.Euler3DTransform()) # Extract all slices and their masks from the stack and store them if extract_slices: dimenson = stack.sitk.GetDimension() if dimenson == 3: stack._N_slices = stack.sitk.GetSize()[-1] stack._slices = stack._extract_slices( slice_thickness=stack.get_slice_thickness()) elif dimenson == 2: stack._N_slices = 1 stack._slices = [stack.sitk[:, :]] else: stack._N_slices = 0 stack._slices = None if verbose: ph.print_info( "Stack (image + mask) associated to '%s' successfully read." % (file_path)) return stack
def from_slice_filenames( cls, dir_input, prefix_stack, suffix_mask=None, dic_slice_filenames=None, prefix_slice="_slice", slice_thickness=None, ): stack = cls() if dir_input[-1] is not "/": dir_input += "/" stack._dir = dir_input stack._filename = prefix_stack # Get 3D images stack.sitk = sitkh.read_nifti_image_sitk( dir_input + prefix_stack + ".nii.gz", sitk.sitkFloat64) stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk) # Store current affine transform of image stack._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image( stack.sitk) # Prepare history of affine transforms, i.e. encoded spatial # position+orientation of stack, and motion estimates of stack # obtained in the course of the registration/reconstruction process stack._history_affine_transforms = [] stack._history_affine_transforms.append(stack._affine_transform_sitk) stack._history_motion_corrections = [] stack._history_motion_corrections.append(sitk.Euler3DTransform()) # Set slice thickness of acquisition if slice_thickness is None: stack._slice_thickness = float(stack.sitk.GetSpacing()[-1]) else: stack._slice_thickness = float(slice_thickness) # Append masks (either provided or binary mask) if suffix_mask is not None and \ os.path.isfile(dir_input + prefix_stack + suffix_mask + ".nii.gz"): stack.sitk_mask = sitkh.read_nifti_image_sitk( dir_input + prefix_stack + suffix_mask + ".nii.gz", sitk.sitkUInt8) stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask) stack._is_unity_mask = False else: stack.sitk_mask = stack._generate_identity_mask() stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask) stack._is_unity_mask = True # Get slices if dic_slice_filenames is None: stack._N_slices = stack.sitk.GetDepth() stack._slices = [None] * stack._N_slices # Append slices as Slice objects for i in range(0, stack._N_slices): path_to_slice = os.path.join( dir_input, prefix_stack + prefix_slice + str(i) + ".nii.gz") path_to_slice_mask = os.path.join( dir_input, prefix_stack + prefix_slice + str(i) + suffix_mask + ".nii.gz") if ph.file_exists(path_to_slice_mask): stack._slices[i] = sl.Slice.from_filename( file_path=path_to_slice, slice_number=i, file_path_mask=path_to_slice_mask) else: stack._slices[i] = sl.Slice.from_filename( file_path=path_to_slice, slice_number=i) else: slice_numbers = sorted(dic_slice_filenames.keys()) stack._N_slices = len(slice_numbers) stack._slices = [None] * stack._N_slices for i, slice_number in enumerate(slice_numbers): path_to_slice = os.path.join( dir_input, dic_slice_filenames[slice_number] + ".nii.gz") path_to_slice_mask = os.path.join( dir_input, dic_slice_filenames[slice_number] + suffix_mask + ".nii.gz") if ph.file_exists(path_to_slice_mask): stack._slices[i] = sl.Slice.from_filename( file_path=path_to_slice, slice_number=slice_number, file_path_mask=path_to_slice_mask, slice_thickness=stack.get_slice_thickness(), ) else: stack._slices[i] = sl.Slice.from_filename( file_path=path_to_slice, slice_number=slice_number, slice_thickness=stack.get_slice_thickness(), ) return stack
def test_reconstruct_volume(self): filename = "SRR_stacks3_TK1_lsmr_alpha0p02_itermax5.nii.gz" output = os.path.join(self.dir_output, filename) dir_reference = os.path.join(self.dir_data, "reconstruct_volume") dir_reference_mc = os.path.join(dir_reference, "motion_correction") path_to_reference = os.path.join(dir_reference, filename) path_to_reference_mask = ph.append_to_filename( os.path.join(dir_reference, filename), self.suffix_mask) two_step_cycles = 1 iter_max = 5 threshold = 0.75 alpha = 0.02 alpha_first = 0.2 sigma = 1 intensity_correction = 1 isotropic_resolution = 1.02 v2v_method = "RegAladin" cmd_args = [] cmd_args.append("--filenames %s" % " ".join(self.filenames)) cmd_args.append("--output %s" % output) cmd_args.append("--suffix-mask %s" % self.suffix_mask) cmd_args.append("--two-step-cycles %s" % two_step_cycles) cmd_args.append("--iter-max %d" % iter_max) cmd_args.append("--threshold-first %f" % threshold) cmd_args.append("--sigma %f" % sigma) cmd_args.append("--threshold %f" % threshold) cmd_args.append("--intensity-correction %d" % intensity_correction) cmd_args.append("--isotropic-resolution %s" % isotropic_resolution) cmd_args.append("--alpha %f" % alpha) cmd_args.append("--alpha-first %f" % alpha_first) cmd_args.append("--v2v-method %s" % v2v_method) # cmd_args.append("--verbose 1") cmd = "niftymic_reconstruct_volume %s" % (" ").join(cmd_args) self.assertEqual(ph.execute_command(cmd), 0) # Check SRR volume res_sitk = sitkh.read_nifti_image_sitk(output) ref_sitk = sitkh.read_nifti_image_sitk(path_to_reference) diff_sitk = res_sitk - ref_sitk error = np.linalg.norm(sitk.GetArrayFromImage(diff_sitk)) self.assertAlmostEqual(error, 0, places=self.precision) # Check SRR mask volume res_sitk = sitkh.read_nifti_image_sitk( ph.append_to_filename(output, "_mask")) ref_sitk = sitkh.read_nifti_image_sitk(path_to_reference_mask) diff_sitk = res_sitk - ref_sitk error = np.linalg.norm(sitk.GetArrayFromImage(diff_sitk)) self.assertAlmostEqual(error, 0, places=self.precision) # Check transforms pattern = REGEX_FILENAMES + "[.]tfm" p = re.compile(pattern) dir_res_mc = os.path.join(self.dir_output, "motion_correction") trafos_res = sorted([ os.path.join(dir_res_mc, t) for t in os.listdir(dir_res_mc) if p.match(t) ]) trafos_ref = sorted([ os.path.join(dir_reference_mc, t) for t in os.listdir(dir_reference_mc) if p.match(t) ]) self.assertEqual(len(trafos_res), len(trafos_ref)) for i in range(len(trafos_ref)): nda_res = sitkh.read_transform_sitk(trafos_res[i]).GetParameters() nda_ref = sitkh.read_transform_sitk(trafos_ref[i]).GetParameters() nda_diff = np.linalg.norm(np.array(nda_res) - nda_ref) self.assertAlmostEqual(nda_diff, 0, places=self.precision)
def from_slice_filenames( cls, dir_input, prefix_stack, suffix_mask=None, dic_slice_filenames=None, prefix_slice="_slice", slice_thickness=None, ): stack = cls() if dir_input[-1] is not "/": dir_input += "/" stack._dir = dir_input stack._filename = prefix_stack # Get 3D images stack.sitk = sitkh.read_nifti_image_sitk( dir_input + prefix_stack + ".nii.gz", sitk.sitkFloat64) stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk) # Set slice thickness of acquisition if slice_thickness is None: stack._slice_thickness = stack.sitk.GetSpacing()[-1] else: stack._slice_thickness = slice_thickness # Append masks (either provided or binary mask) if suffix_mask is not None and \ os.path.isfile(dir_input + prefix_stack + suffix_mask + ".nii.gz"): stack.sitk_mask = sitkh.read_nifti_image_sitk( dir_input + prefix_stack + suffix_mask + ".nii.gz", sitk.sitkUInt8) stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask) stack._is_unity_mask = False else: stack.sitk_mask = stack._generate_identity_mask() stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask) stack._is_unity_mask = True # Get slices if dic_slice_filenames is None: stack._N_slices = stack.sitk.GetDepth() stack._slices = [None] * stack._N_slices # Append slices as Slice objects for i in range(0, stack._N_slices): path_to_slice = os.path.join( dir_input, prefix_stack + prefix_slice + str(i) + ".nii.gz") path_to_slice_mask = os.path.join( dir_input, prefix_stack + prefix_slice + str(i) + suffix_mask + ".nii.gz") if ph.file_exists(path_to_slice_mask): stack._slices[i] = sl.Slice.from_filename( file_path=path_to_slice, slice_number=i, file_path_mask=path_to_slice_mask) else: stack._slices[i] = sl.Slice.from_filename( file_path=path_to_slice, slice_number=i) else: slice_numbers = sorted(dic_slice_filenames.keys()) stack._N_slices = len(slice_numbers) stack._slices = [None] * stack._N_slices for i, slice_number in enumerate(slice_numbers): path_to_slice = os.path.join( dir_input, dic_slice_filenames[slice_number] + ".nii.gz") path_to_slice_mask = os.path.join( dir_input, dic_slice_filenames[slice_number] + suffix_mask + ".nii.gz") if ph.file_exists(path_to_slice_mask): stack._slices[i] = sl.Slice.from_filename( file_path=path_to_slice, slice_number=slice_number, file_path_mask=path_to_slice_mask, slice_thickness=stack.get_slice_thickness(), ) else: stack._slices[i] = sl.Slice.from_filename( file_path=path_to_slice, slice_number=slice_number, slice_thickness=stack.get_slice_thickness(), ) return stack