OSCR

Simulation-based inference at the theoretical limit for fast, robust microstructural MRI with minimal diffusion data.

Code ↔ Paper

5 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 5 matches
  1. [1] § Methods › Tensor-based frameworks ↔ DKI_funcs.py, lines 11–32 · score 0.83 · radial kurtosis, axial kurtosis, kurtosis fractional, kurtosis tensor, DKI metrics, KFA
  2. [2] § Methods › The AxCaliber model ↔ AxCaliber_funcs.py, lines 73–205 · score 0.82 · gamma distribution, restricted compartment, diffusion tensor, AxCaliber, exponential, scalar
  3. [3] § Results › Application of SBI to AxCaliber ↔ AxCaliber_funcs.py, lines 73–205 · score 0.58 · restricted compartment, restricted signal, simulated signals, angle, hindered, fraction
  4. [4] § Results › Application of SBI to AxCaliber ↔ AxCaliber_figs.ipynb, lines 553–575 · score 0.53 · reduced SBI, reduced NLLS, full NLLS, full SBI, angle, circle
  5. [5] § Methods › The AxCaliber model ↔ AxCaliber_figs.ipynb, lines 183–248 · score 0.52 · diffusion tensor, AxCaliber, gamma, Dh, hindered

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Python · 383 lines · 14 KB · no license · 2 matches

  1. from DTI_funcs import *
  2. from scipy.special import j0, jv
  3. from scipy.optimize import bisect
  4. Delta = [0.017, 0.035, 0.061] # ms
  5. delta = 0.007 # ms
  6. def j1_derivative(x):
  7. """Derivative of J1(x) using the identity: J1'(x) = 0.5 * (J0(x) - J2(x))."""
  8. return 0.5 * (j0(x) - j2(x))
  9. def j2(x):
  10. """Bessel function J_2(x)."""
  11. return jv(2, x)
  12. def j1prime_zeros(n, x_max=100, step=0.1):
  13. """
  14. Find the first n positive roots of J1'(x) by scanning from x=0 to x_max.
  15. Parameters
  16. ----------
  17. n : int
  18. Number of roots to find
  19. x_max : float
  20. Maximum x to search
  21. step : float
  22. Step size for scanning sign changes
  23. Returns
  24. -------
  25. zeros : list of float
  26. List of the first n roots (x > 0) of J1'(x).
  27. """
  28. zeros = []
  29. x_vals = np.arange(0.0, x_max, step)
  30. f_prev = j1_derivative(x_vals[0])
  31. for i in range(1, len(x_vals)):
  32. f_curr = j1_derivative(x_vals[i])
  33. # Check for a sign change in [x_vals[i-1], x_vals[i]]
  34. if f_prev * f_curr < 0:
  35. root = bisect(j1_derivative, x_vals[i-1], x_vals[i])
  36. zeros.append(root)
  37. if len(zeros) == n:
  38. break
  39. f_prev = f_curr
  40. return zeros
  41. n_roots = 100
  42. Bessel_roots = np.array(j1prime_zeros(n_roots, x_max=10e6, step=0.01))
  43. def SpherAng(v_in):
  44. if v_in[2] < 0:
  45. v_in = -v_in # Flip the vector to the top hemisphere
  46. x, y, z = v_in
  47. r = np.linalg.norm(v_in)
  48. if r == 0:
  49. # Degenerate vector, define angles however you like:
  50. return 0.0, 0.0
  51. # Polar angle in [0, pi]
  52. theta = np.arccos(z / r)
  53. # Azimuthal angle in (-pi, pi]
  54. phi = np.arctan2(y, x)
  55. return theta,phi
  56. def AxCaliber(bvecs, bvals, Delta, delta, params):
  57. """
  58. Compute the combined diffusion signal in a fast, vectorized way.
  59. Parameters:
  60. bvecs : (M,3) array of b-vectors.
  61. bvals : (M,) array of b-values.
  62. Delta, delta : acquisition parameters (scalars)
  63. params : list/tuple of parameters:
  64. params[0] : fiber directions as an (N,2) array of spherical angles (theta, phi)
  65. params[1] : Dpar (scalar)
  66. params[2] : Dperp (scalar)
  67. params[3] : D (for hindered compartment; passed to vals_to_mat)
  68. params[4] : fiber fractions as an (N+1,) array
  69. (first element for hindered compartment, then one per fiber)
  70. params[5] : mean (scalar, for gamma distribution)
  71. params[6] : sig2 (scalar, for gamma distribution)
  72. params[7] : S0 (scalar)
  73. Returns:
  74. Signal : (M,) array of simulated signal values.
  75. """
  76. # Unpack parameters
  77. V_angles, Dpar, Dperp, D, fracs, mean, S0 = params
  78. # --- 1. Compute fiber unit vectors from spherical angles ---
  79. # Assume V_angles is an (N,2) array: each row is (theta, phi).
  80. theta_fibers = V_angles[:, 0]
  81. phi_fibers = V_angles[:, 1]
  82. V_unit = np.column_stack((np.sin(theta_fibers) * np.cos(phi_fibers),
  83. np.sin(theta_fibers) * np.sin(phi_fibers),
  84. np.cos(theta_fibers))) # shape: (N, 3)
  85. # --- 2. Compute angles between each fiber and each b-vector ---
  86. # Make sure bvecs is an array.
  87. bvecs = np.asarray(bvecs) # shape: (M,3)
  88. M = bvecs.shape[0]
  89. N = V_unit.shape[0]
  90. # Precompute norms of bvecs (we assume fibers are unit length so no extra norm is needed)
  91. bvec_norms = np.linalg.norm(bvecs, axis=1)
  92. # Avoid division by zero:
  93. safe_bvec_norms = np.where(bvec_norms == 0, 1, bvec_norms)
  94. # Compute the dot products for each fiber with all bvecs:
  95. # This gives a (N, M) array where the (i,j) element = v_i dot bvec_j.
  96. dots = V_unit @ bvecs.T # shape: (N, M)
  97. # Divide each column j by the norm of bvec j (broadcasting over fibers)
  98. cos_angles = dots / safe_bvec_norms # shape: (N, M)
  99. cos_angles = np.clip(cos_angles, -1, 1)
  100. # Get the angles in [0,pi]
  101. Angs = np.arccos(cos_angles)
  102. # For bvecs that are zero (norm==0), force the angle to zero.
  103. if np.any(bvec_norms == 0):
  104. Angs[:, bvec_norms == 0] = 0
  105. # If an angle is greater than pi/2, use pi - angle.
  106. Angs = np.where(Angs > np.pi/2, np.pi - Angs, Angs)
  107. # In the original code the first measurement was forced to zero (presumably b = 0)
  108. Angs[:, 0] = 0
  109. # --- 3. Precompute the gamma-distributed weights for the integration over R ---
  110. # Gamma distribution parameters:
  111. lam = mean*10000
  112. # Define R values (50 points between 0.0001 and 0.005)
  113. R_vals = np.arange(0.0001, 0.01, 0.0001) #
  114. transR = (R_vals * 10000).astype(int)
  115. weights = (lam**transR) * np.exp(-lam) / np.array([math.factorial(r) for r in transR.astype(int)]).astype(np.double)
  116. weights /= np.sum(weights)
  117. # --- 4. Precompute the "sumterm" that appears in the restricted compartment ---
  118. # Here we use m=10 terms and assume that a global array Bessel_roots is available.
  119. m = 10
  120. br = Bessel_roots[:m] # shape: (m,)
  121. br2 = br**2
  122. br6 = br**6
  123. # For each R in R_vals, compute the sumterm.
  124. # We need to broadcast over R and over the m terms.
  125. R2 = R_vals**2 # shape: (50,)
  126. # numerator: shape (50, m)
  127. num = (2 * Dperp * br2 * delta / R2[:, None] - 2 +
  128. 2 * np.exp(-Dperp * br2 * delta / R2[:, None]) +
  129. 2 * np.exp(-Dperp * br2 * Delta / R2[:, None]) -
  130. np.exp(-Dperp * br2 * (Delta - delta) / R2[:, None]) -
  131. np.exp(-Dperp * br2 * (Delta + delta) / R2[:, None]))
  132. # denominator: shape (50, m)
  133. den = (Dperp**2) * br6 * (br2 - 1) / (R_vals[:, None]**6)
  134. sumterm_R = np.sum(num / den, axis=1) # shape: (50,)
  135. # --- 5. Compute the restricted compartment signal ---
  136. # For each fiber orientation i (i = 0...N-1) and for each measurement j (j = 0...M-1)
  137. # we need to compute:
  138. # Restricted(b, theta, R) = exp(-b * (cos(theta)**2) * Dpar) *
  139. # exp(-2 * b * (sin(theta)**2) / ((Delta-delta/3)*delta**2) * sumterm)
  140. #
  141. # Notice that only the second exponential depends on R (via sumterm_R) and we need to integrate
  142. # over R with weights.
  143. #
  144. # Compute the part independent of R (base) and the factor x that multiplies sumterm_R.
  145. #
  146. # Angs has shape (N, M) (one row per fiber) and bvals is (M,).
  147. # (We assume that bvals is a 1D array; if not, cast it with np.asarray(bvals).)
  148. bvals = np.asarray(bvals) # shape: (M,)
  149. base = np.exp(-bvals * (np.cos(Angs)**2) * Dpar) # shape: (N, M)
  150. # Factor multiplying sumterm_R inside the second exponential.
  151. x = -2 * bvals * (np.sin(Angs)**2) / ((Delta - delta/3) * delta**2) # shape: (N, M)
  152. # For each fiber orientation and measurement, we want to compute:
  153. # f(i,j) = sum_{r=0}^{49} weights[r] * exp( x(i,j) * sumterm_R[r] )
  154. # We can compute the 3D array exp(x * sumterm_R) with shape (N, M, 50) and then contract out the last axis.
  155. exp_term = np.exp(x[..., None] * sumterm_R) # shape: (N, M, 50)
  156. # Now take the weighted sum over the last axis (the R axis):
  157. restricted_integral = np.tensordot(exp_term, weights, axes=([2], [0])) # shape: (N, M)
  158. # The restricted compartment signal for each fiber and measurement is then:
  159. Res = base * restricted_integral # shape: (N, M)
  160. #
  161. # Finally, combine the fibers by weighting each fiber's contribution by its fraction.
  162. # The original code did: np.sum([f * R for f,R in zip(fracs[1:],Res)], axis=0)
  163. # That is equivalent to a dot product: (fracs[1:]) dot (each row of Res).
  164. restricted_signal = np.dot(fracs[1:], Res) # shape: (M,)
  165. # --- 6. Compute the hindered compartment signal ---
  166. # Compute the diffusion tensor from D (using your vals_to_mat function).
  167. dh = vals_to_mat(D)
  168. # The hindered signal is given by:
  169. # Hi = exp(-b * s)
  170. # where s = sum((bvec @ dh)*bvec, axis=1). Here bvecs is (M,3).
  171. s = np.sum((bvecs @ dh) * bvecs, axis=1) # shape: (M,)
  172. hindered_signal = np.exp(-bvals * s) # shape: (M,)
  173. # --- 7. Combine compartments and scale by S0 ---
  174. Signal = fracs[0] * hindered_signal + restricted_signal
  175. return S0 * Signal
  176. def AxCal_Errors(TrueSig,TrueParams,GuessParams,Delta,bvecs,bvals):
  177. Res = np.linalg.norm(residuals(GuessParams,TrueSig,bvecs,bvals,Delta))
  178. alpha_err = np.abs(GuessParams[11]-TrueParams[11])
  179. angle_err1 = np.abs(GuessParams[0]-TrueParams[0])
  180. angle_err2 = np.abs(GuessParams[1]-TrueParams[1])
  181. Dpar_err = np.abs(TrueParams[2]-GuessParams[2])
  182. Dperp_err = np.abs(TrueParams[3]-GuessParams[3])
  183. MD_guess = np.linalg.eigh(vals_to_mat(GuessParams[4:10]))[0].mean()
  184. MD_true = np.linalg.eigh(vals_to_mat(TrueParams[4:10]))[0].mean()
  185. FA_guess = FracAni(np.linalg.eigh(vals_to_mat(GuessParams[4:10]))[0],MD_guess)
  186. FA_true = FracAni(np.linalg.eigh(vals_to_mat(TrueParams[4:10]))[0],MD_true)
  187. MD_err = np.abs(MD_guess-MD_true)
  188. FA_err = np.abs(FA_guess-FA_true)
  189. Frac_err = np.abs(TrueParams[10]-GuessParams[10])
  190. return Res, alpha_err,angle_err1,angle_err2,Dpar_err,Dperp_err,MD_err,FA_err,Frac_err
  191. def residuals(params,TrueSig,bvecs,bvals,Delta,EstS0 = True):
  192. if(EstS0):
  193. Signal = AxC_Simulator(params,bvecs,bvals,Delta,S0=params[-1])
  194. else:
  195. Signal = AxC_Simulator(params,bvecs,bvals,Delta)
  196. return TrueSig - Signal
  197. def AxC_Simulator(params,bvecs,bvals,Delta,S0=200):
  198. new_params = [np.array([params[:2]]),params[2],params[3],params[4:10],[params[10],1-params[10]],params[11],S0]
  199. Sig = []
  200. for bve,bva,d in zip(bvecs,bvals,Delta):
  201. Sig.append(AxCaliber(bve,bva,d,delta,new_params))
  202. return np.hstack(Sig)
  203. def shell_time_stats(b_dw, Δ_dw, y_dw):
  204. """
  205. Compute mean and variance of y for each (b, Δ) combination
  206. using DW-only arrays.
  207. Parameters
  208. ----------
  209. b_dw : (N,) array of DW b-values
  210. Δ_dw : (N,) array of DW diffusion times
  211. y_dw : (N,) array of DW log-attenuations
  212. Returns
  213. -------
  214. feats : 1D array of length 2 * (#unique b) * (#unique Δ)
  215. [mean_y(b1,Δ1), var_y(b1,Δ1), mean_y(b1,Δ2), var_y(b1,Δ2), ...]
  216. """
  217. b_dw = np.asarray(b_dw)
  218. Δ_dw = np.asarray(Δ_dw)
  219. y_dw = np.asarray(y_dw)
  220. shells = np.unique(b_dw)
  221. times = np.unique(Δ_dw)
  222. feats = []
  223. for b in shells:
  224. for Δ in times:
  225. m = (b_dw == b) & (Δ_dw == Δ)
  226. if np.any(m):
  227. y_sub = y_dw[m]
  228. feats.append(y_sub.mean())
  229. feats.append(y_sub.var())
  230. else:
  231. feats.append(0.0)
  232. feats.append(0.0)
  233. return np.array(feats, dtype=float)
  234. def AxcaliberFeatures(bvecs, bvals, Deltas, Signal):
  235. """
  236. Feature construction for AxCaliber-like data, analogous to DTIFeatures/DKIFeatures.
  237. Parameters
  238. ----------
  239. bvecs : (M, 3) array
  240. Gradient directions.
  241. bvals : (M,) array
  242. b-values corresponding to each gradient.
  243. Deltas : (M,) array
  244. Diffusion times (Delta) for each measurement.
  245. Signal : (M,) array
  246. Measured signal.
  247. Returns
  248. -------
  249. feats : (1 + 18 + 18*18,) array
  250. Concatenated feature vector:
  251. [ S0_hat,
  252. SigFeat (18,),
  253. AcqFeat (18*18,) ]
  254. """
  255. bvecs = np.asarray(bvecs, dtype=float)
  256. bvals = np.asarray(bvals, dtype=float)/1000
  257. Deltas = np.asarray(Deltas, dtype=float)
  258. Signal = np.asarray(Signal, dtype=float)
  259. if bvecs.shape[0] != bvals.shape[0] or bvals.shape[0] != Deltas.shape[0] \
  260. or Signal.shape[0] != bvals.shape[0]:
  261. raise ValueError("bvecs, bvals, Deltas, and Signal must all have the same length (M).")
  262. # ---- 1. Separate b=0 and DW ----
  263. S0_mask = (bvals == 0)
  264. dw_mask = (bvals > 0)
  265. if not np.any(S0_mask):
  266. raise ValueError("At least one b=0 measurement is required to estimate S0.")
  267. if np.sum(dw_mask) < 6:
  268. raise ValueError("At least 6 DW measurements are recommended for this feature mapping.")
  269. S0_hat = np.mean(Signal[S0_mask])
  270. S_dw = Signal[dw_mask]
  271. b_dw = bvals[dw_mask]
  272. g_dw = bvecs[dw_mask, :]
  273. Δ_dw = Deltas[dw_mask]
  274. # Response variable y = -ln(S / S0)
  275. y = -np.log(S_dw / S0_hat) # shape [N]
  276. N = y.size
  277. g1, g2, g3 = g_dw[:, 0], g_dw[:, 1], g_dw[:, 2]
  278. sqrtb = np.sqrt(b_dw)
  279. # ---- 2. Base diffusion-like design (6 terms, as in DTI) ----
  280. # Each term is effectively ~ b * g_i g_j
  281. # We construct it using the same pattern as your DTIFeatures.
  282. X_base = np.vstack([
  283. (sqrtb * g1) * (sqrtb * g1), # b * g1^2
  284. 2 * (sqrtb * g1) * (sqrtb * g2), # 2 b * g1 g2
  285. (sqrtb * g2) * (sqrtb * g2), # b * g2^2
  286. 2 * (sqrtb * g1) * (sqrtb * g3), # 2 b * g1 g3
  287. 2 * (sqrtb * g2) * (sqrtb * g3), # 2 b * g2 g3
  288. (sqrtb * g3) * (sqrtb * g3) # b * g3^2
  289. ]) # shape [6, N]
  290. # ---- 3. Time basis functions for Delta ----
  291. # Use a simple polynomial basis in Delta: [1, Δ, Δ^2]
  292. # Then modulate the 6 diffusion-like terms with each time basis.
  293. T0 = np.ones_like(Δ_dw) # Δ^0
  294. T1 = Δ_dw # Δ^1
  295. T2 = Δ_dw**2 # Δ^2
  296. # Each gives a 6×N block when multiplied with X_base.
  297. X_Δ0 = X_base # 6 × N
  298. X_Δ1 = X_base * T1 # 6 × N (broadcast over columns)
  299. X_Δ2 = X_base * T2 # 6 × N
  300. # Stack into a single design matrix: 18 × N
  301. X = np.vstack([X_Δ0, X_Δ1, X_Δ2]) # shape [18, N]
  302. # ---- 4. Acquisition and signal features ----
  303. # Acquisition features: design self-product
  304. XtX = X_base @ X_base.T # [18, 18]
  305. AcqFeat = (XtX / N).ravel() # length 18*18
  306. # Signal features: design–response product
  307. SigFeat = (X @ y) / N # length 18
  308. ShellTimeFeat = shell_time_stats(b_dw, Δ_dw, y)
  309. # ---- 5. Concatenate ----
  310. return np.hstack([S0_hat, SigFeat, AcqFeat,ShellTimeFeat])
  311. def Par_frac(i,j,Mat):
  312. MD = np.linalg.eigh(vals_to_mat(Mat[i,j]))[0].mean()
  313. FA = FracAni(np.linalg.eigh(vals_to_mat(Mat[i,j]))[0],MD)
  314. return i, j, [FA,MD]

AxCaliber_funcs.py at commit e166ec3, no license · at the source

Overview

  1. Institute of Neuroscience, CSIC-UMH, Alicante, Sant Joan d’Alacant, Spain
  2. Institute of Experimental Epileptology, University Hospital Bonn, Bonn, Germany
Institutions: University Hospital Bonn (Germany); Instituto de Neurociencias (Spain)
Journal: Communications medicine, volume 6, issue 1, article 275
Dates: received 20 August 2025; accepted 13 April 2026; published online 1 May 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1038/s43856-026-01614-6 · PMID 42062550 · PMCID PMC13157494 · OpenAlex W7159614343
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: structural MRI / diffusion (modality), human (organism), computational (subfield)
Methods: Connectivity, Statistics, fMRI & imaging, Physiology & signal measures
Keywords: Magnetic resonance imaging, Diffusion tensor imaging, Computational neuroscience
Topic: Advanced Neuroimaging Techniques and Applications (Radiology, Nuclear Medicine and Imaging, Medicine), according to OpenAlex
Funding: Generalitat Valenciana (Regional Government of Valencia) (CIDE- GENT/2021/015); "la Caixa" Foundation (Caixa Foundation) (LCF/BQ/PI23/11970039); Ministry of Economy and Competitiveness | Agencia Estatal de Investigación (Spanish Agencia Estatal de Investigación) (CNS2023-14488)
Citations: cited by 2 papers (Europe PMC); 79 references in the paper

Abstract

The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.

Repositories

Its files are read in the Code ↔ Paper reader above, with 5 matches between paragraphs and lines of code.

TIB-Lab/SBIDTI

License: none: the authors keep all their rights
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: e166ec3542b2fa5ac15a6f7578199f192c3c4fe2, 27 January 2026
Languages: Python (4), Jupyter (3)
Size: 12 files, 7 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, 3 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: DIPY (3 files), SciPy (3 files), Matplotlib (2 files), NumPy (1 file), PyTorch (1 file), scikit-image (1 file), statsmodels (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
8 files

Zenodo 18086195

License: CC-BY-4.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: DIPY (3 files), SciPy (3 files), Matplotlib (2 files), NumPy (1 file), PyTorch (1 file), scikit-image (1 file), statsmodels (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
8 files
At the source:

Code availability statement

The paper has a code availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

  • it points to the authors' code: TIB-Lab/SBIDTI
  • it says that the code is available on request

Read it in the paper: doi.org/10.1038/s43856-026-01614-6.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 14 scripts, each with its path and the digest of its content;
  • 5 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Code and data availability statement

The paper has a code and data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

  • it points to the authors' code: TIB-Lab/SBIDTI
  • it says that the data are available on request
  • it says that the code is available on request

Read it in the paper: doi.org/10.1038/s43856-026-01614-6.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 2 authors, 3 keywords, 3 funders, 61 references.

Cite

This paper

Eggl, M. F., & De Santis, S. (2026). Simulation-based inference at the theoretical limit for fast, robust microstructural MRI with minimal diffusion data. Communications medicine, 6(1), 275. https://doi.org/10.1038/s43856-026-01614-6

BibTeX

@article{eggl2026simulation,
author = {Eggl, Maximilian F and De Santis, Silvia},
title = {{Simulation-based inference at the theoretical limit for fast, robust microstructural MRI with minimal diffusion data}},
journal = {Communications medicine},
year = {2026},
month = may,
volume = {6},
number = {1},
pages = {275},
publisher = {Nature Publishing Group},
issn = {2730-664X},
doi = {10.1038/s43856-026-01614-6},
url = {https://doi.org/10.1038/s43856-026-01614-6},
pmid = {42062550},
pmcid = {PMC13157494}
}

RIS

TY - JOUR
AU - Eggl, Maximilian F
AU - De Santis, Silvia
TI - Simulation-based inference at the theoretical limit for fast, robust microstructural MRI with minimal diffusion data
T2 - Communications medicine
J2 - Commun Med (Lond)
PY - 2026
DA - 2026/05/01
VL - 6
IS - 1
SP - 275
SN - 2730-664X
PB - Nature Publishing Group
DO - 10.1038/s43856-026-01614-6
UR - https://doi.org/10.1038/s43856-026-01614-6
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s43856-026-01614-6",
"type": "article-journal",
"title": "Simulation-based inference at the theoretical limit for fast, robust microstructural MRI with minimal diffusion data",
"container-title": "Communications medicine",
"author": [
{
"family": "Eggl",
"given": "Maximilian F"
},
{
"family": "De Santis",
"given": "Silvia"
}
],
"container-title-short": "Commun Med (Lond)",
"volume": "6",
"issue": "1",
"page": "275",
"DOI": "10.1038/s43856-026-01614-6",
"PMID": "42062550",
"PMCID": "PMC13157494",
"ISSN": "2730-664X",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s43856-026-01614-6",
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
1
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1002/nbm.70277 [code]
Hierarchical Bayesian Modelling Improves Microstructural Parameter Mapping in Diffusion and Exchange MRI Data.
Journal: NMR in biomedicine
In common: DIPY, SciPy, Matplotlib, 1 other tool, computational, structural MRI / diffusion, 8 references
[2] doi:10.1002/mrm.70378 [code]
Investigating the Sensitivity of the Diffusion MRI Signal to Magnetization Transfer and Permeability via Monte-Carlo Simulations.
Journal: Magnetic resonance in medicine
In common: SciPy, Matplotlib, NumPy, computational, structural MRI / diffusion, 8 references
[3] doi:10.1002/hbm.70513 [code]
Deep Learning Empowered Microstructure Codebook: New Paradigm for Multi-Parameter Tissue Characterization Estimation.
Journal: Human brain mapping
In common: DIPY, PyTorch, NumPy, structural MRI / diffusion, 7 references
[4] doi:10.1038/s41598-026-39162-7 [code]
White matter microstructure differences in obstructive sleep apnea severity groups assessed by diffusion tensor metrics and biophysical modeling.
Journal: Scientific reports
In common: DIPY, scikit-image, SciPy, 1 other tool, structural MRI / diffusion, 6 references
[5] doi:10.1038/s41598-026-51531-w [code]
Multimodal age-dependent diffusion-MRI analysis of the neocortex in a rat model of cortical dysplasia.
Journal: Scientific reports
In common: DIPY, scikit-image, SciPy, 2 other tools, structural MRI / diffusion, 5 references
[6] doi:10.1002/hbm.70553 [code]
Axon Diameter Mapping in the Living Human Brain with Ultra-High-Gradient Diffusion MRI at 500 mT/m Gradient Strength.
Journal: Human brain mapping
In common: NumPy, structural MRI / diffusion, 7 references
[7] doi:10.1371/journal.pone.0346132 [code]
Analysis of cortical dysplasias using b-tensor encoding diffusion MRI in an animal model.
Journal: PloS one
In common: DIPY, scikit-image, SciPy, 2 other tools, structural MRI / diffusion, 4 references
[8] doi:10.1162/imag.a.1341 [code]
Massively parallelized brain tractography using compute clusters, supercomputers, and graphics processing units.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: DIPY, SciPy, Matplotlib, 1 other tool, structural MRI / diffusion, 5 references
[9] doi:10.1002/mrm.70336 [code]
Offline Reconstruction of Diffusion MRI Acquisitions for Comparison Between Complex PCA-Based and AI-Based Denoising.
Journal: Magnetic resonance in medicine
In common: DIPY, SciPy, Matplotlib, 1 other tool, structural MRI / diffusion, 4 references
[10] doi:10.1002/mp.70599 [code]
Accurate estimation of intravoxel incoherent motion parameters based on implicit neural representation.
Journal: Medical physics
In common: PyTorch, SciPy, NumPy, structural MRI / diffusion, 5 references

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.