コード例 #1
0
ファイル: atlas.py プロジェクト: 62442katieb/atlasquerpy
    def get_avg_probability(self, mask_img, struct_idx):
        '''
        Calculates the average probability of the atlas voxels that belong to
        mask_img.

        Parameters
        ----------
        mask_img: nib.Nifti1Image

        struct_idx: int
        Index of the atlas' structure of interest.

        Returns
        -------
        float number of the resulting average probability
        '''
        mask_img = nifti2nipy(mask_img)
        mask_vol = mask_img.get_data()

        if self.image.shape[3] <= struct_idx:
            return 0

        prob_img = nifti2nipy(self.image)
        prob_vol = prob_img[:, :, :, struct_idx]

        total = 0.
        mask_sum = np.sum(mask_vol)

        masked_probs = self._get_roi_mask_intersect(mask_img, struct_idx)

        return masked_probs/mask_sum if mask_sum > 0 else 0
コード例 #2
0
ファイル: slice.py プロジェクト: neuropoly/spinalcordtoolbox
 def _resample(self, image, p_resample, type_img, image_ref=None):
     """
     Resample at a fixed resolution to make sure the cord always appears with similar scale, regardless of the native
     resolution of the image. Assumes SAL orientation.
     :param image: Image() to resample
     :param p_resample: float: Resampling resolution in mm
     :param type_img: {'im', 'seg'}: If im, interpolate using spline. If seg, interpolate using linear then binarize.
     :param image_ref: Destination Image() to resample image to.
     :return:
     """
     dict_interp = {'im': 'spline', 'seg': 'linear'}
     # Create nibabel object
     nii = Nifti1Image(image.data, image.hdr.get_best_affine())
     img = nifti2nipy(nii)
     # If no reference image is provided, resample to specified resolution
     if image_ref is None:
         # Resample to px x p_resample x p_resample mm (orientation is SAL by convention in QC module)
         img_r = resample_nipy(img, new_size=str(image.dim[4]) + 'x' + str(p_resample) + 'x' + str(p_resample),
                               new_size_type='mm', interpolation=dict_interp[type_img])
     # Otherwise, resampling to the space of the reference image
     else:
         # Create nibabel object for reference image
         nii_ref = Nifti1Image(image_ref.data, image_ref.hdr.get_best_affine())
         img_ref = nifti2nipy(nii_ref)
         img_r = resample_nipy(img, img_dest=img_ref, interpolation=dict_interp[type_img])
     # If resampled image is a segmentation, binarize using threshold at 0.5
     if type_img == 'seg':
         img_r_data = (img_r.get_data() > 0.5) * 1
     else:
         img_r_data = img_r.get_data()
     nii_r = nipy2nifti(img_r)
     # Create Image objects
     image_r = Image(img_r_data, hdr=nii_r.header, dim=nii_r.header.get_data_shape()). \
         change_orientation(image.orientation)
     return image_r
コード例 #3
0
ファイル: slice.py プロジェクト: npgoodhue/spinalcordtoolbox
 def _resample(self, image, p_resample, type, image_ref=None):
     """
     Resample at a fixed resolution to make sure the cord always appears with similar scale, regardless of the native
     resolution of the image. Assumes SAL orientation.
     :param image: Image() to resample
     :param p_resample: float: Resampling resolution in mm
     :param type: {'im', 'seg'}: If im, interpolate using spline. If seg, interpolate using linear then binarize.
     :param image_ref: Destination Image() to resample image to.
     :return:
     """
     # If no reference image is provided, create nipy object and resample using resample_nipy()
     if image_ref is None:
         dict_interp = {'im': 'spline', 'seg': 'linear'}
         # Create nibabel object
         nii = Nifti1Image(image.data, image.hdr.get_best_affine())
         img = nifti2nipy(nii)
         # Resample to px x p_resample x p_resample mm (orientation is SAL by convention in QC module)
         img_r = resample_nipy(img, new_size=str(image.dim[4]) + 'x' + str(p_resample) + 'x' + str(p_resample),
                               new_size_type='mm', interpolation=dict_interp[type])
         # If segmentation, binarize using threshold at 0.5
         if type == 'seg':
             img_r_data = (img_r.get_data() > 0.5) * 1
         else:
             img_r_data = img_r.get_data()
         nii_r = nipy2nifti(img_r)
         # Create Image objects
         image_r = Image(img_r_data, hdr=nii_r.header, dim=nii_r.header.get_data_shape()). \
             change_orientation(image.orientation)
     # If resampling to reference image, use Image() built-in resampling function to ref image
     else:
         dict_interp = {'im': 3, 'seg': 0}
         image_r = image.interpolate_from_image(image_ref, interpolation_mode=dict_interp[type], border='nearest')
     return image_r
コード例 #4
0
ファイル: atlas.py プロジェクト: 62442katieb/atlasquerpy
    def _get_roi_mask_intersect(self, mask_img, struct_idx):
        '''
        Parameters
        ----------
        mask_img: nib.Nifti1Image or nipy Image

        struct_idx: int

        Returns
        -------
        The total sum of 

        '''
        mask_vol = np.array(mask_img.get_data())

        if self.image.shape[3] <= struct_idx:
            return 0

        lab_img = nifti2nipy(self.image)
        lab_vol = lab_img[:, :, :, struct_idx]

        masked_probs = 0.0

        mask_cm = get_3D_coordmap(mask_img)
        lab_cm = get_3D_coordmap(lab_img)
        for idx in np.argwhere(mask_vol):
            voxc = mm_to_voxcoord(lab_cm, *voxcoord_to_mm(mask_cm, *idx))
            prob = 100 if lab_vol[tuple(voxc)] == struct_idx else 0
            masked_probs += prob * mask_vol[tuple(idx)]

        return masked_probs
コード例 #5
0
ファイル: atlas.py プロジェクト: Neurita/atlas
    def get_roi_overlap(self, mask_img, struct_idx):
        """
        Calculates the percentage overlap of mask_img and the ROI given by
        struct_idx

        Parameters
        ----------
        mask_img: nib.Nifti1Image

        struct_idx: int
        Index of the atlas' structure of interest.

        bin_prob: boolean
        True if it is to binarise ROI probability map, False otherwise

        Returns
        -------
        float number of the resulting ROI overlap percentage
        """
        mask_img = nifti2nipy(mask_img)
        #mask_vol = mask_img.get_data()

        if self.image.shape[3] <= struct_idx:
            return 0

        log.info('Using ' + self.image.get_filename())

        prob_vol = self.image.get_data()[:, :, :, struct_idx]

        prob_sum = np.sum(prob_vol)

        masked_probs = self._get_roi_mask_intersect(mask_img, struct_idx)

        return masked_probs/prob_sum if prob_sum > 0 else 0
コード例 #6
0
ファイル: atlas.py プロジェクト: Neurita/atlas
    def get_avg_probability(self, mask_img, struct_idx):
        """
        Calculates the average probability of the atlas voxels that belong to
        mask_img.

        Parameters
        ----------
        mask_img: nib.Nifti1Image

        struct_idx: int
        Index of the atlas' structure of interest.

        Returns
        -------
        float number of the resulting average probability
        """
        mask_img = nifti2nipy(mask_img)
        mask_vol = mask_img.get_data()

        if self.image.shape[3] <= struct_idx:
            return 0

        log.info('Using ' + self.image.get_filename())

        #lab_vol = self.image.get_data()

        mask_sum = np.sum(mask_vol)
        masked_probs = self._get_roi_mask_intersect(mask_img, struct_idx)

        return masked_probs/mask_sum if mask_sum > 0 else 0
コード例 #7
0
ファイル: atlas.py プロジェクト: Neurita/atlas
    def _get_roi_mask_intersect(self, mask_img, struct_idx):
        """
        Parameters
        ----------
        mask_img: nib.Nifti1Image or nipy Image

        struct_idx: int

        Returns
        -------
        The total sum of

        """
        mask_vol = np.array(mask_img.get_data())

        if self.image.shape[3] <= struct_idx:
            return 0

        lab_img = nifti2nipy(self.image)
        lab_vol = lab_img[:, :, :, struct_idx]

        masked_probs = 0.0

        mask_cm = get_3D_coordmap(mask_img)
        lab_cm = get_3D_coordmap(lab_img)
        for idx in np.argwhere(mask_vol):
            voxc = mm_to_voxcoord(lab_cm, *voxcoord_to_mm(mask_cm, *idx))
            prob = 100 if lab_vol[tuple(voxc)] == struct_idx else 0
            masked_probs += prob * mask_vol[tuple(idx)]

        return masked_probs
コード例 #8
0
ファイル: atlas.py プロジェクト: 62442katieb/atlasquerpy
    def get_roi_overlap(self, mask_img, struct_idx):
        '''
        Calculates the percentage overlap of mask_img and the ROI given by
        struct_idx

        Parameters
        ----------
        mask_img: nib.Nifti1Image

        struct_idx: int
        Index of the atlas' structure of interest.

        bin_prob: boolean
        True if it is to binarise ROI probability map, False otherwise

        Returns
        -------
        float number of the resulting ROI overlap percentage
        '''
        mask_img = nifti2nipy(mask_img)
        mask_vol = mask_img.get_data()

        if self.image.shape[3] <= struct_idx:
            return 0

        prob_vol = self.image.get_data()[:, :, :, struct_idx]

        prob_sum = np.sum(prob_vol)

        masked_probs = self._get_roi_mask_intersect(mask_img, struct_idx)

        return masked_probs/prob_sum if prob_sum > 0 else 0
コード例 #9
0
def nifti2occiput(nif):
    """Convert Nifti image to occiput ImageND image.

        Args:
            nif (Nifti): Nifti image.

        Returns:
            ImageND: occiput image.
        """
    nip = nifti2nipy(nif)
    return nipy2occiput(nip)
コード例 #10
0
def fake_4dimage_nipy():
    """
    :return: an empty 4-d nipy Image
    """
    nx, ny, nz, nt = 9, 9, 9, 3  # image dimension
    data = np.zeros((nx, ny, nz, nt), dtype=np.int8)
    data[4, 4, 4, 0] = 1.
    affine = np.eye(4)
    # Create nibabel object
    nii = nib.nifti1.Nifti1Image(data, affine)
    # return nipy object
    return nifti2nipy(nii)
コード例 #11
0
def fake_3dimage_nipy_big():
    """
    :return: an empty 3-d nipy Image
    """
    nx, ny, nz = 29, 39, 19  # image dimension
    data = np.zeros((nx, ny, nz), dtype=np.int8)
    data[14, 19, 9] = 1.
    affine = np.eye(4)
    # Create nibabel object
    nii = nib.nifti1.Nifti1Image(data, affine)
    # return nipy object
    return nifti2nipy(nii)
コード例 #12
0
def fake_4dimage_nipy():
    """
    :return: an empty 4-d nipy Image
    """
    nx, ny, nz, nt = 9, 9, 9, 3  # image dimension
    data = np.zeros((nx, ny, nz, nt), dtype=np.int8)
    data[4, 4, 4, 0] = 1.
    affine = np.eye(4)
    # Create nibabel object
    nii = nib.nifti1.Nifti1Image(data, affine)
    # return nipy object
    return nifti2nipy(nii)
コード例 #13
0
def fake_3dimage_nipy_big():
    """
    :return: an empty 3-d nipy Image
    """
    nx, ny, nz = 29, 39, 19  # image dimension
    data = np.zeros((nx, ny, nz), dtype=np.int8)
    data[14, 19, 9] = 1.
    affine = np.eye(4)
    # Create nibabel object
    nii = nib.nifti1.Nifti1Image(data, affine)
    # return nipy object
    return nifti2nipy(nii)
コード例 #14
0
def segment_file(input_filename, output_filename,
                 model_name, threshold, verbosity):
    """Segment a volume file.

    :param input_filename: the input filename.
    :param output_filename: the output filename.
    :param model_name: the name of model to use.
    :param threshold: threshold to apply in predictions (if None,
                      no threshold will be applied)
    :param verbosity: the verbosity level.
    :return: the output filename.
    """
    nii_original = nipy.load_image(input_filename)
    pixdim = nii_original.header["pixdim"][3]
    target_resample = "0.25x0.25x{:.5f}".format(pixdim)

    nii_resampled = nipy_resample.resample_image(nii_original,
                                                 target_resample,
                                                 'mm', 'linear',
                                                 verbosity)

    if (nii_resampled.shape[0] < 200) \
       or (nii_resampled.shape[1] < 200):
        raise RuntimeError("Image too small ({}, {})".format(
                           nii_resampled.shape[0],
                           nii_resampled.shape[1]))

    nii_resampled = nipy2nifti(nii_resampled)
    pred_slices = segment_volume(nii_resampled, model_name, threshold)

    original_res = "{:.5f}x{:.5f}x{:.5f}".format(
        nii_original.header["pixdim"][1],
        nii_original.header["pixdim"][2],
        nii_original.header["pixdim"][3])

    volume_affine = nii_resampled.affine
    volume_header = nii_resampled.header
    nii_segmentation = nib.Nifti1Image(pred_slices, volume_affine,
                                       volume_header)
    nii_segmentation = nifti2nipy(nii_segmentation)

    nii_resampled_original = nipy_resample.resample_image(nii_segmentation,
                                                          original_res,
                                                          'mm', 'linear',
                                                          verbosity)
    res_data = nii_resampled_original.get_data()

    # Threshold after resampling, only if specified
    if threshold is not None:
        res_data = threshold_predictions(res_data, 0.5)

    nipy.save_image(nii_resampled_original, output_filename)
    return output_filename
コード例 #15
0
def motion_correction_nipy(in_file, out_path, mc_alg, extra_params={}):
    """
    an attempt at motion correction using NiPy package. 
    
    inputs:
        in_file: Full path to the resting-state scan. 
        out_path: Full path to the (to be) output file. 
        mc_alg: can be either 'nipy_spacerealign' or 'nipy_spacetimerealign'
        extra_params: extra parameters to SpaceRealign, SpaceTimeRealign, estimate
    return: the motion corrected image
    """

    alg_dict = {
        'nipy_spacerealign': (SpaceRealign, {}),
        'nipy_spacetimerealign': (SpaceTimeRealign, {
            'tr': 2,
            'slice_times': 'asc_alt_2',
            'slice_info': 2
        })
    }
    # format: {'function_name':(function, kwargs), ...}

    # processing starts here
    if type(in_file) in nib.all_image_classes:
        I = nifti2nipy(in_file)  # assume Nifti1Image
    else:
        I = load_image(in_file)
    print 'source image loaded. '

    # initialize the registration algorithm
    reg = AllFeatures(alg_dict[mc_alg][0],
                      extra_params).run(I, **alg_dict[mc_alg][1])
    #    reg = alg_dict[mc_alg][0](I, **alg_dict[mc_alg][1]) # SpaceTimeRealign(I, tr=2, ...)
    print 'motion correction algorithm established. '
    print 'estimating...'

    if USE_CACHE:
        mem = Memory("func_preproc_cache_2")
        mem.cache(AllFeatures(reg.estimate, extra_params).run)(refscan=None)
#        mem.cache(reg.estimate)(refscan=None)
    else:
        AllFeatures(reg.estimate, extra_params).run(refscan=None)
#        reg.estimate(refscan=None)

    print 'estimation complete. Writing to file...'
    result = reg.resample(0)
    if out_path:
        save_image(result, out_path)
    return nipy2nifti(result)
コード例 #16
0
def segment_file(input_filename, output_filename,
                 model_name, threshold, verbosity,
                 use_tta):
    """Segment a volume file.

    :param input_filename: the input filename.
    :param output_filename: the output filename.
    :param model_name: the name of model to use.
    :param threshold: threshold to apply in predictions (if None,
                      no threshold will be applied)
    :param verbosity: the verbosity level.
    :param use_tta: whether it should use TTA (test-time augmentation)
                    or not.
    :return: the output filename.
    """
    nii_original = nipy.load_image(input_filename)
    pixdim = nii_original.header["pixdim"][3]
    target_resample = "0.25x0.25x{:.5f}".format(pixdim)

    nii_resampled = resampling.resample_nipy(nii_original, new_size=target_resample, new_size_type='mm',
                                             interpolation='linear', verbose=verbosity)
    nii_resampled = nipy2nifti(nii_resampled)
    pred_slices = segment_volume(nii_resampled, model_name, threshold,
                                 use_tta)

    original_res = "{:.5f}x{:.5f}x{:.5f}".format(
        nii_original.header["pixdim"][1],
        nii_original.header["pixdim"][2],
        nii_original.header["pixdim"][3])

    volume_affine = nii_resampled.affine
    volume_header = nii_resampled.header
    nii_segmentation = nib.Nifti1Image(pred_slices, volume_affine,
                                       volume_header)
    nii_segmentation = nifti2nipy(nii_segmentation)

    nii_resampled_original = resampling.resample_nipy(nii_segmentation, new_size=original_res, new_size_type='mm',
                                                      interpolation='linear', verbose=verbosity)
    res_data = nii_resampled_original.get_data()

    # Threshold after resampling, only if specified
    if threshold is not None:
        res_data = threshold_predictions(res_data, 0.5)

    nipy.save_image(nii_resampled_original, output_filename)
    return output_filename
コード例 #17
0
def get_3D_coordmap(img):
    '''
    Gets a 3D CoordinateMap from img.

    Parameters
    ----------
    img: nib.Nifti1Image or nipy Image

    Returns
    -------
    nipy.core.reference.coordinate_map.CoordinateMap
    '''
    if isinstance(img, nib.Nifti1Image):
        img = nifti2nipy(img)

    if img.ndim == 4:
        from nipy.core.reference.coordinate_map import drop_io_dim
        cm = drop_io_dim(img.coordmap, 3)
    else:
        cm = img.coordmap

    return cm
コード例 #18
0
ファイル: coord_transform.py プロジェクト: Neurita/boyle
def get_3D_coordmap(img):
    '''
    Gets a 3D CoordinateMap from img.

    Parameters
    ----------
    img: nib.Nifti1Image or nipy Image

    Returns
    -------
    nipy.core.reference.coordinate_map.CoordinateMap
    '''
    if isinstance(img, nib.Nifti1Image):
        img = nifti2nipy(img)

    if img.ndim == 4:
        from nipy.core.reference.coordinate_map import drop_io_dim
        cm = drop_io_dim(img.coordmap, 3)
    else:
        cm = img.coordmap

    return cm
コード例 #19
0
def resample_nipy(img,
                  new_size=None,
                  new_size_type=None,
                  img_dest=None,
                  interpolation='linear',
                  verbose=1):
    """Resample a nipy image object based on a specified resampling factor.
    Can deal with 2d, 3d or 4d image objects.
    :param img: nipy Image.
    :param new_size: list of float: Resampling factor, final dimension or resolution, depending on new_size_type.
    TODO: implement as list.
    :param new_size_type: {'vox', 'factor', 'mm'}: Feature used for resampling. Examples:
      new_size=[128, 128, 90], new_size_type='vox' --> Resampling to a dimension of 128x128x90 voxels
      new_size=[2, 2, 2], new_size_type='factor' --> 2x isotropic upsampling
      new_size=[1, 1, 5], new_size_type='mm' --> Resampling to a resolution of 1x1x5 mm
    :param img_dest: Destination nipy Image to resample the input image to. In this case, new_size and new_size_type are
      ignored
    :param interpolation: {'nn', 'linear', 'spline'}. The interpolation type
    :return: The resampled nipy Image.
    """
    # TODO: deal with 4d (and other dim) data

    # set interpolation method
    dict_interp = {'nn': 0, 'linear': 1, 'spline': 2}

    if img_dest is None:
        # Get dimensions of data
        p = img.header.get_zooms()
        shape = img.header.get_data_shape()

        # parse input argument
        new_size = new_size.split('x')

        if img.ndim == 4:
            new_size += [
                '1'
            ]  # needed because the code below is general, i.e., does not assume 3d input and uses img.shape

        # assert len(shape) == len(new_size)

        # compute new shape based on specific resampling method
        if new_size_type == 'vox':
            shape_r = tuple([int(new_size[i]) for i in range(img.ndim)])
        elif new_size_type == 'factor':
            if len(new_size) == 1:
                # isotropic resampling
                new_size = tuple([new_size[0] for i in range(img.ndim)])
            # compute new shape as: shape_r = shape * f
            shape_r = tuple([
                int(np.round(shape[i] * float(new_size[i])))
                for i in range(img.ndim)
            ])
        elif new_size_type == 'mm':
            if len(new_size) == 1:
                # isotropic resampling
                new_size = tuple([new_size[0] for i in range(img.ndim)])
            # compute new shape as: shape_r = shape * (p_r / p)
            shape_r = tuple([
                int(np.round(shape[i] * float(p[i]) / float(new_size[i])))
                for i in range(img.ndim)
            ])
        else:
            sct.log.error('new_size_type is not recognized.')

        # Generate 3d affine transformation: R
        affine = img.affine[:4, :4]
        affine[3, :] = np.array([
            0, 0, 0, 1
        ])  # satisfy to nifti convention. Otherwise it grabs the temporal
        sct.log.debug('Affine matrix: \n' + str(affine), verbose)
        R = np.eye(4)
        for i in range(3):
            R[i, i] = img.shape[i] / float(shape_r[i])
        affine_r = np.dot(affine, R)

        reference = (shape_r, affine_r)

    else:
        # If reference is provided
        reference = img_dest
        R = None

    if img.ndim == 3:
        img_r = n_resample(img,
                           transform=R,
                           reference=reference,
                           mov_voxel_coords=True,
                           ref_voxel_coords=True,
                           dtype='double',
                           interp_order=dict_interp[interpolation],
                           mode='nearest')

    elif img.ndim == 4:
        # TODO: Cover img_dest with 4D volumes
        # Import here instead of top of the file because this is an isolated case and nibabel takes time to import
        import nibabel as nib
        from nipy.io.nifti_ref import nifti2nipy, nipy2nifti
        data4d = np.zeros(shape_r)
        # Loop across 4th dimension and resample each 3d volume
        for it in range(img.shape[3]):
            # Create dummy 3d nipy image
            nii_tmp = nib.nifti1.Nifti1Image(img.get_data()[..., it], affine)
            img3d_r = n_resample(nifti2nipy(nii_tmp),
                                 transform=R,
                                 reference=(shape_r[:-1], affine_r),
                                 mov_voxel_coords=True,
                                 ref_voxel_coords=True,
                                 dtype='double',
                                 interp_order=dict_interp[interpolation],
                                 mode='nearest')
            data4d[..., it] = img3d_r.get_data()
        # Create 4d nipy Image
        nii4d = nib.nifti1.Nifti1Image(data4d, affine_r)
        # Convert to nipy object
        img_r = nifti2nipy(nii4d)

    # print "HOLA!!!"
    # print img.coordmap
    # print img_r.coordmap
    return img_r
コード例 #20
0
def dummy_segmentation(size_arr=(256, 256, 256), pixdim=(1, 1, 1), dtype=np.float64, orientation='LPI',
                       shape='rectangle', angle_RL=0, angle_AP=0, angle_IS=0, radius_RL=5.0, radius_AP=3.0,
                       zeroslice=[], debug=False):
    """Create a dummy Image with a ellipse or ones running from top to bottom in the 3rd dimension, and rotate the image
    to make sure that compute_csa and compute_shape properly estimate the centerline angle.
    :param size_arr: tuple: (nx, ny, nz)
    :param pixdim: tuple: (px, py, pz)
    :param dtype: Numpy dtype.
    :param orientation: Orientation of the image. Default: LPI
    :param shape: {'rectangle', 'ellipse'}
    :param angle_RL: int: angle around RL axis (in deg)
    :param angle_AP: int: angle around AP axis (in deg)
    :param angle_IS: int: angle around IS axis (in deg)
    :param radius_RL: float: 1st radius. With a, b = 50.0, 30.0 (in mm), theoretical CSA of ellipse is 4712.4
    :param radius_AP: float: 2nd radius
    :param zeroslice: list int: zero all slices listed in this param
    :param debug: Write temp files for debug
    :return: img: Image object
    """
    # Initialization
    padding = 15  # Padding size (isotropic) to avoid edge effect during rotation
    # Create a 3d array, with dimensions corresponding to x: RL, y: AP, z: IS
    nx, ny, nz = [int(size_arr[i] * pixdim[i]) for i in range(3)]
    data = np.random.random((nx, ny, nz)) * 0.
    xx, yy = np.mgrid[:nx, :ny]
    # loop across slices and add object
    for iz in range(nz):
        if shape == 'rectangle':  # theoretical CSA: (a*2+1)(b*2+1)
            data[:, :, iz] = ((abs(xx - nx / 2) <= radius_RL) & (abs(yy - ny / 2) <= radius_AP)) * 1
        if shape == 'ellipse':
            data[:, :, iz] = (((xx - nx / 2) / radius_RL) ** 2 + ((yy - ny / 2) / radius_AP) ** 2 <= 1) * 1

    # Pad to avoid edge effect during rotation
    data = np.pad(data, padding, 'reflect')

    # ROTATION ABOUT IS AXIS
    # rotate (in deg), and re-grid using linear interpolation
    data_rotIS = rotate(data, angle_IS, resize=False, center=None, order=1, mode='constant', cval=0, clip=False,
                        preserve_range=False)

    # ROTATION ABOUT RL AXIS
    # Swap x-z axes (to make a rotation within y-z plane, because rotate will apply rotation on the first 2 dims)
    data_rotIS_swap = data_rotIS.swapaxes(0, 2)
    # rotate (in deg), and re-grid using linear interpolation
    data_rotIS_swap_rotRL = rotate(data_rotIS_swap, angle_RL, resize=False, center=None, order=1, mode='constant',
                                   cval=0, clip=False, preserve_range=False)
    # swap back
    data_rotIS_rotRL = data_rotIS_swap_rotRL.swapaxes(0, 2)

    # ROTATION ABOUT AP AXIS
    # Swap y-z axes (to make a rotation within x-z plane)
    data_rotIS_rotRL_swap = data_rotIS_rotRL.swapaxes(1, 2)
    # rotate (in deg), and re-grid using linear interpolation
    data_rotIS_rotRL_swap_rotAP = rotate(data_rotIS_rotRL_swap, angle_AP, resize=False, center=None, order=1,
                                         mode='constant', cval=0, clip=False, preserve_range=False)
    # swap back
    data_rot = data_rotIS_rotRL_swap_rotAP.swapaxes(1, 2)

    # Crop image (to remove padding)
    data_rot_crop = data_rot[padding:nx+padding, padding:ny+padding, padding:nz+padding]

    # Zero specified slices
    if zeroslice is not []:
        data_rot_crop[:, :, zeroslice] = 0

    # Create nibabel object
    xform = np.eye(4)
    for i in range(3):
        xform[i][i] = 1  # in [mm]
    nii = nib.nifti1.Nifti1Image(data_rot_crop.astype('float32'), xform)
    # Create nipy object and resample to desired resolution
    nii_nipy = nifti2nipy(nii)
    nii_nipy_r = resample_nipy(nii_nipy, new_size='x'.join([str(i) for i in pixdim]), new_size_type='mm',
                               interpolation='linear', dtype=dtype)
    nii_r = nipy2nifti(nii_nipy_r)
    # Create Image object. Default orientation is LPI.
    # For debugging add .save() at the end of the command below
    img = Image(nii_r.get_data(), hdr=nii_r.header, dim=nii_r.header.get_data_shape())
    # Update orientation
    img.change_orientation(orientation)
    if debug:
        img.save('tmp_dummy_seg_'+datetime.now().strftime("%Y%m%d%H%M%S%f")+'.nii.gz')
    return img
コード例 #21
0
def dummy_segmentation(size_arr=(256, 256, 256),
                       pixdim=(1, 1, 1),
                       dtype=np.float64,
                       orientation='LPI',
                       shape='rectangle',
                       angle_RL=0,
                       angle_AP=0,
                       angle_IS=0,
                       radius_RL=5.0,
                       radius_AP=3.0,
                       zeroslice=[],
                       debug=False):
    """Create a dummy Image with a ellipse or ones running from top to bottom in the 3rd dimension, and rotate the image
    to make sure that compute_csa and compute_shape properly estimate the centerline angle.
    :param size_arr: tuple: (nx, ny, nz)
    :param pixdim: tuple: (px, py, pz)
    :param dtype: Numpy dtype.
    :param orientation: Orientation of the image. Default: LPI
    :param shape: {'rectangle', 'ellipse'}
    :param angle_RL: int: angle around RL axis (in deg)
    :param angle_AP: int: angle around AP axis (in deg)
    :param angle_IS: int: angle around IS axis (in deg)
    :param radius_RL: float: 1st radius. With a, b = 50.0, 30.0 (in mm), theoretical CSA of ellipse is 4712.4
    :param radius_AP: float: 2nd radius
    :param zeroslice: list int: zero all slices listed in this param
    :param debug: Write temp files for debug
    :return: img: Image object
    """
    # Initialization
    padding = 15  # Padding size (isotropic) to avoid edge effect during rotation
    # Create a 3d array, with dimensions corresponding to x: RL, y: AP, z: IS
    nx, ny, nz = [int(size_arr[i] * pixdim[i]) for i in range(3)]
    data = np.random.random((nx, ny, nz)) * 0.
    xx, yy = np.mgrid[:nx, :ny]
    # loop across slices and add object
    for iz in range(nz):
        if shape == 'rectangle':  # theoretical CSA: (a*2+1)(b*2+1)
            data[:, :, iz] = ((abs(xx - nx / 2) <= radius_RL) &
                              (abs(yy - ny / 2) <= radius_AP)) * 1
        if shape == 'ellipse':
            data[:, :, iz] = (((xx - nx / 2) / radius_RL)**2 +
                              ((yy - ny / 2) / radius_AP)**2 <= 1) * 1

    # Pad to avoid edge effect during rotation
    data = np.pad(data, padding, 'reflect')

    # ROTATION ABOUT IS AXIS
    # rotate (in deg), and re-grid using linear interpolation
    data_rotIS = rotate(data,
                        angle_IS,
                        resize=False,
                        center=None,
                        order=1,
                        mode='constant',
                        cval=0,
                        clip=False,
                        preserve_range=False)

    # ROTATION ABOUT RL AXIS
    # Swap x-z axes (to make a rotation within y-z plane, because rotate will apply rotation on the first 2 dims)
    data_rotIS_swap = data_rotIS.swapaxes(0, 2)
    # rotate (in deg), and re-grid using linear interpolation
    data_rotIS_swap_rotRL = rotate(data_rotIS_swap,
                                   angle_RL,
                                   resize=False,
                                   center=None,
                                   order=1,
                                   mode='constant',
                                   cval=0,
                                   clip=False,
                                   preserve_range=False)
    # swap back
    data_rotIS_rotRL = data_rotIS_swap_rotRL.swapaxes(0, 2)

    # ROTATION ABOUT AP AXIS
    # Swap y-z axes (to make a rotation within x-z plane)
    data_rotIS_rotRL_swap = data_rotIS_rotRL.swapaxes(1, 2)
    # rotate (in deg), and re-grid using linear interpolation
    data_rotIS_rotRL_swap_rotAP = rotate(data_rotIS_rotRL_swap,
                                         angle_AP,
                                         resize=False,
                                         center=None,
                                         order=1,
                                         mode='constant',
                                         cval=0,
                                         clip=False,
                                         preserve_range=False)
    # swap back
    data_rot = data_rotIS_rotRL_swap_rotAP.swapaxes(1, 2)

    # Crop image (to remove padding)
    data_rot_crop = data_rot[padding:nx + padding, padding:ny + padding,
                             padding:nz + padding]

    # Zero specified slices
    if zeroslice is not []:
        data_rot_crop[:, :, zeroslice] = 0

    # Create nibabel object
    xform = np.eye(4)
    for i in range(3):
        xform[i][i] = 1  # in [mm]
    nii = nib.nifti1.Nifti1Image(data_rot_crop.astype('float32'), xform)
    # Create nipy object and resample to desired resolution
    nii_nipy = nifti2nipy(nii)
    nii_nipy_r = resample_nipy(nii_nipy,
                               new_size='x'.join([str(i) for i in pixdim]),
                               new_size_type='mm',
                               interpolation='linear',
                               dtype=dtype)
    nii_r = nipy2nifti(nii_nipy_r)
    # Create Image object. Default orientation is LPI.
    # For debugging add .save() at the end of the command below
    img = Image(nii_r.get_data(),
                hdr=nii_r.header,
                dim=nii_r.header.get_data_shape())
    # Update orientation
    img.change_orientation(orientation)
    if debug:
        img.save('tmp_dummy_seg_' + datetime.now().strftime("%Y%m%d%H%M%S%f") +
                 '.nii.gz')
    return img