{"action":"created","comment":{"url":"https://api.github.com/repos/nipy/dipy/pulls/comments/30440021","id":30440021,"diff_hunk":"@@ -0,0 +1,666 @@\n+import numpy as np\n+from dipy.reconst.multi_voxel import multi_voxel_fit\n+from scipy.special import hermite, gamma\n+from scipy.misc import factorial, factorial2\n+import dipy.reconst.dti as dti\n+from warnings import warn\n+from dipy.core.gradients import gradient_table\n+from ..utils.optpkg import optional_package\n+\n+cvxopt, have_cvxopt, _ = optional_package(\"cvxopt\")\n+\n+\n+class MapmriModel():\n+\n+    r\"\"\"Mean Apparent Propagator MRI (MAPMRI) [1]_ of the diffusion signal.\n+\n+    The main idea is to model the diffusion signal as a linear combination of\n+    the continuous function presented in [2]_ but extending it in three\n+    dimension.\n+    The main difference with the SHORE proposed in [3]_ is that MAPMRI 3D\n+    extension is provided using a set of three basis function for the radial\n+    part, one for the signal along x, one for y and one for z, while [3]_ \n+    uses one basis function to model the radial part and real Spherical\n+    Harmonics to model the angular part.\n+    From the MAPMRI coefficients is possible to use the analytical formulae \n+    to estimate the ODF.\n+\n+    References\n+    ----------\n+    .. [1] Ozarslan E. et. al, \"Mean apparent propagator (MAP) MRI: A novel\n+           diffusion imaging method for mapping tissue microstructure\",\n+           NeuroImage, 2013.\n+\n+    .. [2] Ozarslan E. et. al, \"Simple harmonic oscillator based reconstruction\n+           and estimation for one-dimensional q-space magnetic resonance\n+           1D-SHORE)\", eapoc Intl Soc Mag Reson Med, vol. 16, p. 35., 2008.\n+\n+    .. [3] Merlet S. et. al, \"Continuous diffusion signal, EAP and ODF\n+           estimation via Compressive Sensing in diffusion MRI\", Medical\n+           Image Analysis, 2013.\n+    \"\"\"\n+\n+    def __init__(self,\n+                 gtab,\n+                 radial_order=4,\n+                 lambd=1e-16,\n+                 eap_cons=False,\n+                 anisotropic_scaling=True,\n+                 eigenvalue_threshold=1e-04,\n+                 bmax_threshold=2000):\n+        r\"\"\" Analytical and continuous modeling of the diffusion signal with\n+        respect to the MAPMRI basis [1]_.\n+\n+        The main idea is to model the diffusion signal as a linear combination of\n+        the continuous functions presented in [2]_ but extending it in three\n+        dimension.\n+\n+        The main difference with the SHORE proposed in [3]_ is that MAPMRI 3D\n+        extension is provided using a set of three basis function for the radial\n+        part, one for the signal along x, one for y and one for z, while [3]_ \n+        uses one basis function to model the radial part and real Spherical\n+        Harmonics to model the angular part.\n+        From the MAPMRI coefficients is possible to use the analytical formulae \n+        to estimate the ODF.\n+\n+\n+        Parameters\n+        ----------\n+        gtab : GradientTable,\n+            gradient directions and bvalues container class\n+        radial_order : unsigned int,\n+            an even integer that represent the order of the basis\n+        lambd : float,\n+            radial regularisation constant\n+        eap_cons : bool,\n+            Constrain the propagator to be positive.\n+        anisotropic_scaling : bool,\n+            If false, force the basis function to be identical in the three\n+            dimensions (SHORE like).\n+        eigenvalue_threshold : float,\n+            set the minimum of the tensor eigenvalues in order to avoid \n+            stability problem\n+        bmax_threshold : float,\n+            set the maximum b-value for the tensor estimation\n+\n+        References\n+        ----------\n+        .. [1] Ozarslan E. et. al, \"Mean apparent propagator (MAP) MRI: A novel\n+               diffusion imaging method for mapping tissue microstructure\",\n+               NeuroImage, 2013.\n+\n+        .. [2] Ozarslan E. et. al, \"Simple harmonic oscillator based reconstruction\n+               and estimation for one-dimensional q-space magnetic resonance\n+               1D-SHORE)\", eapoc Intl Soc Mag Reson Med, vol. 16, p. 35., 2008.\n+\n+        .. [3] Ozarslan E. et. al, \"Simple harmonic oscillator based reconstruction\n+               and estimation for three-dimensional q-space mri\", ISMRM 2009.\n+\n+        Examples\n+        --------\n+        In this example, where the data, gradient table and sphere tessellation\n+        used for reconstruction are provided, we model the diffusion signal\n+        with respect to the MAPMRI model and compute the real and analytical\n+        ODF.\n+\n+        >>> from dipy.core.gradients import gradient_table\n+        >>> from dipy.data import dsi_voxels, get_sphere\n+        >>> data, gtab = dsi_voxels()\n+        >>> sphere = get_sphere('symmetric724')\n+        >>> from dipy.sims.voxel import SticksAndBall\n+        >>> data, golden_directions = SticksAndBall(gtab, d=0.0015, S0=1, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=None)\n+        >>> from dipy.reconst.mapmri import MapmriModel\n+        >>> radial_order = 4\n+        >>> map_model = MapmriModel(gtab, radial_order=radial_order)\n+        >>> mapfit = map_model.fit(data)\n+        >>> odf= mapfit.odf(sphere)\n+        \"\"\"\n+\n+        self.bvals = gtab.bvals\n+        self.bvecs = gtab.bvecs\n+        self.gtab = gtab\n+        self.radial_order = radial_order\n+        self.lambd = lambd\n+        self.eap_cons = eap_cons\n+        self.anisotropic_scaling = anisotropic_scaling\n+        if (gtab.big_delta is None) or (gtab.small_delta is None):\n+            self.tau = 1 / (4 * np.pi ** 2)\n+        else:\n+            self.tau = gtab.big_delta - gtab.small_delta / 3.0\n+        self.eigenvalue_threshold = eigenvalue_threshold\n+\n+        self.ind = self.gtab.bvals <= bmax_threshold\n+        gtab_dti = gradient_table(\n+            self.gtab.bvals[self.ind], self.gtab.bvecs[self.ind, :])\n+        self.tenmodel = dti.TensorModel(gtab_dti)\n+        self.ind_mat = mapmri_index_matrix(self.radial_order)\n+        self.Bm = Bmat(self.ind_mat)\n+\n+    @multi_voxel_fit\n+    def fit(self, data):\n+\n+        tenfit = self.tenmodel.fit(data[..., self.ind])\n+\n+        evals = tenfit.evals\n+        R = tenfit.evecs\n+\n+        ind_evals = np.argsort(evals)[::-1]\n+        evals = evals[ind_evals]\n+        R = R[ind_evals, :]\n+\n+        evals = np.clip(evals, self.eigenvalue_threshold, evals.max())\n+\n+        if self.anisotropic_scaling:\n+            mu = np.sqrt(evals * 2 * self.tau)\n+\n+        else:\n+            mumean = np.sqrt(evals.mean() * 2 * self.tau)\n+            mu = np.array([mumean, mumean, mumean])\n+\n+        qvals = np.sqrt(self.gtab.bvals / self.tau) / (2 * np.pi)\n+        qvecs = np.dot(self.gtab.bvecs, R)\n+        q = qvecs * qvals[:, None]\n+        M = mapmri_phi_matrix(self.radial_order, mu, q.T)\n+\n+        # This is a simple empirical regularization, to be replaced\n+        I = np.diag(self.ind_mat.sum(1)**2)\n+\n+        if self.eap_cons:\n+            if not have_cvxopt:\n+                raise ValueError(\n+                    'CVXOPT package needed to enforce constraints')\n+            import cvxopt.solvers\n+            rmax = 2 * np.sqrt(10 * evals.max() * self.tau)\n+            r_index, r_grad = create_rspace(11, rmax)\n+            K = mapmri_psi_matrix(\n+                self.radial_order,  mu, r_grad[0:len(r_grad) / 2, :])\n+\n+            Q = cvxopt.matrix(np.dot(M.T, M) + self.lambd * I)\n+            p = cvxopt.matrix(-1 * np.dot(M.T, data))\n+            G = cvxopt.matrix(-1 * K)\n+            h = cvxopt.matrix(np.zeros((K.shape[0])), (K.shape[0], 1))\n+            cvxopt.solvers.options['show_progress'] = False\n+            sol = cvxopt.solvers.qp(Q, p, G, h)\n+            if sol['status'] != 'optimal':\n+                warn('Optimization did not find a solution')\n+\n+            coef = np.array(sol['x'])[:, 0]\n+        else:\n+            pseudoInv = np.dot(\n+                np.linalg.inv(np.dot(M.T, M) + self.lambd * I), M.T)\n+            coef = np.dot(pseudoInv, data)\n+\n+        E0 = 0\n+        for i in range(self.ind_mat.shape[0]):\n+            E0 = E0 + coef[i] * self.Bm[i]\n+        coef = coef / E0\n+\n+        return MapmriFit(self, coef, mu, R, self.ind_mat)\n+\n+\n+class MapmriFit():\n+\n+    def __init__(self, model, mapmri_coef, mu, R, ind_mat):\n+        \"\"\" Calculates diffusion properties for a single voxel\n+\n+        Parameters\n+        ----------\n+        model : object,\n+            AnalyticalModel\n+        mapmri_coef : 1d ndarray,\n+            mapmri coefficients\n+        mu : array, shape (3,)\n+            scale parameters vector for x, y and z\n+        R : array, shape (3,3)\n+            rotation matrix\n+        ind_mat : array, shape (N,3)\n+            indices of the basis for x, y and z\n+        \"\"\"\n+\n+        self.model = model\n+        self._mapmri_coef = mapmri_coef\n+        self.gtab = model.gtab\n+        self.radial_order = model.radial_order\n+        self.mu = mu\n+        self.R = R\n+        self.ind_mat = ind_mat\n+\n+    @property\n+    def mapmri_mu(self):\n+        \"\"\"The MAPMRI scale factors\n+        \"\"\"\n+        return self.mu\n+\n+    @property\n+    def mapmri_R(self):\n+        \"\"\"The MAPMRI rotation matrix\n+        \"\"\"\n+        return self.R\n+\n+    @property\n+    def mapmri_coeff(self):\n+        \"\"\"The MAPMRI coefficients\n+        \"\"\"\n+        return self._mapmri_coef\n+\n+    def odf(self, sphere, s=0):\n+        r\"\"\" Calculates the analytical Orientation Distribution Function (ODF)\n+        from the signal [1]_ Eq. 32.\n+\n+        Parameters\n+        ----------\n+        s: unsigned int\n+            radial moment of the ODF\n+\n+        References\n+        ----------\n+        .. [1] Ozarslan E. et. al, \"Mean apparent propagator (MAP) MRI: A novel\n+        diffusion imaging method for mapping tissue microstructure\",\n+        NeuroImage, 2013.\n+        \"\"\"\n+\n+        v_ = sphere.vertices\n+        v = np.dot(v_, self.R)\n+        I_s = mapmri_odf_matrix(self.radial_order, self.mu, s, v)\n+        odf = np.dot(I_s, self._mapmri_coef)\n+        return np.clip(odf, 0, None)\n+\n+    def predict(self, gtab, S0=1.0):\n+        \"\"\"\n+        Predict a signal for this MapmriModel class instance given a gradient\n+        table.\n+\n+        Parameters\n+        ----------\n+        gtab : GradientTable,\n+            gradient directions and bvalues container class\n+\n+        S0 : float or ndarray\n+            The non diffusion-weighted signal in every voxel, or across all\n+            voxels. Default: 1\n+        \"\"\"\n+        if (gtab.big_delta is None) or (gtab.small_delta is None):\n+            tau = 1 / (4 * np.pi ** 2)\n+        else:\n+            tau = gtab.big_delta - gtab.small_delta / 3.0\n+\n+        qvals = np.sqrt(gtab.bvals / tau) / (2 * np.pi)\n+        qvecs = np.dot(gtab.bvecs, self.R)\n+        q = qvecs * qvals[:, None]\n+\n+        s_mat = mapmri_phi_matrix(self.radial_order, self.mu, q.T)\n+        S_reconst = S0 * np.dot(s_mat, self._mapmri_coef)\n+\n+        return S_reconst\n+\n+\n+def mapmri_index_matrix(radial_order):\n+    r\"\"\" Calculates the indices for the MAPMRI [1]_ basis in x, y and z.\n+\n+    Parameters\n+    ----------\n+    radial_order: unsigned int\n+        radial order of MAPMRI basis\n+\n+    Returns\n+    -------\n+    index_matrix: array, shape (N,3)\n+        ordering of the basis in x, y, z\n+\n+    References\n+    ----------\n+    .. [1] Ozarslan E. et. al, \"Mean apparent propagator (MAP) MRI: A novel\n+    diffusion imaging method for mapping tissue microstructure\",\n+    NeuroImage, 2013.\n+    \"\"\"\n+    index_matrix = []\n+    for n in range(0, radial_order + 1, 2):\n+        for i in range(0, n + 1):\n+            for j in range(0, n - i + 1):\n+                index_matrix.append([n - i - j, j, i])\n+\n+    return np.array(index_matrix)\n+\n+\n+def Bmat(ind_mat):\n+    r\"\"\" Calculates the B coefficients from [1]_ Eq. 27.\n+\n+    Parameters\n+    -------\n+    index_matrix: array, shape (N,3)\n+        ordering of the basis in x, y, z\n+\n+    Returns\n+    -------\n+    B: array, shape (N,)\n+        B coefficients for the basis\n+\n+    References\n+    ----------\n+    .. [1] Ozarslan E. et. al, \"Mean apparent propagator (MAP) MRI: A novel\n+    diffusion imaging method for mapping tissue microstructure\",\n+    NeuroImage, 2013.\n+    \"\"\"\n+\n+    B = np.zeros(ind_mat.shape[0])\n+    for i in range(ind_mat.shape[0]):\n+        n1, n2, n3 = ind_mat[i]\n+        K = int(not(n1 % 2) and not(n2 % 2) and not(n3 % 2))\n+        B[i] = K * np.sqrt(factorial(n1) * factorial(n2) * factorial(n3)\n+                           ) / (factorial2(n1) * factorial2(n2) * factorial2(n3))\n+\n+    return B\n+\n+\n+def mapmri_phi_1d(n, q, mu):\n+    r\"\"\" One dimensional MAPMRI basis function from [1]_ Eq. 4.\n+\n+    Parameters\n+    -------\n+    n: unsigned int\n+        order of the basis\n+    q: array, shape (N,)\n+        points in the q-space in which evaluate the basis\n+    mu: float\n+        scale factor of the basis\n+\n+\n+    References\n+    ----------\n+    .. [1] Ozarslan E. et. al, \"Mean apparent propagator (MAP) MRI: A novel\n+    diffusion imaging method for mapping tissue microstructure\",\n+    NeuroImage, 2013.\n+    \"\"\"\n+\n+    qn = 2 * np.pi * mu * q\n+    H = hermite(n)(qn)\n+    i = np.complex(0, 1)\n+    f = factorial(n)\n+\n+    k = i ** (-n) / np.sqrt(2 ** (n) * f)\n+    phi = k * np.exp(- qn ** 2 / 2) * H\n+\n+    return phi\n+\n+\n+def mapmri_phi_3d(n, q, mu):\n+    r\"\"\" Three dimensional MAPMRI basis function from [1]_ Eq. 23.\n+\n+    Parameters\n+    -------\n+    n: array, shape (3,)\n+        order of the basis function for x, y, z\n+    q: array, shape (N,3)\n+        points in the q-space in which evaluate the basis\n+    mu: array, shape (3,)\n+        scale factors of the basis for x, y, z\n+\n+\n+    References\n+    ----------\n+    .. [1] Ozarslan E. et. al, \"Mean apparent propagator (MAP) MRI: A novel\n+    diffusion imaging method for mapping tissue microstructure\",\n+    NeuroImage, 2013.\n+    \"\"\"\n+\n+    n1, n2, n3 = n\n+    qx, qy, qz = q\n+    mux, muy, muz = mu\n+    phi = mapmri_phi_1d\n+    return np.real(phi(n1, qx, mux) * phi(n2, qy, muy) * phi(n3, qz, muz))\n+\n+\n+def mapmri_phi_matrix(radial_order, mu, q_gradients):\n+    r\"\"\"Compute the MAPMRI phi matrix for the signal [1]_\n+\n+    Parameters\n+    ----------\n+    radial_order : unsigned int,\n+        an even integer that represent the order of the basis\n+    mu: array, shape (3,)\n+        scale factors of the basis for x, y, z\n+    q_gradients: array, shape (N,3)\n+        points in the q-space in which evaluate the basis\n+\n+\n+    References\n+    ----------\n+    .. [1] Ozarslan E. et. al, \"Mean apparent propagator (MAP) MRI: A novel\n+    diffusion imaging method for mapping tissue microstructure\",\n+    NeuroImage, 2013.\n+    \"\"\"\n+\n+    ind_mat = mapmri_index_matrix(radial_order)\n+    n_elem = ind_mat.shape[0]\n+    n_qgrad = q_gradients.shape[1]\n+    M = np.zeros((n_qgrad, n_elem))\n+    for j in range(n_elem):\n+        M[:, j] = mapmri_phi_3d(ind_mat[j], q_gradients, mu)\n+\n+    return M\n+\n+\n+def mapmri_psi_1d(n, x, mu):\n+    r\"\"\" One dimensional MAPMRI propagator basis function from [1]_ Eq. 10.\n+\n+    Parameters\n+    -------\n+    n: unsigned int\n+        order of the basis\n+    x: array, shape (N,)\n+        points in the r-space in which evaluate the basis\n+    mu: float\n+        scale factor of the basis\n+\n+\n+    References\n+    ----------\n+    .. [1] Ozarslan E. et. al, \"Mean apparent propagator (MAP) MRI: A novel\n+    diffusion imaging method for mapping tissue microstructure\",\n+    NeuroImage, 2013.\n+    \"\"\"\n+\n+    H = hermite(n)(x / mu)\n+    f = factorial(n)\n+    k = 1 / (np.sqrt(2 ** (n + 1) * np.pi * f) * mu)\n+    psi = k * np.exp(- x ** 2 / (2 * mu ** 2)) * H\n+\n+    return psi\n+\n+\n+def mapmri_psi_3d(n, r, mu):\n+    r\"\"\" Three dimensional MAPMRI propagator basis function from [1]_ Eq. 22.\n+\n+    Parameters\n+    -------\n+    n: array, shape (3,)\n+        order of the basis function for x, y, z\n+    q: array, shape (N,3)\n+        points in the q-space in which evaluate the basis\n+    mu: array, shape (3,)\n+        scale factors of the basis for x, y, z\n+\n+\n+    References\n+    ----------\n+    .. [1] Ozarslan E. et. al, \"Mean apparent propagator (MAP) MRI: A novel\n+    diffusion imaging method for mapping tissue microstructure\",\n+    NeuroImage, 2013.\n+    \"\"\"\n+    n1, n2, n3 = n\n+    x, y, z = r.T\n+    mux, muy, muz = mu\n+    psi = mapmri_psi_1d\n+    return psi(n1, x, mux) * psi(n2, y, muy) * psi(n3, z, muz)\n+\n+\n+def mapmri_psi_matrix(radial_order, mu, rgrad):\n+    r\"\"\"Compute the MAPMRI psi matrix for the propagator [1]_\n+\n+\n+    Parameters\n+    ----------\n+    radial_order : unsigned int,\n+        an even integer that represent the order of the basis\n+    mu: array, shape (3,)\n+        scale factors of the basis for x, y, z\n+    rgrad: array, shape (N,3)\n+        points in the r-space in which evaluate the EAP\n+\n+\n+    References\n+    ----------\n+    .. [1] Ozarslan E. et. al, \"Mean apparent propagator (MAP) MRI: A novel\n+    diffusion imaging method for mapping tissue microstructure\",\n+    NeuroImage, 2013.\n+    \"\"\"\n+\n+    ind_mat = mapmri_index_matrix(radial_order)\n+    n_elem = ind_mat.shape[0]\n+    n_rgrad = rgrad.shape[0]\n+    K = np.zeros((n_rgrad, n_elem))\n+    for j in range(n_elem):\n+        K[:, j] = mapmri_psi_3d(ind_mat[j], rgrad, mu)\n+\n+    return K\n+\n+\n+def mapmri_odf_matrix(radial_order, mu, s, vertices):\n+    r\"\"\"Compute the MAPMRI ODF matrix [1]_  Eq. 33.\n+\n+    Parameters\n+    ----------\n+    radial_order : unsigned int,\n+        an even integer that represent the order of the basis\n+    mu: array, shape (3,)\n+        scale factors of the basis for x, y, z\n+    s: unsigned int\n+        radial moment of the ODF\n+    vertices: array, shape (N,3)\n+        points of the sphere shell in the r-space in which evaluate the ODF\n+\n+\n+    References\n+    ----------\n+    .. [1] Ozarslan E. et. al, \"Mean apparent propagator (MAP) MRI: A novel\n+    diffusion imaging method for mapping tissue microstructure\",\n+    NeuroImage, 2013.\n+    \"\"\"\n+\n+    ind_mat = mapmri_index_matrix(radial_order)\n+    n_vert = vertices.shape[0]\n+    n_elem = ind_mat.shape[0]\n+    odf_mat = np.zeros((n_vert, n_elem))\n+    mux, muy, muz = mu\n+    # Eq, 35a\n+    rho = 1.0 / np.sqrt((vertices[:, 0] / mux) ** 2 +\n+                        (vertices[:, 1] / muy) ** 2 + (vertices[:, 2] / muz) ** 2)\n+    # Eq, 35b\n+    alpha = 2 * rho * (vertices[:, 0] / mux)\n+    # Eq, 35c\n+    beta = 2 * rho * (vertices[:, 1] / muy)\n+    # Eq, 35d\n+    gamma = 2 * rho * (vertices[:, 2] / muz)\n+    const = rho ** (3 + s) / np.sqrt(2 ** (2 - s) * np.pi **\n+                                     3 * (mux ** 2 * muy ** 2 * muz ** 2))\n+    for j in range(n_elem):\n+        n1, n2, n3 = ind_mat[j]\n+        f = np.sqrt(factorial(n1) * factorial(n2) * factorial(n3))\n+        odf_mat[:, j] = const * f * \\\n+            _odf_cfunc(n1, n2, n3, alpha, beta, gamma, s)\n+\n+    return odf_mat\n+\n+\n+def _odf_cfunc(n1, n2, n3, a, b, g, s):\n+    r\"\"\"Compute the MAPMRI ODF function from [1]_  Eq. 34.\n+\n+    References\n+    ----------\n+    .. [1] Ozarslan E. et. al, \"Mean apparent propagator (MAP) MRI: A novel\n+    diffusion imaging method for mapping tissue microstructure\",\n+    NeuroImage, 2013.\n+    \"\"\"\n+\n+    f = factorial\n+    f2 = factorial2\n+    sumc = 0\n+    for i in range(0, n1 + 1, 2):\n+        for j in range(0, n2 + 1, 2):\n+            for k in range(0, n3 + 1, 2):","path":"dipy/reconst/mapmri.py","position":590,"original_position":590,"commit_id":"9ae7f46e244ef460b2cd3cf2a9af70c52116b68d","original_commit_id":"9ae7f46e244ef460b2cd3cf2a9af70c52116b68d","user":{"login":"Garyfallidis","id":134276,"avatar_url":"https://avatars.githubusercontent.com/u/134276?v=3","gravatar_id":"","url":"https://api.github.com/users/Garyfallidis","html_url":"https://github.com/Garyfallidis","followers_url":"https://api.github.com/users/Garyfallidis/followers","following_url":"https://api.github.com/users/Garyfallidis/following{/other_user}","gists_url":"https://api.github.com/users/Garyfallidis/gists{/gist_id}","starred_url":"https://api.github.com/users/Garyfallidis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Garyfallidis/subscriptions","organizations_url":"https://api.github.com/users/Garyfallidis/orgs","repos_url":"https://api.github.com/users/Garyfallidis/repos","events_url":"https://api.github.com/users/Garyfallidis/events{/privacy}","received_events_url":"https://api.github.com/users/Garyfallidis/received_events","type":"User","site_admin":false},"body":"It looks very easy to cythonize. If performance is an issue we could have this as a future TODO. Not for this PR.","created_at":"2015-05-15T19:46:44Z","updated_at":"2015-05-15T19:46:44Z","html_url":"https://github.com/nipy/dipy/pull/640#discussion_r30440021","pull_request_url":"https://api.github.com/repos/nipy/dipy/pulls/640","_links":{"self":{"href":"https://api.github.com/repos/nipy/dipy/pulls/comments/30440021"},"html":{"href":"https://github.com/nipy/dipy/pull/640#discussion_r30440021"},"pull_request":{"href":"https://api.github.com/repos/nipy/dipy/pulls/640"}}},"pull_request":{"url":"https://api.github.com/repos/nipy/dipy/pulls/640","id":34529181,"html_url":"https://github.com/nipy/dipy/pull/640","diff_url":"https://github.com/nipy/dipy/pull/640.diff","patch_url":"https://github.com/nipy/dipy/pull/640.patch","issue_url":"https://api.github.com/repos/nipy/dipy/issues/640","number":640,"state":"open","locked":false,"title":"MAPMRI","user":{"login":"maurozucchelli","id":5042250,"avatar_url":"https://avatars.githubusercontent.com/u/5042250?v=3","gravatar_id":"","url":"https://api.github.com/users/maurozucchelli","html_url":"https://github.com/maurozucchelli","followers_url":"https://api.github.com/users/maurozucchelli/followers","following_url":"https://api.github.com/users/maurozucchelli/following{/other_user}","gists_url":"https://api.github.com/users/maurozucchelli/gists{/gist_id}","starred_url":"https://api.github.com/users/maurozucchelli/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maurozucchelli/subscriptions","organizations_url":"https://api.github.com/users/maurozucchelli/orgs","repos_url":"https://api.github.com/users/maurozucchelli/repos","events_url":"https://api.github.com/users/maurozucchelli/events{/privacy}","received_events_url":"https://api.github.com/users/maurozucchelli/received_events","type":"User","site_admin":false},"body":"Hi everybody, this pull request add the minimal MAPMRI bases for signal reconstruction and ODF estimation. The fit works using cvxopt as an optional package as in shore.py, but since in this method the regularization of the basis is just empirical, adding positivity constraints should be strongly recommended. \r\n\r\nAfter this pull request I will add all the other indexes proposed in Ozarslan et al. Neuroimage 2013 like:\r\nRTOP\r\nRTAP\r\nRTPP\r\nNG\r\nPA\r\nplus a proper regularization. \r\n\r\nThank you, best wishes\r\n\r\n\r\nMauro","created_at":"2015-05-01T09:39:44Z","updated_at":"2015-05-15T19:46:44Z","closed_at":null,"merged_at":null,"merge_commit_sha":"101a6c638e27dc5d25167ef9dd47d9d3e495b805","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/nipy/dipy/pulls/640/commits","review_comments_url":"https://api.github.com/repos/nipy/dipy/pulls/640/comments","review_comment_url":"https://api.github.com/repos/nipy/dipy/pulls/comments{/number}","comments_url":"https://api.github.com/repos/nipy/dipy/issues/640/comments","statuses_url":"https://api.github.com/repos/nipy/dipy/statuses/9ae7f46e244ef460b2cd3cf2a9af70c52116b68d","head":{"label":"maurozucchelli:mapmri","ref":"mapmri","sha":"9ae7f46e244ef460b2cd3cf2a9af70c52116b68d","user":{"login":"maurozucchelli","id":5042250,"avatar_url":"https://avatars.githubusercontent.com/u/5042250?v=3","gravatar_id":"","url":"https://api.github.com/users/maurozucchelli","html_url":"https://github.com/maurozucchelli","followers_url":"https://api.github.com/users/maurozucchelli/followers","following_url":"https://api.github.com/users/maurozucchelli/following{/other_user}","gists_url":"https://api.github.com/users/maurozucchelli/gists{/gist_id}","starred_url":"https://api.github.com/users/maurozucchelli/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maurozucchelli/subscriptions","organizations_url":"https://api.github.com/users/maurozucchelli/orgs","repos_url":"https://api.github.com/users/maurozucchelli/repos","events_url":"https://api.github.com/users/maurozucchelli/events{/privacy}","received_events_url":"https://api.github.com/users/maurozucchelli/received_events","type":"User","site_admin":false},"repo":{"id":11644464,"name":"dipy","full_name":"maurozucchelli/dipy","owner":{"login":"maurozucchelli","id":5042250,"avatar_url":"https://avatars.githubusercontent.com/u/5042250?v=3","gravatar_id":"","url":"https://api.github.com/users/maurozucchelli","html_url":"https://github.com/maurozucchelli","followers_url":"https://api.github.com/users/maurozucchelli/followers","following_url":"https://api.github.com/users/maurozucchelli/following{/other_user}","gists_url":"https://api.github.com/users/maurozucchelli/gists{/gist_id}","starred_url":"https://api.github.com/users/maurozucchelli/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maurozucchelli/subscriptions","organizations_url":"https://api.github.com/users/maurozucchelli/orgs","repos_url":"https://api.github.com/users/maurozucchelli/repos","events_url":"https://api.github.com/users/maurozucchelli/events{/privacy}","received_events_url":"https://api.github.com/users/maurozucchelli/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/maurozucchelli/dipy","description":"Diffusion MR Imaging in Python","fork":true,"url":"https://api.github.com/repos/maurozucchelli/dipy","forks_url":"https://api.github.com/repos/maurozucchelli/dipy/forks","keys_url":"https://api.github.com/repos/maurozucchelli/dipy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/maurozucchelli/dipy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/maurozucchelli/dipy/teams","hooks_url":"https://api.github.com/repos/maurozucchelli/dipy/hooks","issue_events_url":"https://api.github.com/repos/maurozucchelli/dipy/issues/events{/number}","events_url":"https://api.github.com/repos/maurozucchelli/dipy/events","assignees_url":"https://api.github.com/repos/maurozucchelli/dipy/assignees{/user}","branches_url":"https://api.github.com/repos/maurozucchelli/dipy/branches{/branch}","tags_url":"https://api.github.com/repos/maurozucchelli/dipy/tags","blobs_url":"https://api.github.com/repos/maurozucchelli/dipy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/maurozucchelli/dipy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/maurozucchelli/dipy/git/refs{/sha}","trees_url":"https://api.github.com/repos/maurozucchelli/dipy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/maurozucchelli/dipy/statuses/{sha}","languages_url":"https://api.github.com/repos/maurozucchelli/dipy/languages","stargazers_url":"https://api.github.com/repos/maurozucchelli/dipy/stargazers","contributors_url":"https://api.github.com/repos/maurozucchelli/dipy/contributors","subscribers_url":"https://api.github.com/repos/maurozucchelli/dipy/subscribers","subscription_url":"https://api.github.com/repos/maurozucchelli/dipy/subscription","commits_url":"https://api.github.com/repos/maurozucchelli/dipy/commits{/sha}","git_commits_url":"https://api.github.com/repos/maurozucchelli/dipy/git/commits{/sha}","comments_url":"https://api.github.com/repos/maurozucchelli/dipy/comments{/number}","issue_comment_url":"https://api.github.com/repos/maurozucchelli/dipy/issues/comments{/number}","contents_url":"https://api.github.com/repos/maurozucchelli/dipy/contents/{+path}","compare_url":"https://api.github.com/repos/maurozucchelli/dipy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/maurozucchelli/dipy/merges","archive_url":"https://api.github.com/repos/maurozucchelli/dipy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/maurozucchelli/dipy/downloads","issues_url":"https://api.github.com/repos/maurozucchelli/dipy/issues{/number}","pulls_url":"https://api.github.com/repos/maurozucchelli/dipy/pulls{/number}","milestones_url":"https://api.github.com/repos/maurozucchelli/dipy/milestones{/number}","notifications_url":"https://api.github.com/repos/maurozucchelli/dipy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/maurozucchelli/dipy/labels{/name}","releases_url":"https://api.github.com/repos/maurozucchelli/dipy/releases{/id}","created_at":"2013-07-24T20:24:51Z","updated_at":"2014-04-11T19:49:40Z","pushed_at":"2015-05-15T15:23:53Z","git_url":"git://github.com/maurozucchelli/dipy.git","ssh_url":"git@github.com:maurozucchelli/dipy.git","clone_url":"https://github.com/maurozucchelli/dipy.git","svn_url":"https://github.com/maurozucchelli/dipy","homepage":"http://dipy.org","size":15814,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"nipy:master","ref":"master","sha":"ff9c828ed9a62404d55b839da3c306cf9e117985","user":{"login":"nipy","id":233707,"avatar_url":"https://avatars.githubusercontent.com/u/233707?v=3","gravatar_id":"","url":"https://api.github.com/users/nipy","html_url":"https://github.com/nipy","followers_url":"https://api.github.com/users/nipy/followers","following_url":"https://api.github.com/users/nipy/following{/other_user}","gists_url":"https://api.github.com/users/nipy/gists{/gist_id}","starred_url":"https://api.github.com/users/nipy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nipy/subscriptions","organizations_url":"https://api.github.com/users/nipy/orgs","repos_url":"https://api.github.com/users/nipy/repos","events_url":"https://api.github.com/users/nipy/events{/privacy}","received_events_url":"https://api.github.com/users/nipy/received_events","type":"Organization","site_admin":false},"repo":{"id":505209,"name":"dipy","full_name":"nipy/dipy","owner":{"login":"nipy","id":233707,"avatar_url":"https://avatars.githubusercontent.com/u/233707?v=3","gravatar_id":"","url":"https://api.github.com/users/nipy","html_url":"https://github.com/nipy","followers_url":"https://api.github.com/users/nipy/followers","following_url":"https://api.github.com/users/nipy/following{/other_user}","gists_url":"https://api.github.com/users/nipy/gists{/gist_id}","starred_url":"https://api.github.com/users/nipy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nipy/subscriptions","organizations_url":"https://api.github.com/users/nipy/orgs","repos_url":"https://api.github.com/users/nipy/repos","events_url":"https://api.github.com/users/nipy/events{/privacy}","received_events_url":"https://api.github.com/users/nipy/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/nipy/dipy","description":"Diffusion MR Imaging in Python","fork":false,"url":"https://api.github.com/repos/nipy/dipy","forks_url":"https://api.github.com/repos/nipy/dipy/forks","keys_url":"https://api.github.com/repos/nipy/dipy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nipy/dipy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nipy/dipy/teams","hooks_url":"https://api.github.com/repos/nipy/dipy/hooks","issue_events_url":"https://api.github.com/repos/nipy/dipy/issues/events{/number}","events_url":"https://api.github.com/repos/nipy/dipy/events","assignees_url":"https://api.github.com/repos/nipy/dipy/assignees{/user}","branches_url":"https://api.github.com/repos/nipy/dipy/branches{/branch}","tags_url":"https://api.github.com/repos/nipy/dipy/tags","blobs_url":"https://api.github.com/repos/nipy/dipy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nipy/dipy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nipy/dipy/git/refs{/sha}","trees_url":"https://api.github.com/repos/nipy/dipy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nipy/dipy/statuses/{sha}","languages_url":"https://api.github.com/repos/nipy/dipy/languages","stargazers_url":"https://api.github.com/repos/nipy/dipy/stargazers","contributors_url":"https://api.github.com/repos/nipy/dipy/contributors","subscribers_url":"https://api.github.com/repos/nipy/dipy/subscribers","subscription_url":"https://api.github.com/repos/nipy/dipy/subscription","commits_url":"https://api.github.com/repos/nipy/dipy/commits{/sha}","git_commits_url":"https://api.github.com/repos/nipy/dipy/git/commits{/sha}","comments_url":"https://api.github.com/repos/nipy/dipy/comments{/number}","issue_comment_url":"https://api.github.com/repos/nipy/dipy/issues/comments{/number}","contents_url":"https://api.github.com/repos/nipy/dipy/contents/{+path}","compare_url":"https://api.github.com/repos/nipy/dipy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nipy/dipy/merges","archive_url":"https://api.github.com/repos/nipy/dipy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nipy/dipy/downloads","issues_url":"https://api.github.com/repos/nipy/dipy/issues{/number}","pulls_url":"https://api.github.com/repos/nipy/dipy/pulls{/number}","milestones_url":"https://api.github.com/repos/nipy/dipy/milestones{/number}","notifications_url":"https://api.github.com/repos/nipy/dipy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nipy/dipy/labels{/name}","releases_url":"https://api.github.com/repos/nipy/dipy/releases{/id}","created_at":"2010-02-06T11:43:08Z","updated_at":"2015-04-30T05:53:35Z","pushed_at":"2015-05-15T15:23:53Z","git_url":"git://github.com/nipy/dipy.git","ssh_url":"git@github.com:nipy/dipy.git","clone_url":"https://github.com/nipy/dipy.git","svn_url":"https://github.com/nipy/dipy","homepage":"http://dipy.org","size":21840,"stargazers_count":60,"watchers_count":60,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":88,"mirror_url":null,"open_issues_count":79,"forks":88,"open_issues":79,"watchers":60,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/nipy/dipy/pulls/640"},"html":{"href":"https://github.com/nipy/dipy/pull/640"},"issue":{"href":"https://api.github.com/repos/nipy/dipy/issues/640"},"comments":{"href":"https://api.github.com/repos/nipy/dipy/issues/640/comments"},"review_comments":{"href":"https://api.github.com/repos/nipy/dipy/pulls/640/comments"},"review_comment":{"href":"https://api.github.com/repos/nipy/dipy/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/nipy/dipy/pulls/640/commits"},"statuses":{"href":"https://api.github.com/repos/nipy/dipy/statuses/9ae7f46e244ef460b2cd3cf2a9af70c52116b68d"}}}}