예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
    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
예제 #4
0
    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)
예제 #5
0
    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"
예제 #6
0
    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
예제 #7
0
    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
예제 #8
0
    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)
예제 #9
0
    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
예제 #10
0
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
예제 #11
0
## 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])
예제 #12
0
    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
예제 #13
0
    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)