Example #1
0
def test_BaseModel():

    BM = BaseModel(data_path + 'small_dwi.nii.gz', data_path + 'dwi.bvecs',
                   data_path + 'dwi.bvals')

    npt.assert_equal(BM.r_squared, np.ones(BM.signal.shape[:3]))
    npt.assert_equal(BM.R_squared, np.ones(BM.signal.shape[:3]))
    npt.assert_equal(BM.coeff_of_determination, np.ones(BM.signal.shape[:3]))
    npt.assert_equal(BM.RMSE, np.zeros(BM.signal.shape[:3]))

    # Test without numexpr: XXX Doesn't seem to do that for now
    has_numexpr = ozm.has_numexpr
    if has_numexpr:
        ozm.has_numexpr = False
        BM_wo_numexpr = BaseModel(data_path + 'small_dwi.nii.gz',
                                  data_path + 'dwi.bvecs',
                                  data_path + 'dwi.bvals')

        npt.assert_equal(BM.r_squared, np.ones(BM.signal.shape[:3]))
        npt.assert_equal(BM.R_squared, np.ones(BM.signal.shape[:3]))
        npt.assert_equal(BM.coeff_of_determination,
                         np.ones(BM.signal.shape[:3]))
        npt.assert_equal(BM.RMSE, np.zeros(BM.signal.shape[:3]))

        # Set it back:
        ozm.has_numexpr = True
Example #2
0
    def __init__(self,
                 data,
                 bvecs,
                 bvals,
                 sh_order=8,
                 quad_points=132,
                 verts_level=5,
                 alpha=None,
                 rho=None,
                 params_file=None,
                 affine=None,
                 mask=None,
                 scaling_factor=SCALE_FACTOR):

        # Initialize the super-class:
        BaseModel.__init__(self,
                           data,
                           bvecs,
                           bvals,
                           affine=affine,
                           mask=mask,
                           scaling_factor=scaling_factor,
                           params_file=params_file)

        self.sh_order = sh_order
        self.quad_points = quad_points

        # This will soon be replaced by an import from dipy:
        import kernel_model
        from dipy.core.subdivide_octahedron import create_unit_hemisphere

        self.kernel_model = kernel_model
        self.verts_level = verts_level

        # Set the sparseness params.
        # First, for the default values:
        aa = 0.0001  # L1 weight
        bb = 0.00001  # L2 weight
        if alpha is None:
            alpha = aa + bb
        if rho is None:
            rho = aa / (aa + bb)

        self.alpha = alpha
        self.rho = rho
Example #3
0
    def __init__(self,
                 data,
                 bvecs,
                 bvals,
                 sh_order=8,
                 quad_points=132,
                 verts_level=5,
                 alpha=None,
                 rho=None,
                 params_file=None,
                 affine=None,
                 mask=None,
                 scaling_factor=SCALE_FACTOR):

        # Initialize the super-class:
        BaseModel.__init__(self,
                           data,
                           bvecs,
                           bvals,
                           affine=affine,
                           mask=mask,
                           scaling_factor=scaling_factor,
                           params_file=params_file)

        self.sh_order = sh_order
        self.quad_points = quad_points

        # This will soon be replaced by an import from dipy:
        import kernel_model
        from dipy.core.subdivide_octahedron import create_unit_hemisphere
        
        self.kernel_model = kernel_model
        self.verts_level = verts_level

        # Set the sparseness params.
        # First, for the default values:
        aa = 0.0001  # L1 weight
        bb = 0.00001 # L2 weight
        if alpha is None:
            alpha = aa + bb
        if rho is None: 
            rho = aa/(aa + bb)

        self.alpha = alpha
        self.rho = rho
Example #4
0
    def __init__(self,
                 data,
                 bvecs,
                 bvals,
                 params_file=None,
                 affine=None,
                 mask=None,
                 scaling_factor=SCALE_FACTOR):

        # Initialize the super-class:
        BaseModel.__init__(self,
                           data,
                           bvecs,
                           bvals,
                           affine=affine,
                           mask=mask,
                           scaling_factor=scaling_factor,
                           params_file=params_file)
    def __init__(self,
                 data,
                 bvecs,
                 bvals,
                 params_file=None,
                 affine=None,
                 mask=None,
                 scaling_factor=SCALE_FACTOR):

        
        # Initialize the super-class:
        BaseModel.__init__(self,
                           data,
                           bvecs,
                           bvals,
                           affine=affine,
                           mask=mask,
                           scaling_factor=scaling_factor,
                           params_file=params_file)
Example #6
0
    def __init__(self,
                 data,
                 FG,
                 bvecs=None,
                 bvals=None,
                 affine=None,
                 mask=None,
		 scaling_factor=None,
		 params_file=None,
		 sub_sample=None):
	"""
	Parameters
	----------
        
	data : a volume with data (can be diffusion data, but doesn't have to
	be)

	FG : a osmosis.fibers.FiberGroup object, or the name of a pdb file
        containing the fibers to be read in using ozf.fg_from_pdb
        """
        # Initialize the super-class:
        BaseModel.__init__(self,
                            data,
                            bvecs,
                            bvals,
                            affine=affine,
                            mask=mask,
                            scaling_factor=scaling_factor,
                            params_file=params_file,
                            sub_sample=sub_sample)
        
        if affine is not None:
            # The FG is transformed through the provided affine if need be: 
            self.FG = FG.xform(affine.getI(), inplace=False)
        else:
            self.FG = FG
Example #7
0
    def __init__(self,
                 data,
                 FG,
                 bvecs=None,
                 bvals=None,
                 affine=None,
                 mask=None,
                 scaling_factor=None,
                 params_file=None,
                 sub_sample=None):
        """
	Parameters
	----------
        
	data : a volume with data (can be diffusion data, but doesn't have to
	be)

	FG : a osmosis.fibers.FiberGroup object, or the name of a pdb file
        containing the fibers to be read in using ozf.fg_from_pdb
        """
        # Initialize the super-class:
        BaseModel.__init__(self,
                           data,
                           bvecs,
                           bvals,
                           affine=affine,
                           mask=mask,
                           scaling_factor=scaling_factor,
                           params_file=params_file,
                           sub_sample=sub_sample)

        if affine is not None:
            # The FG is transformed through the provided affine if need be:
            self.FG = FG.xform(affine.getI(), inplace=False)
        else:
            self.FG = FG
Example #8
0
    def __init__(self,
                 data,
                 bvecs,
                 bvals,
                 params_file=None,
                 axial_diffusivity=AD,
                 radial_diffusivity=RD,
                 affine=None,
                 mask=None,
                 scaling_factor=SCALE_FACTOR,
                 sub_sample=None,
                 over_sample=None,
                 mode='relative_signal',
                 iso_diffusivity=None,
                 verbose=True):

        """
        Initialize a CanonicalTensorModel class instance.

        Parameters
        ----------

        params_file: str, optional
             full path to the name of the file in which to save the model
             parameters, once a model is fit. 

        over_sample: optional, int.
           Sometimes you might want to probe the sphere at a higher resolution
           than that provided by the measurement. You can do that using two
           possible sources of information. The first is the camino points,
           which ship together with osmosis and are used for the boot-strapping
           (see osmosis.boot). These are used for integers smaller than 150,
           for 246 and for 755. The other sources of information are the
           symmetric spheres provided as part of dipy. These are used if 362 or
           642 are provided. Note that these might be problematic, because they
           contain polar opposite points, so use with caution.

        mode: string, optional
        This can take one of several values, determining the form of the
        regressors and the form of the signal to fit to.

        'relative_signal': The fit is to $\frac{S}{S_0}$ and the regressors
        are the relative signal predicted for a canonical tensor and the
        relative signal predicted for a isotropic diffusivity compartment:

        .. math::

           \frac{S}{S_0} = \beta_1 e^{-bD} + \beta_2 e^{-b\vec{b}Q\vec{b}^t}

    
        'signal_attenuation': The fit is to $1-\frac{S}{S_0}$ and the
        regressors are the signal attenuation for the canonical tensor and the
        signal attenuation due to isotropic diffusion:

        .. math::

             1-\frac{S}{S_0} = \beta_1 (1-e^{-bD}) + \beta_2 (1-e^{-b\vec{b} Q \vec{b}^t})

        'normalize': in this case, we fit to $\frac{S}{S_0}$, but our regressor
        set is normalized to maximum of 1 in each columns. This affects the
        values of the weights, and also the goodness-of-fit (because of the
        relative scaling of the regressors in the OLS). The equation in
        this case is: 

        .. math::

             \frac{S}{S_0} = \beta_1 + \beta_2 \frac{e^{-b\vec{b} Q \vec{b}^t}}{max(e^{-b\vec{b} Q \vec{b}^t})}


        'log': in this case, we fit to $log(\frac{S}{S_0})$ and our regressors
        are the exponents:

        .. math::

            log(\frac{S}{S_0}) = \beta_1 -bD + \beta_1 -b\vec{b}Q\vec{b}^t

        iso_diffusivity: optional, float
            What the diffusivity of the isotropic component should be set
            to. This is irrelevant for the 'normalize' mode. Defaults to be
            equal to the axial_diffusivity
              
        """
        
        # Initialize the super-class:
        BaseModel.__init__(self,
                            data,
                            bvecs,
                            bvals,
                            affine=affine,
                            mask=mask,
                            scaling_factor=scaling_factor,
                            sub_sample=sub_sample,
                            params_file=params_file,
                            verbose=verbose)

        self.ad = axial_diffusivity
        self.rd = radial_diffusivity

        if iso_diffusivity is None:
           iso_diffusivity = axial_diffusivity
        self.iso_diffusivity = iso_diffusivity

        if over_sample is not None:
            # Symmetric spheres from dipy: 
            if over_sample in[362, 642]:
                # We want to get these vertices:
                verts = dpd.get_sphere('symmetric%s'%over_sample).vertices
                # Their convention is transposed relative to ours:
                self.rot_vecs = verts.T
            elif (isinstance(over_sample, int) and (over_sample<=150 or
                                                    over_sample in [246,755])):
                self.rot_vecs = ozu.get_camino_pts(over_sample)
            elif over_sample== 'quad132':
                pp = os.path.split(oz.__file__)[0]+'/data/SparseKernelModel/'
                self.rot_vecs = np.loadtxt(pp + 'qsph1-16-132DP.dat')[:,:-1].T
            else:
                e_s = "You asked to sample the sphere in %s"%over_sample
                e_s += " different directions. Can only do that for n<=150"
                e_s += " or n in [246, 362, 642, 755]"
                raise ValueError(e_s)
        else:
            self.rot_vecs = self.bvecs[:,self.b_idx]

        if mode not in ['relative_signal',
                        'signal_attenuation',
                        'normalize',
                        'log']:
            raise ValueError("Not a recognized mode of CanonicalTensorModel")

        self.mode = mode
        self.iso_diffusivity = iso_diffusivity
Example #9
0
    def __init__(
        self,
        data,
        bvecs,
        bvals,
        model_coeffs,
        params_file=None,
        axial_diffusivity=None,
        radial_diffusivity=None,
        response_file=None,
        affine=None,
        mask=None,
        scaling_factor=SCALE_FACTOR,
        sub_sample=None,
        verbose=True,
    ):
        """
        Initialize a SphericalHarmonicsModel class instance.
        
        Parameters
        ----------
        DWI: osmosis.dwi.DWI class instance.

        model_coefficients: ndarray
           Coefficients for a SH model, organized according to the conventions
           used by mrtrix (see sph_harm_set for details).
        
        """
        # Initialize the super-class:
        BaseModel.__init__(
            self,
            data,
            bvecs,
            bvals,
            affine=affine,
            mask=mask,
            scaling_factor=scaling_factor,
            sub_sample=sub_sample,
            params_file=params_file,
            verbose=verbose,
        )

        # If it's a string, assume it's a full path to a nifti file:
        if isinstance(model_coeffs, str):
            self.model_coeffs = ni.load(model_coeffs).get_data()
        else:
            # Otherwise, it had better be an array:
            self.model_coeffs = model_coeffs

        self.L = self._calculate_L(self.model_coeffs.shape[-1])
        self.n_params = self.model_coeffs.shape[-1]

        self.ad = axial_diffusivity
        self.rd = radial_diffusivity

        if axial_diffusivity is None and radial_diffusivity is None and response_file is None:
            self.ad = AD
            self.rd = RD

        elif axial_diffusivity is not None and radial_diffusivity is not None and response_file is not None:
            e_s = "Need to provide information to generate canonical tensor"
            e_s += " *or* path to response file for response function. "
            e_s += "Not both!"
            raise ValueError(e_s)

        self.response_file = response_file
Example #10
0
    def __init__(self,
                 data,
                 bvecs,
                 bvals,
                 params_file=None,
                 axial_diffusivity=AD,
                 radial_diffusivity=RD,
                 affine=None,
                 mask=None,
                 scaling_factor=SCALE_FACTOR,
                 sub_sample=None,
                 over_sample=None,
                 mode='relative_signal',
                 iso_diffusivity=None,
                 verbose=True):
        """
        Initialize a CanonicalTensorModel class instance.

        Parameters
        ----------

        params_file: str, optional
             full path to the name of the file in which to save the model
             parameters, once a model is fit. 

        over_sample: optional, int.
           Sometimes you might want to probe the sphere at a higher resolution
           than that provided by the measurement. You can do that using two
           possible sources of information. The first is the camino points,
           which ship together with osmosis and are used for the boot-strapping
           (see osmosis.boot). These are used for integers smaller than 150,
           for 246 and for 755. The other sources of information are the
           symmetric spheres provided as part of dipy. These are used if 362 or
           642 are provided. Note that these might be problematic, because they
           contain polar opposite points, so use with caution.

        mode: string, optional
        This can take one of several values, determining the form of the
        regressors and the form of the signal to fit to.

        'relative_signal': The fit is to $\frac{S}{S_0}$ and the regressors
        are the relative signal predicted for a canonical tensor and the
        relative signal predicted for a isotropic diffusivity compartment:

        .. math::

           \frac{S}{S_0} = \beta_1 e^{-bD} + \beta_2 e^{-b\vec{b}Q\vec{b}^t}

    
        'signal_attenuation': The fit is to $1-\frac{S}{S_0}$ and the
        regressors are the signal attenuation for the canonical tensor and the
        signal attenuation due to isotropic diffusion:

        .. math::

             1-\frac{S}{S_0} = \beta_1 (1-e^{-bD}) + \beta_2 (1-e^{-b\vec{b} Q \vec{b}^t})

        'normalize': in this case, we fit to $\frac{S}{S_0}$, but our regressor
        set is normalized to maximum of 1 in each columns. This affects the
        values of the weights, and also the goodness-of-fit (because of the
        relative scaling of the regressors in the OLS). The equation in
        this case is: 

        .. math::

             \frac{S}{S_0} = \beta_1 + \beta_2 \frac{e^{-b\vec{b} Q \vec{b}^t}}{max(e^{-b\vec{b} Q \vec{b}^t})}


        'log': in this case, we fit to $log(\frac{S}{S_0})$ and our regressors
        are the exponents:

        .. math::

            log(\frac{S}{S_0}) = \beta_1 -bD + \beta_1 -b\vec{b}Q\vec{b}^t

        iso_diffusivity: optional, float
            What the diffusivity of the isotropic component should be set
            to. This is irrelevant for the 'normalize' mode. Defaults to be
            equal to the axial_diffusivity
              
        """

        # Initialize the super-class:
        BaseModel.__init__(self,
                           data,
                           bvecs,
                           bvals,
                           affine=affine,
                           mask=mask,
                           scaling_factor=scaling_factor,
                           sub_sample=sub_sample,
                           params_file=params_file,
                           verbose=verbose)

        self.ad = axial_diffusivity
        self.rd = radial_diffusivity

        if iso_diffusivity is None:
            iso_diffusivity = axial_diffusivity
        self.iso_diffusivity = iso_diffusivity

        if over_sample is not None:
            # Symmetric spheres from dipy:
            if over_sample in [362, 642]:
                # We want to get these vertices:
                verts = dpd.get_sphere('symmetric%s' % over_sample).vertices
                # Their convention is transposed relative to ours:
                self.rot_vecs = verts.T
            elif (isinstance(over_sample, int)
                  and (over_sample <= 150 or over_sample in [246, 755])):
                self.rot_vecs = ozu.get_camino_pts(over_sample)
            elif over_sample == 'quad132':
                pp = os.path.split(oz.__file__)[0] + '/data/SparseKernelModel/'
                self.rot_vecs = np.loadtxt(pp + 'qsph1-16-132DP.dat')[:, :-1].T
            else:
                e_s = "You asked to sample the sphere in %s" % over_sample
                e_s += " different directions. Can only do that for n<=150"
                e_s += " or n in [246, 362, 642, 755]"
                raise ValueError(e_s)
        else:
            self.rot_vecs = self.bvecs[:, self.b_idx]

        if mode not in [
                'relative_signal', 'signal_attenuation', 'normalize', 'log'
        ]:
            raise ValueError("Not a recognized mode of CanonicalTensorModel")

        self.mode = mode
        self.iso_diffusivity = iso_diffusivity
Example #11
0
    def __init__(self,
                 data,
                 bvecs,
                 bvals,
                 params_file=None,
                 mask=None,
                 scaling_factor=SCALE_FACTOR,
                 sub_sample=None,
                 verbose=True,
                 fit_method='WLS'):
        """
        Parameters
        -----------

        data, bvecs, bvals: see DWI inputs

        scaling_factor: This scales the b value for the Stejskal/Tanner
        equation

        mask: ndarray or file-name
              An array of the same shape as the data, containing a binary mask
              pointing to the locations of voxels that should be analyzed.

        sub_sample: int or array of ints.

           If we want to sub-sample the DWI data on the sphere (in the bvecs),
           we can do one of two things: 

           1. If sub_sample is an integer, that number of random bvecs will be
           chosen from the data.

           2. If an array of indices is provided, these will serve as indices
           into the last dimension of the data and only that part of the data
           will be used


        params_file: A file to cache the initial tensor calculation in. If this
        file already exists, we pull the tensor fit out of it. Otherwise, we
        calculate the tensor fit and save this file with the params of the
        tensor fit.

        fit_method: str
           'WLS' for weighted least squares fitting (default) or 'LS'/'OLS' for
           ordinary least squares.
        
        """
        # Initialize the super-class:
        BaseModel.__init__(self,
                           data,
                           bvecs,
                           bvals,
                           affine=None,
                           mask=mask,
                           scaling_factor=scaling_factor,
                           sub_sample=sub_sample,
                           params_file=params_file,
                           verbose=verbose)

        # Allow using 'OLS' to denote the ordinary least-squares method
        if fit_method == 'OLS':
            fit_method = 'LS'

        self.scaling_factor = scaling_factor
        self.fit_method = fit_method
        self.gtab = gradients.gradient_table(self.bvals, self.bvecs)
Example #12
0
    def __init__(self,
                 data,
                 bvecs,
                 bvals,
                 model_coeffs,
                 params_file=None,
                 axial_diffusivity=None,
                 radial_diffusivity=None,
                 response_file=None,
                 affine=None,
                 mask=None,
                 scaling_factor=SCALE_FACTOR,
                 sub_sample=None,
                 verbose=True):
        """
        Initialize a SphericalHarmonicsModel class instance.
        
        Parameters
        ----------
        DWI: osmosis.dwi.DWI class instance.

        model_coefficients: ndarray
           Coefficients for a SH model, organized according to the conventions
           used by mrtrix (see sph_harm_set for details).
        
        """
        # Initialize the super-class:
        BaseModel.__init__(self,
                           data,
                           bvecs,
                           bvals,
                           affine=affine,
                           mask=mask,
                           scaling_factor=scaling_factor,
                           sub_sample=sub_sample,
                           params_file=params_file,
                           verbose=verbose)

        # If it's a string, assume it's a full path to a nifti file:
        if isinstance(model_coeffs, str):
            self.model_coeffs = ni.load(model_coeffs).get_data()
        else:
            # Otherwise, it had better be an array:
            self.model_coeffs = model_coeffs

        self.L = self._calculate_L(self.model_coeffs.shape[-1])
        self.n_params = self.model_coeffs.shape[-1]

        self.ad = axial_diffusivity
        self.rd = radial_diffusivity

        if (axial_diffusivity is None and radial_diffusivity is None
                and response_file is None):
            self.ad = AD
            self.rd = RD

        elif (axial_diffusivity is not None and radial_diffusivity is not None
              and response_file is not None):
            e_s = "Need to provide information to generate canonical tensor"
            e_s += " *or* path to response file for response function. "
            e_s += "Not both!"
            raise ValueError(e_s)

        self.response_file = response_file
Example #13
0
    def __init__(self,
                 data,
                 bvecs,
                 bvals,
                 params_file=None,
                 mask=None,
                 scaling_factor=SCALE_FACTOR,
                 sub_sample=None,
                 verbose=True,
                 fit_method='WLS'):
        """
        Parameters
        -----------

        data, bvecs, bvals: see DWI inputs

        scaling_factor: This scales the b value for the Stejskal/Tanner
        equation

        mask: ndarray or file-name
              An array of the same shape as the data, containing a binary mask
              pointing to the locations of voxels that should be analyzed.

        sub_sample: int or array of ints.

           If we want to sub-sample the DWI data on the sphere (in the bvecs),
           we can do one of two things: 

           1. If sub_sample is an integer, that number of random bvecs will be
           chosen from the data.

           2. If an array of indices is provided, these will serve as indices
           into the last dimension of the data and only that part of the data
           will be used


        params_file: A file to cache the initial tensor calculation in. If this
        file already exists, we pull the tensor fit out of it. Otherwise, we
        calculate the tensor fit and save this file with the params of the
        tensor fit.

        fit_method: str
           'WLS' for weighted least squares fitting (default) or 'LS'/'OLS' for
           ordinary least squares.
        
        """
        # Initialize the super-class:
        BaseModel.__init__(self,
                           data,
                           bvecs,
                           bvals,
                           affine=None,
                           mask=mask,
                           scaling_factor=scaling_factor,
                           sub_sample=sub_sample,
                           params_file=params_file,
                           verbose=verbose) 

        # Allow using 'OLS' to denote the ordinary least-squares method
        if fit_method=='OLS':
            fit_method = 'LS'
        
        self.scaling_factor = scaling_factor
        self.fit_method = fit_method
        self.gtab = gradients.gradient_table(self.bvals, self.bvecs)