Source code for dipy.stats.qc
import numpy as np
from dipy.core.geometry import cart_distance
from dipy.testing.decorators import warning_for_keywords
[docs]
def find_qspace_neighbors(gtab):
"""Create a mapping of dwi volume index to its nearest neighbor.
An approximate q-space is used (the deltas are not included).
Note that neighborhood is not necessarily bijective. One neighbor
is found per dwi volume.
Parameters
----------
gtab: dipy.core.gradients.GradientTable
Gradient table.
Returns
-------
neighbors: list of tuple
A list of 2-tuples indicating the nearest q-space neighbor
of each dwi volume.
Examples
--------
>>> from dipy.core.gradients import gradient_table
>>> import numpy as np
>>> gtab = gradient_table(
... np.array([0, 1000, 1000, 2000]),
... bvecs=np.array([
... [1, 0, 0],
... [1, 0, 0],
... [0.99, 0.0001, 0.0001],
... [1, 0, 0]]))
>>> find_qspace_neighbors(gtab)
[(1, 2), (2, 1), (3, 1)]
"""
dwi_neighbors = []
# Only correlate the b>0 images
dwi_mask = np.logical_not(gtab.b0s_mask)
dwi_indices = np.flatnonzero(dwi_mask)
# Get a pseudo-qspace value for b>0s
qvecs = np.sqrt(gtab.bvals)[:, np.newaxis] * gtab.bvecs
for dwi_index in dwi_indices:
qvec = qvecs[dwi_index]
# Calculate distance in q-space, accounting for symmetry
pos_dist = cart_distance(qvec[np.newaxis, :], qvecs)
neg_dist = cart_distance(qvec[np.newaxis, :], -qvecs)
distances = np.min(np.column_stack([pos_dist, neg_dist]), axis=1)
# Be sure we don't select the image as its own neighbor
distances[dwi_index] = np.inf
# Or a b=0
distances[gtab.b0s_mask] = np.inf
neighbor_index = np.argmin(distances)
dwi_neighbors.append((dwi_index, neighbor_index))
return dwi_neighbors
[docs]
@warning_for_keywords()
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 :footcite:t:`Yeh2019`, an NDC less than 0.4
indicates a low quality image.
Parameters
----------
dwi_data : 4D ndarray
dwi data on which to calculate NDC
gtab : dipy.core.gradients.GradientTable
Gradient table.
mask : 3D ndarray, optional
Mask of voxels to include in the NDC calculation
Returns
-------
ndc : float
The neighboring DWI correlation
References
----------
.. footbibliography::
"""
neighbor_indices = find_qspace_neighbors(gtab)
neighbor_correlations = []
if mask is not None:
binary_mask = mask > 0
for from_index, to_index in neighbor_indices:
# Flatten the dwi images
if mask is not None:
flat_from_image = dwi_data[..., from_index][binary_mask]
flat_to_image = dwi_data[..., to_index][binary_mask]
else:
flat_from_image = dwi_data[..., from_index].flatten()
flat_to_image = dwi_data[..., to_index].flatten()
neighbor_correlations.append(np.corrcoef(flat_from_image, flat_to_image)[0, 1])
return np.mean(neighbor_correlations)