def generate_t1_rho_map(self): """Generate 3D T1-rho map and r2 fit map using monoexponential fit across subvolumes acquired at different echo times :return: a MedicalVolume """ spin_lock_times = [] subvolumes_list = [] msk = None if self.focused_mask_filepath: print('Using focused mask: %s' % self.focused_mask_filepath) msk = io_utils.load_nifti(self.focused_mask_filepath) sorted_keys = natsorted(list(self.subvolumes.keys())) for spin_lock_time_index in sorted_keys: subvolumes_list.append(self.subvolumes[spin_lock_time_index]) spin_lock_times.append(self.spin_lock_times[spin_lock_time_index]) mef = MonoExponentialFit( spin_lock_times, subvolumes_list, mask=msk, bounds=(__T1_RHO_LOWER_BOUND__, __T1_RHO_UPPER_BOUND__), tc0=__INITIAL_T1_RHO_VAL__, decimal_precision=__T1_RHO_DECIMAL_PRECISION__) self.t1rho_map, self.r2 = mef.fit() return self.t1rho_map
def generate_t2_star_map(self): """Generate 3D T2* map and r2 fit map using monoexponential fit across subvolumes acquired at different echo times :return: a MedicalVolume """ msk = None spin_lock_times = [] subvolumes_list = [] if self.focused_mask_filepath: print('Using focused mask: %s' % self.focused_mask_filepath) msk = io_utils.load_nifti(self.focused_mask_filepath) for echo_time in self.subvolumes.keys(): spin_lock_times.append(echo_time) subvolumes_list.append(self.subvolumes[echo_time]) mef = MonoExponentialFit( spin_lock_times, subvolumes_list, mask=msk, bounds=(__T2_STAR_LOWER_BOUND__, __T2_STAR_UPPER_BOUND__), tc0=__INITIAL_T2_STAR_VAL__, decimal_precision=__T2_STAR_DECIMAL_PRECISION__) self.t2star_map, self.r2 = mef.fit() return self.t2star_map
def test_baseline_raw_negative(self): base_filepath = './dicoms/healthy07/cubequant_elastix_baseline/raw/%03d.nii.gz' spin_lock_times = [1, 10, 30, 60] for sl in spin_lock_times: filepath = base_filepath % sl arr, _ = io_utils.load_nifti(filepath) assert np.sum( arr < 0) == 0, "Failed %03d: no values should be negative" % sl
def load_data(self, base_load_dirpath): super().load_data(base_load_dirpath) self.subvolumes = [] # Load subvolumes from nifti file for i in range(self.__NUM_ECHOS__): nii_registration_filepath = os.path.join(base_load_dirpath, 'echo%d.nii.gz' % (i + 1)) subvolume = io_utils.load_nifti(nii_registration_filepath) self.subvolumes.append(subvolume)
def test_simpleitk_io(self): # Read and write dicom volume using simpleitk arr, refs_dicom, spacing = dicom_utils.load_dicom( DESS_DICOM_PATH, 'dcm') filepath = './dicoms/ex.nii.gz' io_utils.save_nifti(filepath, arr, spacing) arr2, spacing2 = io_utils.load_nifti(filepath) print(spacing) assert (arr == arr2).all(), "Saved and loaded array must be the same" assert spacing == spacing2, "spacing should agree"
def __load_interregistered_files__(self, interregistered_dirpath): """Load the nifti files of the interregistered subvolumes These subvolumes have already been registered to some base scan using the interregister function :param interregistered_dirpath: path to interregistered directory folder (should be in the data folder specified for saving data) :return: dictionary of subvolumes mapping echo time index --> MedicalVolume :raise: ValueError: 1. Files are not of the name <INTEGER>.nii.gz (e.g. 0.nii.gz, 000.nii.gz, etc) 2. No interregistered files found in interregistered_dirpath """ print('loading interregistered files') if 'interregistered' not in interregistered_dirpath: raise ValueError( 'Invalid path for loading %s interregistered files' % self.NAME) subfiles = os.listdir(interregistered_dirpath) subfiles = natsorted(subfiles) if len(subfiles) == 0: raise ValueError('No interregistered files found') indices = [] subvolumes = [] for subfile in subfiles: subfile_nums = re.findall(r"[-+]?\d*\.\d+|\d+", subfile) if len(subfile_nums) == 0: raise ValueError( '%s is not an interregisterd \'.gz.nii\' file.' % subfile) subfile_num = int(subfile_nums[0]) indices.append(subfile_num) filepath = os.path.join(interregistered_dirpath, subfile) subvolume = io_utils.load_nifti(filepath) subvolumes.append(subvolume) assert len(indices) == len(subvolumes), "Number of subvolumes mismatch" if len(subvolumes) == 0: raise ValueError('No interregistered files found') subvolumes_dict = dict() for i in range(len(indices)): subvolumes_dict[indices[i]] = subvolumes[i] return subvolumes_dict
def interregister(self, target_path, mask_path=None): base_spin_lock_time, base_image = self.intraregistered_data['BASE'] files = self.intraregistered_data['FILES'] temp_interregistered_dirpath = io_utils.check_dir( os.path.join(self.temp_path, 'interregistered')) print('') print('==' * 40) print('Interregistering...') print('Target: %s' % target_path) if mask_path is not None: print('Mask: %s' % mask_path) print('==' * 40) if not mask_path: parameter_files = [ fc.ELASTIX_RIGID_PARAMS_FILE, fc.ELASTIX_AFFINE_PARAMS_FILE ] else: parameter_files = [ fc.ELASTIX_RIGID_INTERREGISTER_PARAMS_FILE, fc.ELASTIX_AFFINE_INTERREGISTER_PARAMS_FILE ] warped_file, transformation_files = self.__interregister_base_file__( (base_image, base_spin_lock_time), target_path, temp_interregistered_dirpath, mask_path=mask_path, parameter_files=parameter_files) warped_files = [(base_spin_lock_time, warped_file)] # Load the transformation file. Apply same transform to the remaining images for spin_lock_time, filename in files: warped_file = self.__apply_transform__( (filename, spin_lock_time), transformation_files, temp_interregistered_dirpath) # append the last warped file - this has all the transforms applied warped_files.append((spin_lock_time, warped_file)) # copy each of the interregistered warped files to their own output subvolumes = dict() for spin_lock_time, warped_file in warped_files: subvolumes[spin_lock_time] = io_utils.load_nifti(warped_file) self.subvolumes = subvolumes
def load_data(self, load_dirpath): """Load information for tissue All tissue information is based on the mask. If mask for tissue doesn't exist, there is no information to load. :param load_dirpath: base path to load data (same as 'save_dirpath' arg input to self.save_data(save_dirpath)) :raise FileNotFoundError: 1. if mask file (.nii.gz nifti format) cannot be found in load_dirpath """ load_dirpath = self.__save_dirpath__(load_dirpath) mask_filepath = os.path.join(load_dirpath, '%s.nii.gz' % self.STR_ID) if not os.path.isfile(mask_filepath): raise FileNotFoundError('File \'%s\' does not exist' % mask_filepath) filepath = os.path.join(load_dirpath, '%s.nii.gz' % self.STR_ID) self.__mask__ = io_utils.load_nifti(filepath)
def __dilate_mask__(self, mask_path, temp_path, dil_rate=defaults.DEFAULT_MASK_DIL_RATE, dil_threshold=defaults.DEFAULT_MASK_DIL_THRESHOLD): """Dilate mask using gaussian blur and write to disk to use with elastix :param mask_path: path to mask to use to use as focus points for registration, mask must be binary :param temp_path: path to store temporary data :param dil_rate: dilation rate (sigma) :param dil_threshold: threshold to binarize dilated mask - float between [0, 1] :return: the path to the dilated mask :raise FileNotFoundError: 1. filepath specified by mask_path is not found :raise ValueError: 1. dil_threshold not in range [0, 1] """ if not os.path.isfile(mask_path): raise FileNotFoundError('File %s not found' % mask_path) if dil_threshold < 0 or dil_threshold > 1: raise ValueError('dil_threshold must be in range [0, 1]') mask = io_utils.load_nifti(mask_path) mask = mask.volume dilated_mask = sni.gaussian_filter(np.asarray(mask.volume, dtype=np.float32), sigma=dil_rate) > dil_threshold fixed_mask = np.asarray(dilated_mask, dtype=np.int8) fixed_mask_filepath = os.path.join(io_utils.check_dir(temp_path), 'dilated-mask.nii.gz') dilated_mask_volume = MedicalVolume(fixed_mask, mask.pixel_spacing) dilated_mask_volume.save_volume(fixed_mask_filepath) return fixed_mask_filepath
def handle_knee(vargin): """Handle parsing command-line input for knee subcommand :param vargin: :return: """ tissues = vargin[TISSUES_KEY] load_path = vargin[LOAD_KEY] medial_to_lateral = vargin[MEDIAL_TO_LATERAL_KEY] pid = vargin[PID_KEY] # Get all supported quantitative values qvs = [] for qv in SUPPORTED_QUANTITATIVE_VALUES: if vargin[qv.name.lower()]: qvs.append(qv) for tissue in tissues: tissue.pid = pid tissue.medial_to_lateral = medial_to_lateral tissue.load_data(load_path) print('') print('==' * 40) print(tissue.FULL_NAME) print('==' * 40) for qv in qvs: # load file print('Analyzing %s' % qv.name.lower()) filepath = find_filepath_with_qv(load_path, qv) tmp = io_utils.load_nifti(filepath) tissue.calc_quant_vals(tmp, qv) for tissue in tissues: tissue.save_data(vargin[SAVE_KEY]) return tissues
## inizializzare mappa t2 e femoral cartilage t2_par = QuantitativeValues(2) dess_l = Dess(dicom_path_l) fc_l = FemoralCartilage() fc_l.pid = sub_id fc_l.scan = scan_id dess_r = Dess(dicom_path_r) fc_r = FemoralCartilage() fc_r.pid = sub_id fc_r.scan = scan_id fc_r.medial_to_lateral = True dess_l.t2map = load_nifti(t2_filepath_left) dess_r.t2map = load_nifti(t2_filepath_right) fc_l.__mask__ = load_nifti(mask_filepath_left) fc_r.__mask__ = load_nifti(mask_filepath_right) fc_l.calc_quant_vals(dess_l.t2map, t2_par) fc_r.calc_quant_vals(dess_r.t2map, t2_par) #save data fc_l.__save_quant_data__(left_knee_save_folder, [20, 85]) fc_r.__save_quant_data__(right_knee_save_folder, [40, 100]) fc_l.save_data(left_knee_save_folder, [20, 85]) fc_r.save_data(right_knee_save_folder, [40, 100])
def interregister(self, target_path, mask_path=None): temp_raw_dirpath = io_utils.check_dir( os.path.join(self.temp_path, 'raw')) subvolumes = self.subvolumes raw_filepaths = dict() echo_time_inds = natsorted(list(subvolumes.keys())) for i in range(len(echo_time_inds)): raw_filepath = os.path.join(temp_raw_dirpath, '%03d.nii.gz' % i) subvolumes[i].save_volume(raw_filepath) raw_filepaths[i] = raw_filepath # last echo should be base base_echo_time, base_image = len(echo_time_inds) - 1, raw_filepaths[ len(echo_time_inds) - 1] temp_interregistered_dirpath = io_utils.check_dir( os.path.join(self.temp_path, 'interregistered')) print('') print('==' * 40) print('Interregistering...') print('Target: %s' % target_path) if mask_path is not None: print('Mask: %s' % mask_path) print('==' * 40) files_to_warp = [] for echo_time_ind in raw_filepaths.keys(): if echo_time_ind == base_echo_time: continue filepath = raw_filepaths[echo_time_ind] files_to_warp.append((echo_time_ind, filepath)) if not mask_path: parameter_files = [ fc.ELASTIX_RIGID_PARAMS_FILE, fc.ELASTIX_AFFINE_PARAMS_FILE ] else: parameter_files = [ fc.ELASTIX_RIGID_INTERREGISTER_PARAMS_FILE, fc.ELASTIX_AFFINE_INTERREGISTER_PARAMS_FILE ] warped_file, transformation_files = self.__interregister_base_file__( (base_image, base_echo_time), target_path, temp_interregistered_dirpath, mask_path=mask_path, parameter_files=parameter_files) warped_files = [(base_echo_time, warped_file)] # Load the transformation file. Apply same transform to the remaining images for echo_time, filename in files_to_warp: warped_file = self.__apply_transform__( (filename, echo_time), transformation_files, temp_interregistered_dirpath) # append the last warped file - this has all the transforms applied warped_files.append((echo_time, warped_file)) # copy each of the interregistered warped files to their own output subvolumes = dict() for echo_time, warped_file in warped_files: subvolumes[echo_time] = io_utils.load_nifti(warped_file) self.subvolumes = subvolumes
def test_load_modified_mask(self): filepath = './dicoms/healthy07/data/fc_modified.nii.gz' arr2, spacing2 = io_utils.load_nifti(filepath) print(arr2.shape) print(spacing2)