From 3f210a06ef681576357a16b09b27954f20506603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sun, 28 Jul 2024 14:47:38 -0400 Subject: [PATCH 01/17] DOC: Enclose an emphasis-containing string inside double backticks Enclose an emphasis-containing string inside double backticks to avoid a warning about an unended emphasis markup opening. Fixes: ``` /dipy/dipy/doc/index.rst:99: WARNING: Inline emphasis start-string without end-string. ``` raised for example in: https://github.com/dipy/dipy/actions/runs/9982200633/job/27587486843#step:5:805 --- doc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index 04098ac64a..7ec99e4c9d 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -96,7 +96,7 @@ Highlights - DeepN4 novel DL-based N4 Bias Correction method added. - Multiple Workflows added. - Large update of DIPY Horizon features. -- Pytest for Cython files(*.pyx) added. +- Pytest for Cython files (``*.pyx``) added. - Large documentation update. - Support of Python 3.8 removed. - Closed 142 issues and merged 60 pull requests. From 13fbfb54bb07cdbe2e5322b61eff9de62777b52f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sun, 28 Jul 2024 13:43:11 -0400 Subject: [PATCH 02/17] DOC: Make title underline length match the title length Make title underline length match the title length. Fixes: ``` /home/runner/work/dipy/dipy/doc/api_changes.rst:9: WARNING: Title underline too short. DIPY 1.10.0 changes ------------------ ``` and similar warnings raised for example in: https://github.com/dipy/dipy/actions/runs/9982200633/job/27587486843#step:5:680 --- doc/api_changes.rst | 2 +- doc/examples/_valid_examples.toml | 2 +- doc/examples/denoise_mppca.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/api_changes.rst b/doc/api_changes.rst index f0626e4181..1a2f21d0fc 100644 --- a/doc/api_changes.rst +++ b/doc/api_changes.rst @@ -6,7 +6,7 @@ Here we provide information about functions or classes that have been removed, renamed or are deprecated (not recommended) during different release circles. DIPY 1.10.0 changes ------------------- +------------------- **Reconstruction** diff --git a/doc/examples/_valid_examples.toml b/doc/examples/_valid_examples.toml index 0dee7b2ff8..e5b3a8ad90 100644 --- a/doc/examples/_valid_examples.toml +++ b/doc/examples/_valid_examples.toml @@ -263,7 +263,7 @@ files = [ [workflows] readme = """ Workflows --------- +--------- """ position = 37 diff --git a/doc/examples/denoise_mppca.py b/doc/examples/denoise_mppca.py index be9d011a9a..52f175a39a 100644 --- a/doc/examples/denoise_mppca.py +++ b/doc/examples/denoise_mppca.py @@ -187,7 +187,7 @@ # # # Noise standard deviation estimation using the Marchenko-Pastur PCA algorithm -# =========================================================================== +# ============================================================================ # # As mentioned above, the Marcenko-Pastur PCA algorithm can also be used to # estimate the image's noise standard deviation (std). The noise std From db33d9a06047e2d25ea193b1f2dec2dd938733b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 27 Jul 2024 11:47:12 -0400 Subject: [PATCH 03/17] DOC: Fix math expression indentation in `dki` module Fix math expression indentation in `dki` module docstrings. --- dipy/reconst/dki.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dipy/reconst/dki.py b/dipy/reconst/dki.py index 8d867ef04a..a8d7659427 100644 --- a/dipy/reconst/dki.py +++ b/dipy/reconst/dki.py @@ -1038,8 +1038,8 @@ def radial_kurtosis( .. math:: - RK \equiv \frac{1}{2\pi} \int d\Omega _\mathbf{\theta} K(\mathbf{\theta}) - \delta (\mathbf{\theta}\cdot \mathbf{e}_1) + RK \equiv \frac{1}{2\pi} \int d\Omega _\mathbf{\theta} K(\mathbf{\theta}) + \delta (\mathbf{\theta}\cdot \mathbf{e}_1) This equation can be numerically computed by averaging apparent directional kurtosis samples for directions perpendicular to e1. [2]_ @@ -2246,8 +2246,8 @@ def rk(self, min_kurtosis=-3.0 / 7, max_kurtosis=10, analytical=True): .. math:: - RK \equiv \frac{1}{2\pi} \int d\Omega _\mathbf{\theta} - K(\mathbf{\theta}) \delta (\mathbf{\theta}\cdot \mathbf{e}_1) + RK \equiv \frac{1}{2\pi} \int d\Omega _\mathbf{\theta} + K(\mathbf{\theta}) \delta (\mathbf{\theta}\cdot \mathbf{e}_1) This equation can be numerically computed by averaging apparent directional kurtosis samples for directions perpendicular to e1 [2]_. From 0f408b59ee5b77f4ea93ab3bfd67e997e34d1077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 27 Jul 2024 12:22:28 -0400 Subject: [PATCH 04/17] DOC: Fix LaTeX formatting for symmetric, rank 4 isotropic tensor in KFA Fix LaTeX formatting for symmetric, rank 4 isotropic tensor in KFA: add the missing curly brackets for the exponentiation. --- dipy/reconst/dki.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dipy/reconst/dki.py b/dipy/reconst/dki.py index a8d7659427..0839b37ba6 100644 --- a/dipy/reconst/dki.py +++ b/dipy/reconst/dki.py @@ -1615,7 +1615,7 @@ def kurtosis_fractional_anisotropy(dki_params): KFA \equiv \frac{||\mathbf{W} - MKT \mathbf{I}^{(4)}||_F}{||\mathbf{W}||_F} - where $W$ is the kurtosis tensor, MKT the kurtosis tensor mean, $I^(4)$ is + where $W$ is the kurtosis tensor, MKT the kurtosis tensor mean, $I^{(4)}$ is the fully symmetric rank 2 isotropic tensor and $||...||_F$ is the tensor's Frobenius norm [1]_. @@ -2433,7 +2433,7 @@ def kfa(self): KFA \equiv \frac{||\mathbf{W} - MKT \mathbf{I}^{(4)}||_F}{||\mathbf{W}||_F} - where $W$ is the kurtosis tensor, MKT the kurtosis tensor mean, $I^(4)$ + where $W$ is the kurtosis tensor, MKT the kurtosis tensor mean, $I^{(4)}$ is the fully symmetric rank 2 isotropic tensor and $||...||_F$ is the tensor's Frobenius norm [1]_. From 4579f4f7ac17c42c4234e96db0725f3199d77b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 27 Jul 2024 10:46:14 -0400 Subject: [PATCH 05/17] DOC: Mark docstrings with math expressions as raw strings in `dti` Mark docstrings with math expresssions as raw strings in `dti` module. Documentation: https://sphinx-rtd-trial.readthedocs.io/en/latest/ext/math.html#module-sphinx.ext.mathbase --- dipy/reconst/dti.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dipy/reconst/dti.py b/dipy/reconst/dti.py index de5e6fb911..da8f675e94 100755 --- a/dipy/reconst/dti.py +++ b/dipy/reconst/dti.py @@ -649,7 +649,7 @@ def apparent_diffusion_coef(q_form, sphere): def tensor_prediction(dti_params, gtab, S0): - """ + r""" Predict a signal given tensor parameters. Parameters @@ -1187,7 +1187,7 @@ def odf(self, sphere): return odf def adc(self, sphere): - """ + r""" Calculate the apparent diffusion coefficient (ADC) in each direction on the sphere for each voxel in the data @@ -1215,7 +1215,7 @@ def adc(self, sphere): return apparent_diffusion_coef(self.quadratic_form, sphere) def predict(self, gtab, S0=None, step=None): - """ + r""" Given a model fit, predict the signal on the vertices of a sphere Parameters From 21894be0616ee4bd1195cf3d84eadfd1b0b14af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 27 Jul 2024 10:43:10 -0400 Subject: [PATCH 06/17] DOC: Use `.. math::` consistently for displayed mathematical expressions Use `.. math::` consistently for displayed mathematical expressions. Documentation: https://sphinx-rtd-trial.readthedocs.io/en/latest/ext/math.html --- dipy/denoise/localpca.py | 4 ++-- dipy/reconst/dki.py | 8 ++++---- dipy/reconst/dsi.py | 8 ++++---- dipy/reconst/dti.py | 17 +++++++++-------- dipy/reconst/forecast.py | 2 +- dipy/reconst/qtdmri.py | 2 +- dipy/reconst/shore.py | 14 +++++++------- dipy/workflows/denoise.py | 2 +- 8 files changed, 29 insertions(+), 28 deletions(-) diff --git a/dipy/denoise/localpca.py b/dipy/denoise/localpca.py index 7b801dac37..bfac2c0abf 100644 --- a/dipy/denoise/localpca.py +++ b/dipy/denoise/localpca.py @@ -220,7 +220,7 @@ def genpca( Thresholding of PCA eigenvalues is done by nulling out eigenvalues that are smaller than: - .. math :: + .. math:: \tau = (\tau_{factor} \sigma)^2 @@ -450,7 +450,7 @@ def localpca( Thresholding of PCA eigenvalues is done by nulling out eigenvalues that are smaller than: - .. math :: + .. math:: \tau = (\tau_{factor} \sigma)^2 diff --git a/dipy/reconst/dki.py b/dipy/reconst/dki.py index 0839b37ba6..d98f2280a3 100644 --- a/dipy/reconst/dki.py +++ b/dipy/reconst/dki.py @@ -649,7 +649,7 @@ def apparent_kurtosis_coef( For each sphere direction with coordinates $(n_{1}, n_{2}, n_{3})$, the calculation of AKC is done using formula [1]_: - .. math :: + .. math:: AKC(n)=\frac{MD^{2}}{ADC(n)^{2}}\sum_{i=1}^{3}\sum_{j=1}^{3} \sum_{k=1}^{3}\sum_{l=1}^{3}n_{i}n_{j}n_{k}n_{l}W_{ijkl} @@ -657,7 +657,7 @@ def apparent_kurtosis_coef( where $W_{ijkl}$ are the elements of the kurtosis tensor, MD the mean diffusivity and ADC the apparent diffusion coefficient computed as: - .. math :: + .. math:: ADC(n)=\sum_{i=1}^{3}\sum_{j=1}^{3}n_{i}n_{j}D_{ij} @@ -2038,7 +2038,7 @@ def akc(self, sphere): For each sphere direction with coordinates $(n_{1}, n_{2}, n_{3})$, the calculation of AKC is done using formula: - .. math :: + .. math:: AKC(n)=\frac{MD^{2}}{ADC(n)^{2}}\sum_{i=1}^{3}\sum_{j=1}^{3} \sum_{k=1}^{3}\sum_{l=1}^{3}n_{i}n_{j}n_{k}n_{l}W_{ijkl} @@ -2046,7 +2046,7 @@ def akc(self, sphere): where $W_{ijkl}$ are the elements of the kurtosis tensor, MD the mean diffusivity and ADC the apparent diffusion coefficient computed as: - .. math :: + .. math:: ADC(n)=\sum_{i=1}^{3}\sum_{j=1}^{3}n_{i}n_{j}D_{ij} diff --git a/dipy/reconst/dsi.py b/dipy/reconst/dsi.py index 6a3ae9b74b..c951720419 100644 --- a/dipy/reconst/dsi.py +++ b/dipy/reconst/dsi.py @@ -25,7 +25,7 @@ def __init__( spin displacements) can be estimated by applying 3D FFT to the signal values $S(\mathbf{q})$ - ..math:: + .. math:: :nowrap: \begin{eqnarray} P(\mathbf{r}) & = & S_{0}^{-1}\int S(\mathbf{q})\exp(-i2\pi\mathbf{q}\cdot\mathbf{r})d\mathbf{r} @@ -240,7 +240,7 @@ def rtop_pdf(self, normalized=True): def msd_discrete(self, normalized=True): r"""Calculates the mean squared displacement on the discrete propagator - ..math:: + .. math:: :nowrap: \begin{equation} MSD:{DSI}=\int_{-\infty}^{\infty}\int_{-\infty}^{\infty}\int_{-\infty}^{\infty} P(\hat{\mathbf{r}}) \cdot \hat{\mathbf{r}}^{2} \ dr_x \ dr_y \ dr_z @@ -284,7 +284,7 @@ def msd_discrete(self, normalized=True): def odf(self, sphere): r"""Calculates the real discrete odf for a given discrete sphere - ..math:: + .. math:: :nowrap: \begin{equation} \psi_{DSI}(\hat{\mathbf{u}})=\int_{0}^{\infty}P(r\hat{\mathbf{u}})r^{2}dr @@ -509,7 +509,7 @@ def __init__( The idea is to remove the convolution on the DSI propagator that is caused by the truncation of the q-space in the DSI sampling. - ..math:: + .. math:: :nowrap: \begin{eqnarray*} P_{dsi}(\mathbf{r}) & = & S_{0}^{-1}\iiint\limits_{\| \mathbf{q} \| \le \mathbf{q_{max}}} S(\mathbf{q})\exp(-i2\pi\mathbf{q}\cdot\mathbf{r})d\mathbf{q} \\ diff --git a/dipy/reconst/dti.py b/dipy/reconst/dti.py index da8f675e94..8c044688cc 100755 --- a/dipy/reconst/dti.py +++ b/dipy/reconst/dti.py @@ -371,7 +371,7 @@ def isotropic(q_form): ----- The isotropic part of a tensor is defined as (equations 3-5 of [1]_): - .. math :: + .. math:: \bar{A} = \frac{1}{2} tr(A) I References @@ -407,8 +407,8 @@ def deviatoric(q_form): ----- The deviatoric part of the tensor is defined as (equations 3-5 in [1]_): - .. math :: - \widetilde{A} = A - \bar{A} + .. math:: + \widetilde{A} = A - \bar{A} Where $A$ is the tensor quadratic form and $\bar{A}$ is the anisotropic part of the tensor. @@ -634,7 +634,7 @@ def apparent_diffusion_coef(q_form, sphere): ----- The calculation of ADC, relies on the following relationship: - .. math :: + .. math:: ADC = \vec{b} Q \vec{b}^T @@ -1205,7 +1205,7 @@ def adc(self, sphere): ----- The calculation of ADC, relies on the following relationship: - .. math :: + .. math:: ADC = \vec{b} Q \vec{b}^T @@ -1243,12 +1243,13 @@ def predict(self, gtab, S0=None, step=None): ----- The predicted signal is given by: - .. math :: + .. math:: S(\theta, b) = S_0 * e^{-b ADC} Where: - .. math :: + .. math:: + ADC = \theta Q \theta^T $\theta$ is a unit vector pointing at any direction on the sphere for @@ -1607,7 +1608,7 @@ def err_func(self, tensor, design_matrix, data, weighting=None, sigma=None): breakdown point (6,7). The explicit formula for C using the MAD estimator is: - .. math :: + .. math:: C = 1.4826 x MAD = 1.4826 x median{|r1-\hat{r}|,... |r_n-\hat{r}|} diff --git a/dipy/reconst/forecast.py b/dipy/reconst/forecast.py index 1f18d84aa3..b05dca8206 100644 --- a/dipy/reconst/forecast.py +++ b/dipy/reconst/forecast.py @@ -66,7 +66,7 @@ def __init__( single fiber response function $F(\mathbf{b})$ times the fODF $\rho(\mathbf{v})$ - ..math:: + .. math:: :nowrap: \begin{equation} E(\mathbf{b}) = \int_{\mathbf{v} \in \mathcal{S}^2} \rho(\mathbf{v}) F({\mathbf{b}} | \mathbf{v}) d \mathbf{v} diff --git a/dipy/reconst/qtdmri.py b/dipy/reconst/qtdmri.py index a343f3022b..9272dee4e8 100644 --- a/dipy/reconst/qtdmri.py +++ b/dipy/reconst/qtdmri.py @@ -35,7 +35,7 @@ class QtdmriModel(Cache): The main idea is to model the diffusion signal over time and space as a linear combination of continuous functions, - ..math:: + .. math:: :nowrap: \begin{equation} \hat{E}(\textbf{q},\tau;\textbf{c}) = diff --git a/dipy/reconst/shore.py b/dipy/reconst/shore.py index 25f790351c..461940d59a 100644 --- a/dipy/reconst/shore.py +++ b/dipy/reconst/shore.py @@ -20,7 +20,7 @@ class ShoreModel(Cache): The main idea is to model the diffusion signal as a linear combination of continuous functions $\phi_i$, - ..math:: + .. math:: :nowrap: \begin{equation} S(\mathbf{q})= \sum_{i=0}^I c_{i} \phi_{i}(\mathbf{q}). @@ -83,7 +83,7 @@ def __init__( The main idea is to model the diffusion signal as a linear combination of continuous functions $\phi_i$, - ..math:: + .. math:: :nowrap: \begin{equation} S(\mathbf{q})= \sum_{i=0}^I c_{i} \phi_{i}(\mathbf{q}). @@ -454,7 +454,7 @@ def rtop_pdf(self): def msd(self): r"""Calculates the analytical mean squared displacement (MSD) [1]_ - ..math:: + .. math:: :nowrap: \begin{equation} MSD:{DSI}=\int_{-\infty}^{\infty}\int_{-\infty}^{\infty} @@ -502,7 +502,7 @@ def shore_coeff(self): def shore_matrix(radial_order, zeta, gtab, tau=1 / (4 * np.pi**2)): r"""Compute the SHORE matrix for modified Merlet's 3D-SHORE [1]_ - ..math:: + .. math:: :nowrap: \begin{equation} \textbf{E}(q\textbf{u})=\sum_{l=0, even}^{N_{max}} @@ -512,7 +512,7 @@ def shore_matrix(radial_order, zeta, gtab, tau=1 / (4 * np.pi**2)): \end{equation} where $\phi_{nlm}$ is - ..math:: + .. math:: :nowrap: \begin{equation} \phi_{nlm}^{SHORE}(q\textbf{u})=\Biggl[\dfrac{2(n-l)!} @@ -733,7 +733,7 @@ def create_rspace(gridsize, radius_max): def shore_indices(radial_order, index): r"""Given the basis order and the index, return the shore indices n, l, m for modified Merlet's 3D-SHORE - ..math:: + .. math:: :nowrap: \begin{equation} \textbf{E}(q\textbf{u})=\sum_{l=0, even}^{N_{max}} @@ -743,7 +743,7 @@ def shore_indices(radial_order, index): \end{equation} where $\phi_{nlm}$ is - ..math:: + .. math:: :nowrap: \begin{equation} \phi_{nlm}^{SHORE}(q\textbf{u})=\Biggl[\dfrac{2(n-l)!} diff --git a/dipy/workflows/denoise.py b/dipy/workflows/denoise.py index d6c1875856..6d2b074df7 100644 --- a/dipy/workflows/denoise.py +++ b/dipy/workflows/denoise.py @@ -245,7 +245,7 @@ def run( Thresholding of PCA eigenvalues is done by nulling out eigenvalues that are smaller than: - .. math :: + .. math:: \tau = (\tau_{factor} \sigma)^2 From b960b48db5ee2519e012eb2a1db3fde03889a535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 27 Jul 2024 12:08:50 -0400 Subject: [PATCH 07/17] DOC: Use LaTeX math markup for `localpca` inline math expression Use LaTeX math markup for `localpca` inline math expression. --- dipy/denoise/localpca.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dipy/denoise/localpca.py b/dipy/denoise/localpca.py index bfac2c0abf..08f68e4254 100644 --- a/dipy/denoise/localpca.py +++ b/dipy/denoise/localpca.py @@ -224,9 +224,9 @@ def genpca( \tau = (\tau_{factor} \sigma)^2 - \tau_{factor} can be set to a predefined values (e.g. \tau_{factor} = - 2.3 [3]_), or automatically calculated using random matrix theory - (in case that \tau_{factor} is set to None). + $\tau_{factor}$ can be set to a predefined values (e.g. $\tau_{factor} = + 2.3$ [3]_), or automatically calculated using random matrix theory + (in case that $\tau_{factor}$ is set to None). return_sigma : bool (optional) If true, the Standard deviation of the noise will be returned. out_dtype : str or dtype (optional) From 687b63bc77fd3ad50c18717da06be5031c30c90a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sun, 28 Jul 2024 13:34:56 -0400 Subject: [PATCH 08/17] DOC: Use math mode for SH basis cases documentation Use math mode for SH basis cases documentation: improves readability when the documentation is rendered. Mark the corresponding docstrings as raw strings. Make the multiplying factor be before the `Re` and `Im` factors for the sake of readability. Use curly brackets to enclose the exponent of the basis so that the LaTeX expression is correctly rendered (i.e. $Y^{|m|}_l$ instead of $Y^|m|_l$, where only the first vertical bar would be raised). Take advantage of the commit to use LaTeX markup when the SH order and degree symbols are mentioned in docstrings. --- dipy/reconst/csdeconv.py | 4 +- dipy/reconst/forecast.py | 2 +- dipy/reconst/mcsd.py | 10 +- dipy/reconst/shm.py | 156 +++++++++++++++++---------- doc/examples/reconst_csa.py | 2 +- doc/examples/reconst_csa_parallel.py | 2 +- 6 files changed, 109 insertions(+), 67 deletions(-) diff --git a/dipy/reconst/csdeconv.py b/dipy/reconst/csdeconv.py index e4a3ebad9c..3811addc07 100644 --- a/dipy/reconst/csdeconv.py +++ b/dipy/reconst/csdeconv.py @@ -498,7 +498,7 @@ def forward_sdt_deconv_mat(ratio, l_values, r2_term=False): ratio = $\frac{\lambda_2}{\lambda_1}$ of the single fiber response function l_values : ndarray (N,) - The order (l) of spherical harmonic function associated with each row + The order ($l$) of spherical harmonic function associated with each row of the deconvolution matrix. Only even orders are allowed. r2_term : bool True if ODF comes from an ODF computed from a model using the $r^2$ @@ -877,7 +877,7 @@ def odf_sh_to_sharp( ratio of the smallest vs the largest eigenvalue of the single prolate tensor response function (:math:`\frac{\lambda_2}{\lambda_1}`) sh_order_max : int - maximal SH order (l) of the SH representation + maximal SH order ($l$) of the SH representation lambda_ : float lambda parameter (see odfdeconv) (default 1.0) tau : float diff --git a/dipy/reconst/forecast.py b/dipy/reconst/forecast.py index b05dca8206..62f67d14cb 100644 --- a/dipy/reconst/forecast.py +++ b/dipy/reconst/forecast.py @@ -84,7 +84,7 @@ def __init__( gtab : GradientTable, gradient directions and bvalues container class. sh_order_max : unsigned int, - an even integer that represent the maximal SH order (l) of the + an even integer that represent the maximal SH order ($l$) of the basis (max 12) lambda_lb: float, Laplace-Beltrami regularization weight. diff --git a/dipy/reconst/mcsd.py b/dipy/reconst/mcsd.py index 000222ff95..502b37701f 100644 --- a/dipy/reconst/mcsd.py +++ b/dipy/reconst/mcsd.py @@ -44,9 +44,9 @@ def multi_tissue_basis(gtab, sh_order_max, iso_comp): B : ndarray Matrix of the spherical harmonics model used to fit the data m_values : int ``|m_value| <= l_value`` - The phase factor (m) of the harmonic. + The phase factor ($m$) of the harmonic. l_values : int ``l_value >= 0`` - The order (l) of the harmonic. + The order ($l$) of the harmonic. """ if iso_comp < 2: msg = "Multi-tissue CSD requires at least 2 tissue compartments" @@ -112,7 +112,7 @@ def _inflate_response(response, gtab, sh_order_max, delta): response : MultiShellResponse object gtab : GradientTable sh_order_max : int ``>= 0`` - The maximal order (l) of the harmonic. + The maximal order ($l$) of the harmonic. delta : Delta generated from `_basic_delta` """ if ( @@ -141,9 +141,9 @@ def _basic_delta(iso, m_value, l_value, theta, phi): number of compartments required is 2. Default: 2 m_value : int ``|m| <= l`` - The phase factor (m) of the harmonic. + The phase factor ($m$) of the harmonic. l_value : int ``>= 0`` - The order (l) of the harmonic. + The order ($l$) of the harmonic. theta : array_like inclination or polar angle phi : array_like diff --git a/dipy/reconst/shm.py b/dipy/reconst/shm.py index 2ccac6fe3c..67e8935d59 100755 --- a/dipy/reconst/shm.py +++ b/dipy/reconst/shm.py @@ -69,7 +69,7 @@ def forward_sdeconv_mat(r_rh, l_values): function. Each element ``rh[i]`` is associated with spherical harmonics of order ``2*i``. l_values : ndarray - The orders (l) of spherical harmonic function associated with each row + The orders ($l$) of spherical harmonic function associated with each row of the deconvolution matrix. Only even orders are allowed Returns @@ -109,10 +109,10 @@ def sh_to_rh(r_sh, m_values, l_values): These coefficients must correspond to the real spherical harmonic functions produced by `shm.real_sh_descoteaux_from_index`. m_values : ndarray (N,) - The phase factors (m) of the spherical harmonic function associated with + The phase factors ($m$) of the spherical harmonic function associated with each coefficient. l_values : ndarray (N,) - The orders (l) of the spherical harmonic function associated with each + The orders ($l$) of the spherical harmonic function associated with each coefficient. Returns @@ -161,7 +161,7 @@ def gen_dirac(m_values, l_values, theta, phi, legacy=True): The phase factors of the spherical harmonic function associated with each coefficient. l_values : ndarray (N,) - The order (l) of the spherical harmonic function associated with each + The order ($l$) of the spherical harmonic function associated with each coefficient. theta : float [0, pi] The polar (colatitudinal) coordinate. @@ -204,9 +204,9 @@ def spherical_harmonics(m_values, l_values, theta, phi, use_scipy=True): Parameters ---------- m_values : array of int ``|m| <= l`` - The phase factors (m) of the harmonics. + The phase factors ($m$) of the harmonics. l_values : array of int ``l >= 0`` - The orders (l) of the harmonics. + The orders ($l$) of the harmonics. theta : float [0, 2*pi] The azimuthal (longitudinal) coordinate. phi : float [0, pi] @@ -266,13 +266,19 @@ def spherical_harmonics(m_values, l_values, theta, phi, use_scipy=True): until="2.0", ) def real_sph_harm(m_values, l_values, theta, phi): - """Compute real spherical harmonics. + r"""Compute real spherical harmonics. Where the real harmonic $Y^m_l$ is defined to be: - Imag($Y^m_l$) * sqrt(2) if m > 0 - $Y^0_l$ if m = 0 - Real($Y^|m|_l$) * sqrt(2) if m < 0 + .. math:: + :nowrap: + + Y^m_l = + \begin{cases} + \sqrt(2) * Im(Y^m_l) \; if m > 0 \\ + Y^0_l \; if m = 0 \\ + \sqrt(2) * Re(Y^{|m|}_l) \; if m < 0 \\ + \end{cases} This may take scalar or array arguments. The inputs will be broadcast against each other. @@ -280,9 +286,9 @@ def real_sph_harm(m_values, l_values, theta, phi): Parameters ---------- m_values : array of int ``|m| <= l`` - The phase factors (m) of the harmonics. + The phase factors ($m$) of the harmonics. l_values : array of int ``l >= 0`` - The orders (l) of the harmonics. + The orders ($l$) of the harmonics. theta : float [0, pi] The polar (colatitudinal) coordinate. phi : float [0, 2*pi] @@ -310,13 +316,19 @@ def real_sph_harm(m_values, l_values, theta, phi): until="2.0", ) def real_sh_tournier_from_index(m_values, l_values, theta, phi, legacy=True): - """Compute real spherical harmonics as initially defined in Tournier + r"""Compute real spherical harmonics as initially defined in Tournier 2007 [1]_ then updated in MRtrix3 [2]_, where the real harmonic $Y^m_l$ is defined to be: - Real($Y^m_l$) * sqrt(2) if m > 0 - $Y^0_l$ if m = 0 - Imag($Y^|m|_l$) * sqrt(2) if m < 0 + .. math:: + :nowrap: + + Y^m_l = + \begin{cases} + \sqrt(2) * Re(Y^m_l) \; if m > 0 \\ + Y^0_l \; if m = 0 \\ + \sqrt(2) * Im(Y^{|m|}_l) \; if m < 0 \\ + \end{cases} This may take scalar or array arguments. The inputs will be broadcast against each other. @@ -324,9 +336,9 @@ def real_sh_tournier_from_index(m_values, l_values, theta, phi, legacy=True): Parameters ---------- m_values : array of int ``|m| <= l`` - The phase factors (m) of the harmonics. + The phase factors ($m$) of the harmonics. l_values : array of int ``l >= 0`` - The orders (l) of the harmonics. + The orders ($l$) of the harmonics. theta : float [0, pi] The polar (colatitudinal) coordinate. phi : float [0, 2*pi] @@ -374,12 +386,18 @@ def real_sh_tournier_from_index(m_values, l_values, theta, phi, legacy=True): until="2.0", ) def real_sh_descoteaux_from_index(m_values, l_values, theta, phi, legacy=True): - """Compute real spherical harmonics as in Descoteaux et al. 2007 [1]_, + r"""Compute real spherical harmonics as in Descoteaux et al. 2007 [1]_, where the real harmonic $Y^m_l$ is defined to be: - Imag($Y^m_l$) * sqrt(2) if m > 0 - $Y^0_l$ if m = 0 - Real($Y^m_l$) * sqrt(2) if m < 0 + .. math:: + :nowrap: + + Y^m_l = + \begin{cases} + \sqrt(2) * Im(Y^m_l) \; if m > 0 \\ + Y^0_l \; if m = 0 \\ + \sqrt(2) * Re($Y^m_l) \; if m < 0 \\ + \end{cases} This may take scalar or array arguments. The inputs will be broadcast against each other. @@ -387,9 +405,9 @@ def real_sh_descoteaux_from_index(m_values, l_values, theta, phi, legacy=True): Parameters ---------- m_values : array of int ``|m| <= l`` - The phase factors (m) of the harmonics. + The phase factors ($m$) of the harmonics. l_values : array of int ``l >= 0`` - The orders (l) of the harmonics. + The orders ($l$) of the harmonics. theta : float [0, pi] The polar (colatitudinal) coordinate. phi : float [0, 2*pi] @@ -426,13 +444,19 @@ def real_sh_descoteaux_from_index(m_values, l_values, theta, phi, legacy=True): @deprecated_params("sh_order", "sh_order_max", since="1.9", until="2.0") def real_sh_tournier(sh_order_max, theta, phi, full_basis=False, legacy=True): - """Compute real spherical harmonics as initially defined in Tournier + r"""Compute real spherical harmonics as initially defined in Tournier 2007 [1]_ then updated in MRtrix3 [2]_, where the real harmonic $Y^m_l$ is defined to be: - Real($Y^m_l$) * sqrt(2) if m > 0 - $Y^0_l$ if m = 0 - Imag($Y^|m|_l$) * sqrt(2) if m < 0 + .. math:: + :nowrap: + + Y^m_l = + \begin{cases} + \sqrt(2) * Re(Y^m_l) \; if m > 0 \\ + Y^0_l \; if m = 0 \\ + \sqrt(2) * Im(Y^{|m|}_l) \; if m < 0 \\ + \end{cases} This may take scalar or array arguments. The inputs will be broadcast against each other. @@ -440,7 +464,7 @@ def real_sh_tournier(sh_order_max, theta, phi, full_basis=False, legacy=True): Parameters ---------- sh_order_max : int - The maximum order (l) of the spherical harmonic basis. + The maximum order ($l$) of the spherical harmonic basis. theta : float [0, pi] The polar (colatitudinal) coordinate. phi : float [0, 2*pi] @@ -457,9 +481,9 @@ def real_sh_tournier(sh_order_max, theta, phi, full_basis=False, legacy=True): real_sh : real float The real harmonic $Y^m_l$ sampled at ``theta`` and ``phi``. m_values : array of int - The phase factor (m) of the harmonics. + The phase factor ($m$) of the harmonics. l_values : array of int - The order (l) of the harmonics. + The order ($l$) of the harmonics. References ---------- @@ -484,12 +508,18 @@ def real_sh_tournier(sh_order_max, theta, phi, full_basis=False, legacy=True): @deprecated_params("sh_order", "sh_order_max", since="1.9", until="2.0") def real_sh_descoteaux(sh_order_max, theta, phi, full_basis=False, legacy=True): - """Compute real spherical harmonics as in Descoteaux et al. 2007 [1]_, + r"""Compute real spherical harmonics as in Descoteaux et al. 2007 [1]_, where the real harmonic $Y^m_l$ is defined to be: - Imag($Y^m_l$) * sqrt(2) if m > 0 - $Y^0_l$ if m = 0 - Real($Y^m_l$) * sqrt(2) if m < 0 + .. math:: + :nowrap: + + Y^m_l = + \begin{cases} + \sqrt(2) * Im(Y^m_l) \; if m > 0 \\ + Y^0_l \; if m = 0 \\ + \sqrt(2) * Re($Y^m_l) \; if m < 0 \\ + \end{cases} This may take scalar or array arguments. The inputs will be broadcast against each other. @@ -497,7 +527,7 @@ def real_sh_descoteaux(sh_order_max, theta, phi, full_basis=False, legacy=True): Parameters ---------- sh_order_max : int - The maximum order (l) of the spherical harmonic basis. + The maximum order ($l$) of the spherical harmonic basis. theta : float [0, pi] The polar (colatitudinal) coordinate. phi : float [0, 2*pi] @@ -516,9 +546,9 @@ def real_sh_descoteaux(sh_order_max, theta, phi, full_basis=False, legacy=True): real_sh : real float The real harmonic $Y^m_l$ sampled at ``theta`` and ``phi``. m_values : array of int - The phase factor (m) of the harmonics. + The phase factor ($m$) of the harmonics. l_values : array of int - The order (l) of the harmonics. + The order ($l$) of the harmonics. References ---------- @@ -544,13 +574,19 @@ def real_sh_descoteaux(sh_order_max, theta, phi, full_basis=False, legacy=True): ) @deprecated_params("sh_order", "sh_order_max", since="1.9", until="2.0") def real_sym_sh_mrtrix(sh_order_max, theta, phi): - """ + r""" Compute real symmetric spherical harmonics as in Tournier 2007 [2]_, where the real harmonic $Y^m_l$ is defined to be:: - Real($Y^m_l$) if m > 0 - $Y^0_l$ if m = 0 - Imag($Y^|m|_l$) if m < 0 + .. math:: + :nowrap: + + Y^m_l = + \begin{cases} + Re(Y^m_l) \; if m > 0 \\ + Y^0_l \; if m = 0 \\ + Im(Y^{|m|}_l) \; if m < 0 \\ + \end{cases} This may take scalar or array arguments. The inputs will be broadcast against each other. @@ -558,7 +594,7 @@ def real_sym_sh_mrtrix(sh_order_max, theta, phi): Parameters ---------- sh_order_max : int - The maximum order (l) of the spherical harmonic basis. + The maximum order ($l$) of the spherical harmonic basis. theta : float [0, pi] The polar (colatitudinal) coordinate. phi : float [0, 2*pi] @@ -571,9 +607,9 @@ def real_sym_sh_mrtrix(sh_order_max, theta, phi): implemented in mrtrix. Warning: the basis is Tournier et al. 2007 [2]_; 2004 [1]_ is slightly different. m_values : array - The phase factor (m) of the harmonics. + The phase factor ($m$) of the harmonics. l_values : array - The order (l) of the harmonics. + The order ($l$) of the harmonics. References ---------- @@ -599,16 +635,22 @@ def real_sym_sh_mrtrix(sh_order_max, theta, phi): ) @deprecated_params("sh_order", "sh_order_max", since="1.9", until="2.0") def real_sym_sh_basis(sh_order_max, theta, phi): - """Samples a real symmetric spherical harmonic basis at point on the sphere + r"""Samples a real symmetric spherical harmonic basis at point on the sphere Samples the basis functions up to order `sh_order_max` at points on the sphere given by `theta` and `phi`. The basis functions are defined here the same way as in Descoteaux et al. 2007 [1]_ where the real harmonic $Y^m_l$ is defined to be: - Imag($Y^m_l$) * sqrt(2) if m > 0 - $Y^0_l$ if m = 0 - Real($Y^|m|_l$) * sqrt(2) if m < 0 + .. math:: + :nowrap: + + Y^m_l = + \begin{cases} + \sqrt(2) * Im(Y^m_l) \; if m > 0 \\ + Y^0_l \; if m = 0 \\ + \sqrt(2) * Re(Y^{|m|}_l) \; if m < 0 \\ + \end{cases} This may take scalar or array arguments. The inputs will be broadcast against each other. @@ -616,7 +658,7 @@ def real_sym_sh_basis(sh_order_max, theta, phi): Parameters ---------- sh_order_max : int - The maximum order (l) of the spherical harmonic basis. Even int > 0, + The maximum order ($l$) of the spherical harmonic basis. Even int > 0, max spherical harmonic order theta : float [0, 2*pi] The azimuthal (longitudinal) coordinate. @@ -628,9 +670,9 @@ def real_sym_sh_basis(sh_order_max, theta, phi): y_mn : real float The real harmonic $Y^m_l$ sampled at ``theta`` and ``phi`` m_values : array of int - The phase factor (m) of the harmonics. + The phase factor ($m$) of the harmonics. l_values : array of int - The order (l) of the harmonics. + The order ($l$) of the harmonics. References ---------- @@ -662,7 +704,7 @@ def sph_harm_ind_list(sh_order_max, full_basis=False): Parameters ---------- sh_order_max : int - The maximum order (l) of the spherical harmonic basis. + The maximum order ($l$) of the spherical harmonic basis. Even int > 0, max order to return full_basis: bool, optional True for SH basis with even and odd order terms @@ -670,9 +712,9 @@ def sph_harm_ind_list(sh_order_max, full_basis=False): Returns ------- m_list : array of int - phase factors (m) of even spherical harmonics + phase factors ($m$) of even spherical harmonics l_list : array of int - orders (l) of even spherical harmonics + orders ($l$) of even spherical harmonics See Also -------- @@ -713,7 +755,7 @@ def order_from_ncoef(ncoef, full_basis=False): Returns ------- sh_order_max: int - maximum order (l) of SH basis + maximum order ($l$) of SH basis """ if full_basis: # Solve the equation : @@ -848,7 +890,7 @@ def __init__( gtab : GradientTable Diffusion gradients used to acquire data sh_order_max : even int >= 0 - the maximal spherical harmonic order (l) of the model + the maximal spherical harmonic order ($l$) of the model smooth : float between 0 and 1, optional The regularization parameter of the model min_signal : float, > 0, optional diff --git a/doc/examples/reconst_csa.py b/doc/examples/reconst_csa.py index d7cb53da5d..4ac73edc81 100644 --- a/doc/examples/reconst_csa.py +++ b/doc/examples/reconst_csa.py @@ -46,7 +46,7 @@ ) ############################################################################### -# We instantiate our CSA model with spherical harmonic order (l) of 4 +# We instantiate our CSA model with spherical harmonic order ($l$) of 4 csamodel = CsaOdfModel(gtab, 4) diff --git a/doc/examples/reconst_csa_parallel.py b/doc/examples/reconst_csa_parallel.py index 12c908dd7f..18a17940c6 100644 --- a/doc/examples/reconst_csa_parallel.py +++ b/doc/examples/reconst_csa_parallel.py @@ -31,7 +31,7 @@ ) ############################################################################### -# We instantiate our CSA model with spherical harmonic order (l) of 4 +# We instantiate our CSA model with spherical harmonic order ($l$) of 4 csamodel = CsaOdfModel(gtab, 4) From 8d7477fb33727bb272a5324cc7ea99db092771b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 27 Jul 2024 10:49:48 -0400 Subject: [PATCH 09/17] DOC: Use displayed math for miscellaneous modules Use the displayed math syntax for math expressions in miscellaneous modules for the sake of readability. --- dipy/reconst/dki_micro.py | 5 ++++- dipy/reconst/dti.py | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/dipy/reconst/dki_micro.py b/dipy/reconst/dki_micro.py index 94a71fd863..536264a136 100644 --- a/dipy/reconst/dki_micro.py +++ b/dipy/reconst/dki_micro.py @@ -626,7 +626,10 @@ def predict(self, gtab, S0=1.0): ----- The predicted signal is given by: - $S(\theta, b) = S_0 * [f * e^{-b ADC_{r}} + (1-f) * e^{-b ADC_{h}]$, + .. math:: + + S(\theta, b) = S_0 * [f * e^{-b ADC_{r}} + (1-f) * e^{-b ADC_{h}] + where $ADC_{r}$ and $ADC_{h}$ are the apparent diffusion coefficients of the diffusion hindered and restricted compartment for a given direction $\theta$, $b$ is the b value provided in the GradientTable diff --git a/dipy/reconst/dti.py b/dipy/reconst/dti.py index 8c044688cc..a3db6ca93d 100755 --- a/dipy/reconst/dti.py +++ b/dipy/reconst/dti.py @@ -668,8 +668,13 @@ def tensor_prediction(dti_params, gtab, S0): Notes ----- - The predicted signal is given by: $S(\theta, b) = S_0 * e^{-b ADC}$, where - $ADC = \theta Q \theta^T$, $\theta$ is a unit vector pointing at any + The predicted signal is given by: + + .. math:: + + S(\theta, b) = S_0 * e^{-b ADC} + + where $ADC = \theta Q \theta^T$, $\theta$ is a unit vector pointing at any direction on the sphere for which a signal is to be predicted, $b$ is the b value provided in the GradientTable input for that direction, $Q$ is the quadratic form of the tensor determined by the input parameters. From 01e0e58ea7923418f066abe7d9ba8926acfc7ed8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sun, 28 Jul 2024 13:23:07 -0400 Subject: [PATCH 10/17] DOC: Cite references and increase consistency in misc refs Cite existing references. Fixes: ``` /dipy/doc/examples_built/reconstruction/histology_resdnn.rst:193: WARNING: Footnote [1] is not referenced. ``` and similar warnings raised for example in: https://github.com/dipy/dipy/actions/runs/9982200633/job/27587486843#step:5:739 Take advantage of the commit to remove duplicate refs, and fix/make names consistent accross appearances. --- dipy/core/optimize.py | 2 +- dipy/denoise/nlmeans.py | 2 +- dipy/nn/histo_resdnn.py | 2 +- dipy/reconst/dti.py | 2 +- dipy/reconst/mapmri.py | 11 +++++++---- dipy/segment/clustering.py | 2 +- dipy/stats/qc.py | 2 +- dipy/viz/horizon/app.py | 4 ++-- dipy/workflows/denoise.py | 6 +++--- dipy/workflows/nn.py | 2 +- dipy/workflows/reconst.py | 26 ++++++++++++-------------- dipy/workflows/viz.py | 2 +- 12 files changed, 32 insertions(+), 31 deletions(-) diff --git a/dipy/core/optimize.py b/dipy/core/optimize.py index 41e23ebe7d..6e56350dea 100644 --- a/dipy/core/optimize.py +++ b/dipy/core/optimize.py @@ -382,7 +382,7 @@ def fit(self, X, y): class PositiveDefiniteLeastSquares: @warning_for_keywords() def __init__(self, m, *, A=None, L=None): - r"""Regularized least squares with linear matrix inequality constraints + r"""Regularized least squares with linear matrix inequality constraints [1]_. Generate a CVXPY representation of a regularized least squares optimization problem subject to linear matrix inequality constraints. diff --git a/dipy/denoise/nlmeans.py b/dipy/denoise/nlmeans.py index f38e483643..fe61f41d14 100644 --- a/dipy/denoise/nlmeans.py +++ b/dipy/denoise/nlmeans.py @@ -22,7 +22,7 @@ def nlmeans( rician=True, num_threads=None, ): - r"""Non-local means for denoising 3D and 4D images + r"""Non-local means for denoising 3D and 4D images [Descoteaux08]_. Parameters ---------- diff --git a/dipy/nn/histo_resdnn.py b/dipy/nn/histo_resdnn.py index df3d0e9922..0623700f56 100644 --- a/dipy/nn/histo_resdnn.py +++ b/dipy/nn/histo_resdnn.py @@ -45,7 +45,7 @@ class HistoResDNN: def __init__(self, *, sh_order_max=8, basis_type="tournier07", verbose=False): r""" The model was re-trained for usage with a different basis function - ('tournier07') like the proposed model in [1, 2]. + ('tournier07') like the proposed model in [1]_, [2]_. To obtain the pre-trained model, use:: >>> resdnn_model = HistoResDNN() # skip if not have_tf diff --git a/dipy/reconst/dti.py b/dipy/reconst/dti.py index a3db6ca93d..8b8d8b1a0e 100755 --- a/dipy/reconst/dti.py +++ b/dipy/reconst/dti.py @@ -748,7 +748,7 @@ def __init__(self, gtab, fit_method="WLS", return_S0_hat=False, *args, **kwargs) .. [2] Basser, P., Pierpaoli, C., 1996. Microstructural and physiological features of tissues elucidated by quantitative diffusion-tensor MRI. Journal of Magnetic Resonance 111, 209-219. - .. [3] Lin-Ching C., Jones D.K., Pierpaoli, C. 2005. RESTORE: Robust + .. [3] Chang, L-C, Jones D.K., Pierpaoli, C. 2005. RESTORE: Robust estimation of tensors by outlier rejection. MRM 53: 1088-1095 """ diff --git a/dipy/reconst/mapmri.py b/dipy/reconst/mapmri.py index 96f9f105f3..04b649dde3 100644 --- a/dipy/reconst/mapmri.py +++ b/dipy/reconst/mapmri.py @@ -37,6 +37,8 @@ class MapmriModel(ReconstModel, Cache): From the MAPMRI coefficients is possible to use the analytical formulae to estimate the ODF. + See [8]_ for additional tissue microstructure insights provided by MAPMRI. + References ---------- .. [1] Ozarslan E. et al., "Mean apparent propagator (MAP) MRI: A novel @@ -135,7 +137,7 @@ def __init__( Regularize using the Laplacian of the MAP-MRI basis. laplacian_weighting: string or scalar, The string 'GCV' makes it use generalized cross-validation to find - the regularization weight [4]. A scalar sets the regularization + the regularization weight [4]_. A scalar sets the regularization weight to that value and an array will make it selected the optimal weight from the values in the array. positivity_constraint : bool, @@ -153,7 +155,8 @@ def __init__( If set to a float, the maximum distance the local positivity constraint constrains to posivity is that value. If set to 'adaptive', the maximum distance is dependent on the estimated - tissue diffusivity. + tissue diffusivity. If 'infinity', semidefinite programming + constraints are used [9]_. anisotropic_scaling : bool, If True, uses the standard anisotropic MAP-MRI basis. If False, uses the isotropic MAP-MRI basis (equal to 3D-SHORE). @@ -176,7 +179,7 @@ def __init__( static_diffusivity : float, the tissue diffusivity that is used when dti_scale_estimation is set to False. The default is that of typical white matter - D=0.7e-3 _[5]. + D=0.7e-3 [5]_. cvxpy_solver : str, optional cvxpy solver name. Optionally optimize the positivity constraint with a particular cvxpy solver. See https://www.cvxpy.org/ for @@ -2244,7 +2247,7 @@ def generalized_crossvalidation(data, M, LR, gcv_startpoint=5e-2): def gcv_cost_function(weight, args): - """The GCV cost function that is iterated [4].""" + """The GCV cost function that is iterated [4]_.""" data, M, MMt, K, LR = args S = np.linalg.multi_dot([M, np.linalg.pinv(MMt + weight * LR), M.T]) trS = np.trace(S) diff --git a/dipy/segment/clustering.py b/dipy/segment/clustering.py index a2fdd9eb1b..6892b47728 100644 --- a/dipy/segment/clustering.py +++ b/dipy/segment/clustering.py @@ -554,7 +554,7 @@ def cluster(self, streamlines, *, ordering=None): class QuickBundlesX(Clustering): - r"""Clusters streamlines using QuickBundlesX. + r"""Clusters streamlines using QuickBundlesX [Garyfallidis16]_. Parameters ---------- diff --git a/dipy/stats/qc.py b/dipy/stats/qc.py index 410aeaa806..fe3b5ed4d4 100644 --- a/dipy/stats/qc.py +++ b/dipy/stats/qc.py @@ -71,7 +71,7 @@ def neighboring_dwi_correlation(dwi_data, gtab, *, mask=None): """Calculate the Neighboring DWI Correlation (NDC) from dMRI data. Using a mask is highly recommended, otherwise the FOV will influence the - correlations. According to [Yeh2019], an NDC less than 0.4 indicates a + correlations. According to [Yeh2019]_, an NDC less than 0.4 indicates a low quality image. Parameters diff --git a/dipy/viz/horizon/app.py b/dipy/viz/horizon/app.py index 0a9b8a02c1..8a3d49399a 100644 --- a/dipy/viz/horizon/app.py +++ b/dipy/viz/horizon/app.py @@ -82,7 +82,7 @@ def __init__( roi_colors=(1, 0, 0), surface_colors=((1, 0, 0),), ): - """Interactive medical visualization - Invert the Horizon! + """Interactive medical visualization - Invert the Horizon! [Horizon_ISMRM19]_. Parameters @@ -748,7 +748,7 @@ def horizon( recorded_events=None, return_showm=False, ): - """Interactive medical visualization - Invert the Horizon! + """Interactive medical visualization - Invert the Horizon! [Horizon_ISMRM19]_. Parameters diff --git a/dipy/workflows/denoise.py b/dipy/workflows/denoise.py index 6d2b074df7..6863a80870 100644 --- a/dipy/workflows/denoise.py +++ b/dipy/workflows/denoise.py @@ -131,7 +131,7 @@ def run( out_dir="", out_denoised="dwi_nlmeans.nii.gz", ): - """Workflow wrapping the nlmeans denoising method. + """Workflow wrapping the nlmeans denoising method [Descoteaux08]_. It applies nlmeans denoise on each file found by 'globing' ``input_files`` and saves the results in a directory specified by @@ -319,7 +319,7 @@ def run( out_denoised="dwi_mppca.nii.gz", out_sigma="dwi_sigma.nii.gz", ): - r"""Workflow wrapping Marcenko-Pastur PCA denoising method. + r"""Workflow wrapping Marcenko-Pastur PCA denoising method [1]_. Parameters ---------- @@ -394,7 +394,7 @@ def run( out_dir="", out_unring="dwi_unring.nii.gz", ): - r"""Workflow for applying Gibbs Ringing method. + r"""Workflow for applying Gibbs Ringing method [1]_, [2]_. Parameters ---------- diff --git a/dipy/workflows/nn.py b/dipy/workflows/nn.py index 3534859a1e..ede37b70d4 100644 --- a/dipy/workflows/nn.py +++ b/dipy/workflows/nn.py @@ -20,7 +20,7 @@ def run( out_mask="brain_mask.nii.gz", out_masked="dwi_masked.nii.gz", ): - """Extract brain using EVAC+. + """Extract brain using EVAC+ [Park2022]_. Parameters ---------- diff --git a/dipy/workflows/reconst.py b/dipy/workflows/reconst.py index 1f938d18e2..3fbb1a77c6 100644 --- a/dipy/workflows/reconst.py +++ b/dipy/workflows/reconst.py @@ -306,7 +306,8 @@ def run( out_peaks_indices="peaks_indices.nii.gz", out_gfa="gfa.nii.gz", ): - """Workflow for tensor reconstruction and for computing DTI metrics. + """Workflow for tensor reconstruction and for computing DTI metrics + [1]_, [2]_. using Weighted Least-Squares. Performs a tensor reconstruction on the files by 'globing' ``input_files`` and saves the DTI metrics in a directory specified by @@ -328,10 +329,10 @@ def run( multiple masks at once. fit_method : string, optional can be one of the following: - 'WLS' for weighted least squares - 'LS' or 'OLS' for ordinary least squares + 'WLS' for weighted least squares [4]_ + 'LS' or 'OLS' for ordinary least squares [4]_ 'NLLS' for non-linear least-squares - 'RT' or 'restore' or 'RESTORE' for RESTORE robust tensor fitting + 'RT' or 'restore' or 'RESTORE' for RESTORE robust tensor fitting [3]_. b0_threshold : float, optional Threshold used to find b0 volumes. bvecs_tol : float, optional @@ -412,16 +413,13 @@ def run( physiological features of tissues elucidated by quantitative diffusion-tensor MRI. Journal of Magnetic Resonance 111, 209-219. - .. [3] Lin-Ching C., Jones D.K., Pierpaoli, C. 2005. RESTORE: Robust + .. [3] Chang, L-C, Jones D.K., Pierpaoli, C. 2005. RESTORE: Robust estimation of tensors by outlier rejection. MRM 53: 1088-1095 - .. [4] hung, SW., Lu, Y., Henry, R.G., 2006. Comparison of bootstrap + .. [4] Chung, SW., Lu, Y., Henry, R.G., 2006. Comparison of bootstrap approaches for estimation of uncertainties of DTI parameters. NeuroImage 33, 531-541. - .. [5] Chang, L-C, Jones, DK and Pierpaoli, C (2005). RESTORE: robust - estimation of tensors by outlier rejection. MRM, 53: 1088-95. - """ save_metrics = save_metrics or [] @@ -770,7 +768,7 @@ def run( out_peaks_indices="peaks_indices.nii.gz", out_gfa="gfa.nii.gz", ): - """Constrained spherical deconvolution + """Constrained spherical deconvolution [1]_. Parameters ---------- @@ -984,7 +982,7 @@ def run( out_peaks_indices="peaks_indices.nii.gz", out_gfa="gfa.nii.gz", ): - """Constant Solid Angle. + """Constant Solid Angle [1]_. Parameters ---------- @@ -1159,9 +1157,9 @@ def run( out_gfa="gfa.nii.gz", ): """Workflow for Diffusion Kurtosis reconstruction and for computing - DKI metrics. Performs a DKI reconstruction on the files by 'globing' - ``input_files`` and saves the DKI metrics in a directory specified by - ``out_dir``. + DKI metrics [1]_, [2]_. Performs a DKI reconstruction on the files by + 'globing' ``input_files`` and saves the DKI metrics in a directory + specified by ``out_dir``. Parameters ---------- diff --git a/dipy/workflows/viz.py b/dipy/workflows/viz.py index b256b0dbcd..8bdf4ff95e 100644 --- a/dipy/workflows/viz.py +++ b/dipy/workflows/viz.py @@ -51,7 +51,7 @@ def run( out_dir="", out_stealth_png="tmp.png", ): - """Interactive medical visualization - Invert the Horizon! + """Interactive medical visualization - Invert the Horizon! [Horizon_ISMRM19]_. Interact with any number of .trk, .tck or .dpy tractograms and anatomy files .nii or .nii.gz. Cluster streamlines on loading. From 49d496a78633f8248772360fd415fc6843fd8fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 27 Jul 2024 10:45:15 -0400 Subject: [PATCH 11/17] DOC: Fix AD computation docstring Fix AD computation docstring: the method computes AD, not RD. --- dipy/reconst/dti.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dipy/reconst/dti.py b/dipy/reconst/dti.py index 8b8d8b1a0e..39646df463 100755 --- a/dipy/reconst/dti.py +++ b/dipy/reconst/dti.py @@ -1026,7 +1026,7 @@ def ad(self): Notes ----- - RD is calculated with the following equation: + AD is calculated with the following equation: .. math:: From c5e1dba43eafb0a5c9f091e26e1963d8d2ab85fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 27 Jul 2024 11:45:09 -0400 Subject: [PATCH 12/17] DOC: Fix typos in documentation Fix typos in documentation. --- dipy/align/streamlinear.py | 4 ++-- dipy/reconst/cross_validation.py | 2 +- dipy/reconst/csdeconv.py | 4 ++-- dipy/reconst/forecast.py | 2 +- dipy/viz/horizon/app.py | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dipy/align/streamlinear.py b/dipy/align/streamlinear.py index 46dd1ad28c..3463cec015 100644 --- a/dipy/align/streamlinear.py +++ b/dipy/align/streamlinear.py @@ -912,13 +912,13 @@ def progressive_slr( ): """Progressive SLR. - This is an utility function that allows for example to do affine + This is a utility function that allows for example to do affine registration using Streamline-based Linear Registration (SLR) [Garyfallidis15]_ by starting with translation first, then rigid, then similarity, scaling and finally affine. Similarly, if for example, you want to perform rigid then you start with - translation first. This progressive strategy can helps with finding the + translation first. This progressive strategy can help with finding the optimal parameters of the final transformation. Parameters diff --git a/dipy/reconst/cross_validation.py b/dipy/reconst/cross_validation.py index 6376b74c6a..18f0d3b7c5 100644 --- a/dipy/reconst/cross_validation.py +++ b/dipy/reconst/cross_validation.py @@ -54,7 +54,7 @@ def coeff_of_determination(data, model, axis=-1): def kfold_xval(model, data, folds, *model_args, **model_kwargs): """Perform k-fold cross-validation. - It generate out-of-sample predictions for each measurement. + It generates out-of-sample predictions for each measurement. Parameters ---------- diff --git a/dipy/reconst/csdeconv.py b/dipy/reconst/csdeconv.py index 3811addc07..54e2d0a9df 100644 --- a/dipy/reconst/csdeconv.py +++ b/dipy/reconst/csdeconv.py @@ -376,8 +376,8 @@ def __init__( diffusion ODF as the QballModel or the CsaOdfModel. This results in a sharper angular profile with better angular resolution. The Constrained SDTModel is similar to the Constrained CSDModel but mathematically it - deconvolves the q-ball ODF as oppposed to the HARDI signal (see [1]_ - for a comparison and a through discussion). + deconvolves the q-ball ODF as opposed to the HARDI signal (see [1]_ + for a comparison and a thorough discussion). A sharp fODF is obtained because a single fiber *response* function is injected as *a priori* knowledge. In the SDTModel, this response is a diff --git a/dipy/reconst/forecast.py b/dipy/reconst/forecast.py index 62f67d14cb..73e244f8bc 100644 --- a/dipy/reconst/forecast.py +++ b/dipy/reconst/forecast.py @@ -73,7 +73,7 @@ def __init__( \end{equation} where $\mathbf{b}$ is the b-vector (b-value times gradient direction) - and $\mathbf{v}$ is an unit vector representing a fiber direction. + and $\mathbf{v}$ is a unit vector representing a fiber direction. In FORECAST $\rho$ is modeled using real symmetric Spherical Harmonics (SH) and $F(\mathbf(b))$ is an axially symmetric tensor. diff --git a/dipy/viz/horizon/app.py b/dipy/viz/horizon/app.py index 8a3d49399a..a975ae0319 100644 --- a/dipy/viz/horizon/app.py +++ b/dipy/viz/horizon/app.py @@ -135,7 +135,7 @@ def __init__( File path to replay recorded events return_showm : bool Return ShowManager object. Used only at Python level. Can be used - for extending Horizon's cababilities externally and for testing + for extending Horizon's capabilities externally and for testing purposes. bg_color : ndarray or list or tuple Define the background color of the scene. From b00a94e49aa9fd14d3921262046da45040448850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 27 Jul 2024 11:45:52 -0400 Subject: [PATCH 13/17] DOC: Use `ADC` in uppercase to refer to the apparent diffusion coeff Use `ADC` in uppercase to refer to the apparent diffusion coefficient. --- dipy/reconst/dki.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dipy/reconst/dki.py b/dipy/reconst/dki.py index d98f2280a3..7a02da0725 100644 --- a/dipy/reconst/dki.py +++ b/dipy/reconst/dki.py @@ -421,7 +421,7 @@ def _F2m(a, b, c): def directional_diffusion(dt, V, min_diffusivity=0): - r"""Calculate the apparent diffusion coefficient (adc) in each direction + r"""Calculate the apparent diffusion coefficient (ADC) in each direction of a sphere for a single voxel [1]_ Parameters @@ -439,7 +439,7 @@ def directional_diffusion(dt, V, min_diffusivity=0): Returns ------- adc : ndarray (g,) - Apparent diffusion coefficient (adc) in all g directions of a sphere + Apparent diffusion coefficient (ADC) in all g directions of a sphere for a single voxel. References @@ -491,7 +491,7 @@ def directional_diffusion_variance(kt, V, min_kurtosis=-3 / 7): (theoretical kurtosis limit for regions that consist of water confined to spherical pores [1]_) adc : ndarray(g,) (optional) - Apparent diffusion coefficient (adc) in all g directions of a sphere + Apparent diffusion coefficient (ADC) in all g directions of a sphere for a single voxel. adv : ndarray(g,) (optional) Apparent diffusion variance coefficient (advc) in all g directions of @@ -568,7 +568,7 @@ def directional_kurtosis( (theoretical kurtosis limit for regions that consist of water confined to spherical pores [3]_) adc : ndarray(g,) (optional) - Apparent diffusion coefficient (adc) in all g directions of a sphere + Apparent diffusion coefficient (ADC) in all g directions of a sphere for a single voxel. adv : ndarray(g,) (optional) Apparent diffusion variance (advc) in all g directions of a sphere for From 3d09ba710d8c3c22c79e96a0b82d9728b608351c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sun, 28 Jul 2024 13:26:06 -0400 Subject: [PATCH 14/17] DOC: Use multi-line format for module docstring Fix module-level formatting: use the multi-line format. Fixes: ``` /dipy/reconst/cross_validation.py: docstring of dipy.reconst.cross_validation.coeff_of_determination:5: CRITICAL: Unexpected section title. ``` and similar warnings raised for example in: https://github.com/dipy/dipy/actions/runs/9982200633/job/27587486843#step:5:1073 --- dipy/reconst/cross_validation.py | 4 +++- dipy/reconst/dki.py | 4 +++- dipy/reconst/dti.py | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/dipy/reconst/cross_validation.py b/dipy/reconst/cross_validation.py index 18f0d3b7c5..e49520ca70 100644 --- a/dipy/reconst/cross_validation.py +++ b/dipy/reconst/cross_validation.py @@ -1,4 +1,6 @@ -"""Cross-validation analysis of diffusion models.""" +""" +Cross-validation analysis of diffusion models. +""" import numpy as np diff --git a/dipy/reconst/dki.py b/dipy/reconst/dki.py index 7a02da0725..0d717344f5 100644 --- a/dipy/reconst/dki.py +++ b/dipy/reconst/dki.py @@ -1,5 +1,7 @@ #!/usr/bin/python -"""Classes and functions for fitting the diffusion kurtosis model""" +""" +Classes and functions for fitting the diffusion kurtosis model. +""" import warnings diff --git a/dipy/reconst/dti.py b/dipy/reconst/dti.py index 39646df463..491de8b8e5 100755 --- a/dipy/reconst/dti.py +++ b/dipy/reconst/dti.py @@ -1,5 +1,7 @@ #!/usr/bin/python -"""Classes and functions for fitting tensors""" +""" +Classes and functions for fitting tensors. +""" import functools import warnings From 0636e2a14bacbd2881b175f4cef45af98bd1a151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 27 Jul 2024 10:52:18 -0400 Subject: [PATCH 15/17] DOC: Remove optional argument default value from docstring Remove optional argument default value in miscellaneous docstrings: reduces the maintenance burden, avoiding the risk of making the docstring go out of sync with the method signature. --- dipy/align/streamlinear.py | 2 +- dipy/reconst/cross_validation.py | 2 +- dipy/reconst/dki_micro.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dipy/align/streamlinear.py b/dipy/align/streamlinear.py index 3463cec015..c8a3063f0e 100644 --- a/dipy/align/streamlinear.py +++ b/dipy/align/streamlinear.py @@ -935,7 +935,7 @@ def progressive_slr( method : string L_BFGS_B' or 'Powell' optimizers can be used. Default is 'L_BFGS_B'. verbose : bool, optional. - If True, log messages. Default: + If True, log messages. num_threads : int, optional Number of threads to be used for OpenMP parallelization. If None (default) the value of OMP_NUM_THREADS environment variable is used diff --git a/dipy/reconst/cross_validation.py b/dipy/reconst/cross_validation.py index e49520ca70..5a4c1579b5 100644 --- a/dipy/reconst/cross_validation.py +++ b/dipy/reconst/cross_validation.py @@ -18,7 +18,7 @@ def coeff_of_determination(data, model, axis=-1): model : ndarray The predictions of a model for this data. Same shape as the data. axis: int, optional - The axis along which different samples are laid out (default: -1). + The axis along which different samples are laid out. Returns ------- diff --git a/dipy/reconst/dki_micro.py b/dipy/reconst/dki_micro.py index 536264a136..ee5ec401c2 100644 --- a/dipy/reconst/dki_micro.py +++ b/dipy/reconst/dki_micro.py @@ -620,7 +620,7 @@ def predict(self, gtab, S0=1.0): S0 : float or ndarray (optional) The non diffusion-weighted signal in every voxel, or across all - voxels. Default: 1 + voxels. Notes ----- From 34b1b3d0b6f97775eefcf37c02b31236d12b8142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sun, 28 Jul 2024 14:12:59 -0400 Subject: [PATCH 16/17] DOC: Add parameter explanation to `progressive_slr` method Add parameter explanation to `progressive_slr` method. --- dipy/align/streamlinear.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dipy/align/streamlinear.py b/dipy/align/streamlinear.py index c8a3063f0e..de192ba2b2 100644 --- a/dipy/align/streamlinear.py +++ b/dipy/align/streamlinear.py @@ -924,8 +924,11 @@ def progressive_slr( Parameters ---------- static : Streamlines + Static streamlines. moving : Streamlines + Moving streamlines. metric : StreamlineDistanceMetric + Distance metric for registration optimization. x0 : string Could be any of 'translation', 'rigid', 'similarity', 'scaling', 'affine' From f8f130269c2a323f2592f44cbd41c0e8833c8015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sun, 28 Jul 2024 13:55:26 -0400 Subject: [PATCH 17/17] STYLE: Simplify concatenated string in exception message Simplify concatenated string in exception message. --- dipy/utils/tractogram.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dipy/utils/tractogram.py b/dipy/utils/tractogram.py index cecca3e116..0d8a0dd65e 100644 --- a/dipy/utils/tractogram.py +++ b/dipy/utils/tractogram.py @@ -94,7 +94,7 @@ def concatenate_tractogram( ): if not delete_dpv: logging.debug(f"{key} dpv key does not exist in all TrxFile.") - raise ValueError("TrxFile must be sharing identical dpv " "keys.") + raise ValueError("TrxFile must be sharing identical dpv keys.") elif ( ref_trx.data_per_vertex[key]._data.dtype != curr_trx.data_per_vertex[key]._data.dtype @@ -112,7 +112,7 @@ def concatenate_tractogram( ): if not delete_dps: logging.debug(f"{key} dps key does not exist in all TrxFile.") - raise ValueError("TrxFile must be sharing identical dps " "keys.") + raise ValueError("TrxFile must be sharing identical dps keys.") elif ( ref_trx.data_per_streamline[key].dtype != curr_trx.data_per_streamline[key].dtype