OSCR

The Role of Dendritic Spines in Water Exchange Measurements With Diffusion MRI: Time-Dependent Single Diffusion Encoding MRI.

Code ↔ Paper

10 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 10 matches
  1. [1] § Methods › Monte Carlo Diffusion Simulations ↔ diffusion_signal_analysis.m, lines 1 to 64 · score 0.74 · particle dynamics, gradient separation, gradient pulses, pulse schemes, durations, diffusion signal · Report a mismatch
  2. [2] § Results › Impact of Dendritic Spines on Time‐Dependent SDE Measurements and NEXI Analysis ↔ nexi_bias_analysis.m, lines 1 to 34 · score 0.66 · NEXI model, membrane permeability, narrow pulse, dendritic spine volume, synthetic, spine volume fraction · Report a mismatch
  3. [3] § Results › Diffusion Time‐Dependence in Spiny Dendritic Branches ↔ highb_cumulant_analysis.m, lines 89 to 191 · score 0.64 · longest diffusion, permeable barriers, spiny branch, cumulant, kurtosis, spine densities · Report a mismatch
  4. [4] § Methods › Spiny Dendritic Branches ↔ main_analysis_ub.m, lines 33 to 144 · score 0.58 · beading amplitudes, undulation periods, realistic, smooth, spine densities, shaft · Report a mismatch
  5. [5] § Methods › Monte Carlo Diffusion Simulations ↔ particle_dynamics_analysis.m, lines 1 to 28 · score 0.58 · particle dynamics, particle concentrations, curve, exchange rates, bias, density · Report a mismatch
  6. [6] § Results › Diffusion Time‐Dependence in Spiny Dendritic Branches ↔ highb_cumulant_analysis.m, lines 89 to 191 · score 0.58 · longest diffusion, apparent kurtosis, spiny branch, cumulant, spine densities, permeable · Report a mismatch
  7. [7] § Methods › Monte Carlo Diffusion Simulations ↔ diffusion_signal_analysis.m, lines 1 to 64 · score 0.57 · particle dynamics, diffusion simulations, disimpy, exchange rates, substrate, water · Report a mismatch
  8. [8] § Methods › Data Analysis › Impact of Dendritic Spines on Time‐Dependent SDE Measurements and NEXI Analysis ↔ nexi_bias_analysis.m, lines 1 to 34 · score 0.57 · NEXI model, membrane permeability, biased, spine volume fraction, literature, dendritic spines · Report a mismatch
  9. [9] § Methods › Data Analysis › Impact of Dendritic Spines on Time‐Dependent SDE Measurements and NEXI Analysis ↔ coarse_grained_nexi_analysis.m, lines 41 to 98 · score 0.54 · volume ratio, simulated signals, voxel, spine volume fraction, surface, exchange rate · Report a mismatch
  10. [10] § Theory › Coarse‐Grained Extended Kärger Model: An Adaptation to the Motional Narrowing Regime ↔ coarse_grained_nexi_analysis.m, lines 1 to 39 · score 0.50 · coarse graining, cylindrical, neck, head, water, radius · Report a mismatch

Paper

Loaded from Europe PMC by your browser; OSCR does not store it: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

MATLAB · 692 lines · 24 KB · no license · 2 matches

  1. % diffusion_signal_analysis.m
  2. % Diffusion-signal analysis: parallel/perpendicular signal fits, exchange
  3. % rates, and the direction-average (Sperp=1) NEXI bias -> Figures 5, 9
  4. % (narrow + wide pulse via the 'pulse' switch below), plus the
  5. % perpendicular-signal supplementary figures. (Figure 4 -- spine<->shaft
  6. % exchange rates from MC particle dynamics -- is in
  7. % particle_dynamics_analysis.m, which it shares data with.)
  8. %
  9. % The NEXI permeability x spine-fraction bias map (Figure 10) is a separate,
  10. % self-contained script -- see nexi_bias_analysis.m -- since it needs none of
  11. % the data loaded here and mixing the two risked variable-name collisions.
  12. % Run from the repository root.
  13. clear all
  14. close all
  15. clc
  16. % No absolute cd: keep the repo portable for publication.
  17. % cd(fileparts(mfilename('fullpath')))
  18. addpath(genpath('src'))
  19. % ===================== Pulse scheme (change this one line) =====================
  20. % Each MATLAB script handles ONE pulse scheme per run. Set 'narrow' or 'wide':
  21. % the data file, gradient timings and field names below adapt automatically, so
  22. % the same script reproduces the corresponding figures for either dataset.
  23. pulse = 'wide'; % 'narrow' (delta_small = 3 ms) | 'wide' (delta_small = 15 ms)
  24. switch lower(pulse)
  25. case 'narrow'
  26. datafile = 'tunable_meshes_Water_narrowPulse_dt100ns.mat';
  27. cumulantfile = 'ADC_K_fromCumulants_narrowPulse.mat';
  28. smalldelta = 3; % gradient pulse duration [ms]
  29. delta = [5, 10, 25, 35, 55, 85, 160]; % gradient separations [ms] (incl. td = 4 ms)
  30. case 'wide'
  31. datafile = 'tunable_meshes_Water_widePulse_dt100ns.mat';
  32. cumulantfile = 'ADC_K_fromCumulants_widePulse.mat';
  33. smalldelta = 15;
  34. delta = [25, 35, 55, 85, 160];
  35. otherwise
  36. error('pulse must be ''narrow'' or ''wide''.')
  37. end
  38. load(fullfile('SpineMCresults', datafile)) % -> D###_d##, b, td, ...
  39. cumulants = load(fullfile('SpineMCresults', cumulantfile)); % ADC, K, td, spine_density
  40. GAMMA = 2.67513E8; % from the diffusion simulator disimpy
  41. smalldelta = smalldelta .* ones(size(delta)); % per-timing vector (back-compat)
  42. % =============================================================================
  43. Rh = 0.4; % effective spine head radius
  44. Rn = 0.125;
  45. Ln = 1.2;
  46. Rsh = 0.5;
  47. D = 2.0;
  48. De = D;
  49. % spine volume fraction (spines per micron)
  50. rho =[ 0 0.30 0.60 0.90 1.20 1.50 2.00 2.50 3.00 3.50];
  51. % measured volume of spines in the substrate (um^3)
  52. Vspine = [0 8.1003 16.1886 24.3715 32.9335 40.3329 52.1781 67.1394 80.6029 93.9811];
  53. % number of spines in the substrates
  54. Nspine = [0 30 60 90 120 150 200 250 300 350];
  55. % measured total volume of substrates
  56. Vtotal = [78.0362 87.9328 96.7014 105.5739 114.1809 122.5810 135.1033 150.7471 164.7820 178.7003];
  57. % spine volume fraction in the substrates
  58. nu = Vspine./Vtotal;
  59. % nu = vspine_tot./V_tot;
  60. options = optimset('display', 'off');
  61. %% ============================================================
  62. % Analyse Parallel Signals
  63. % ============================================================
  64. Y = [];
  65. Ymean = [];
  66. for i = 1:numel(delta)
  67. % Field names are D<delta>_d<smalldelta>, zero-padded (e.g. D005_d03,
  68. % D025_d15). This single rule covers narrow and wide pulses and the new
  69. % td = 4 ms (D005) timing.
  70. s = eval(sprintf('D%03d_d%02d', delta(i), smalldelta(1)));
  71. Y = [Y, s.parallel];
  72. Ymean = [Ymean, (s.parallel + s.perpendicular) ./ 2];
  73. end
  74. Tpar = Y;
  75. rr = zeros(numel(nu), 1);
  76. options = optimset('display','off');
  77. for i=1:numel(nu)
  78. % -------------------- Parallel signal fit --------------------
  79. ffit = @(p,x) modifiedKargerParallel(De, p, nu(i), x, td);
  80. rr(i) = initModelFitting(ffit, b, Y(i,:), 0.01, 250, 1000);
  81. % rr(i) = lsqcurvefit(ffit, 3.75, b, Y(i,:), 0.01, 250, options);
  82. end
  83. %% ============================================================
  84. % Theoretical and Estimated Exchange Rates: Spine ↔ Shaft
  85. % ============================================================
  86. % Computes theoretical first-passage times and exchange rates
  87. % for spine-to-shaft and shaft-to-spine diffusion, then compares
  88. % them to estimated values and plots both.
  89. % ------------------------------------------------------------
  90. % --- Theoretical first-passage time: Spine → Shaft ---
  91. Vh = (4/3) * pi .* Rh.^3;
  92. % Main formula
  93. tau_sp_sh_th = Ln .* ( ...
  94. 2 .* pi .* Rh.^3 + ...
  95. 3 .* Rn.^2 .* Ln + ...
  96. 2 .* pi .* Rh.^2 .* Rn .* log(Rh ./ Rn) - ...
  97. 2 .* Rn.^3 ) ./ (6 .* Rn.^2 .* D);
  98. % Conversion to rate constants
  99. k_sp_sh_th = 1 ./ tau_sp_sh_th;
  100. k_sh_sp_th = k_sp_sh_th .* nu ./ (1 - nu);
  101. % Total theoretical exchange rate
  102. k_th = k_sp_sh_th + k_sh_sp_th;
  103. tau_th = 1 ./ k_th;
  104. % --- Estimated exchange rates (from data) ---
  105. tau_sp_sh = rr; % Estimated spine→shaft time
  106. k_sp_sh = 1 ./ tau_sp_sh; % Corresponding rate
  107. % Estimated shaft→spine rate (depends on volume fractions)
  108. k_sh_sp = k_sp_sh .* nu' ./ (1 - nu');
  109. tau_sh_sp = 1 ./ k_sh_sp;
  110. % Total effective exchange rate
  111. k = k_sh_sp + k_sp_sh;
  112. tau = 1 ./ k;
  113. % --- Plot results ---
  114. figure('Color', 'w'); hold on;
  115. % Theoretical rates
  116. plot(rho(2:end), k_sp_sh_th .* ones(size(nu(2:end))), ...
  117. '-', 'Color', [0.15, 0.15, 0.15], 'LineWidth', 3);
  118. plot(rho(2:end), k_th(2:end), ...
  119. '-', 'Color', [0.64,0.08,0.18], 'LineWidth', 3);
  120. % Estimated rates
  121. plot(rho(2:end), smooth(k_sp_sh(2:end)), ...
  122. '--', 'Color', [0.15, 0.15, 0.15], 'LineWidth', 4);
  123. plot(rho(2:end), smooth(k(2:end)), ...
  124. '--', 'Color', [0.64,0.08,0.18], 'LineWidth', 4);
  125. % Labels and styling
  126. set(gca, 'FontName', 'Cambria', 'FontSize', 24);
  127. xlabel('Spine density [\mum^{-1}]', 'FontWeight', 'bold');
  128. ylabel('Exchange rate [ms^{-1}]', 'FontWeight', 'bold');
  129. box on; grid on;
  130. legend( ...
  131. {'k_{sp→sh} (theory)', 'k_{ex}^{DM} (theory)', ...
  132. 'k_{sp→sh} (simulation)', 'k_{ex}^{DM} (simulation)'}, ...
  133. 'Location', 'northeastoutside', 'FontSize', 24);
  134. % title('Exchange Rate: Spine ↔ Shaft', ...
  135. % 'FontWeight', 'bold', 'Interpreter', 'tex', 'Units', 'normalized', ...
  136. % 'Position', [0.5, 1.02, 0]);
  137. %% ==============================================
  138. % Plot parallel diffusion signals vs b
  139. % ==============================================
  140. bth = linspace(0.001, max(b), 100);
  141. n = numel(nu(1:2:end));
  142. left_margin = 0.07;
  143. right_margin = 0.05;
  144. space_between = 0.08;
  145. width = (1 - left_margin - right_margin - (n-1)*space_between)/n;
  146. height = 0.6;
  147. bottom = 0.15;
  148. figure
  149. colors = copper(length(delta)+1);
  150. for i = 1:n
  151. left = left_margin + (i-1)*(width + space_between);
  152. ax(i) = subplot(1,5,i);
  153. hold on
  154. Ytmp_exp = reshape(Y(2*i-1,:), [numel(b), numel(delta)]);
  155. Ytmp_th = reshape(modifiedKargerParallel(De, tau_sp_sh(2*i-1), nu(2*i-1), bth, td), [numel(bth), numel(delta)]);
  156. legendtxt = cell(numel(delta),1);
  157. for j = 1:numel(delta)
  158. h_exp(j) = plot(b, Ytmp_exp(:,j), 'o', 'MarkerSize', 10, ...
  159. 'MarkerEdgeColor','k', 'MarkerFaceColor',colors(j,:), ...
  160. 'LineWidth',0.5);
  161. plot(bth, Ytmp_th(:,j), '-', 'Color',colors(j,:), 'LineWidth',2);
  162. legendtxt{j} = sprintf('t_d = %.0f ms', td(j));
  163. end
  164. % Axes formatting
  165. set(ax(i), 'Position', [left, bottom, width, height], ...
  166. 'YScale', 'log', ...
  167. 'FontName', 'Cambria', ...
  168. 'FontSize', 24, ...
  169. 'Box', 'on', ...
  170. 'LineWidth', 1.5);
  171. grid on
  172. xlabel('b [ms/\mum^2]', 'FontName', 'Cambria', 'FontSize', 24)
  173. ylabel('S_{||}', 'FontName', 'Cambria', 'FontSize', 24)
  174. title(['\rho = ' num2str(rho(2*i-1)) ' \mum^{-1}'], ...
  175. 'Interpreter', 'tex', 'FontSize', 24)
  176. box on; grid on;
  177. axis([0 8 1e-6 1]);
  178. yticks([1e-6 1e-4 1e-2 1e0]);
  179. yticklabels({'10^{-6}','10^{-4}','10^{-2}','10^{0}'});
  180. end
  181. legend_handle = legend(h_exp, legendtxt, 'FontSize',24, ...
  182. 'Orientation','horizontal', 'Box','on', ...
  183. 'Position',[0.35 0.9 0.3 0.05]);
  184. %% ==============================================
  185. % Estimate direction-average signal assuming Sperp=1
  186. % (for narrow pulse scheme)
  187. % ==============================================
  188. % Empirical parallel diffusivity values [µm²/ms]
  189. % estimated from simulated or measured trajectories
  190. Dpar = [2.00410277 1.81620312 1.66844738 1.53665382 ...
  191. 1.42504216 1.33651321 1.22414968 1.10610485 ...
  192. 1.01157496 0.94218438];
  193. % Corresponding spine density or frequency (arbitrary units)
  194. % Ensure 'nu' is defined before this section, e.g.:
  195. % nu = linspace(0.01, 0.1, numel(Dpar));
  196. % (This should match your Dpar data)
  197. % Linear regression between Dpar and spine density
  198. p = polyfit(nu, Dpar, 1); % p(1) = slope, p(2) = intercept
  199. % Display fit coefficients
  200. fprintf('Linear fit: Dpar = %.4f * nu + %.4f\n', p(1), p(2));
  201. % Extrapolate Dpar for a continuous spine volume fraction range
  202. fextra = 0.25; % extracellular volume fraction
  203. Dpar_fit = polyval(p, nu); % extrapolated Dpar values
  204. nu_tot = nu .* (1-fextra);
  205. figure('Color', 'w'); hold on
  206. plot(nu_tot, Dpar, 'o', 'MarkerSize', 12, 'MarkerFaceColor', 'k', 'MarkerEdgeColor', 'k',...
  207. 'DisplayName', 'Simulated D_{||}', 'LineWidth',0.5)
  208. plot(nu_tot, Dpar_fit, '-', ...
  209. 'Color', [0.64,0.08,0.18],...
  210. 'LineWidth', 3, 'DisplayName', 'Linear fit')
  211. text_str = sprintf('D_{||} = %.4f * ν + %.4f', p(1), p(2));
  212. text(0.1, 1, text_str, ...
  213. 'Color', 'k', ...
  214. 'FontSize', 20, ...
  215. 'FontWeight', 'bold', ...
  216. 'HorizontalAlignment', 'left', ...
  217. 'VerticalAlignment', 'bottom')
  218. xlabel('Total spine volume fraction')
  219. ylabel('D_{||} [\mum^2/ms]')
  220. legend('Location', 'northeast', 'Box', 'on')
  221. grid on; box on
  222. set(gca, 'FontName', 'Cambria', 'FontSize', 24)
  223. % Generate Dpar values for signal simulations
  224. nu_th = linspace(0, max(nu), 51); % spine volume fraction [a.u.]
  225. Dpar = polyval(p, nu_th);
  226. rr_nexi = zeros(numel(nu_th),4);
  227. rr_nexi_corr = zeros(numel(nu_th),3);
  228. % Parameter bounds
  229. lb = [0 0 0 0]; % lower bounds
  230. ub = [inf 1.0 3.0 3.0]; % upper bounds
  231. % Number of random initializations
  232. Nsamples = 10;
  233. % Initial guesses (based on true parameters)
  234. r0 = [100 1 3 3] .* rand(Nsamples, 4);
  235. r0_corr = [100 1 3] .* rand(Nsamples, 3);
  236. for i = 1:numel(nu_th)
  237. Ytmp = zeros(numel(delta), numel(b));
  238. % --- Simulate signals for different diffusion times ---
  239. for j = 1:numel(delta)
  240. Ytmp(j,:) = (1-fextra) .* integral(@(x) ...
  241. modifiedKargerParallel(De, tau_sp_sh_th, nu_th(i), b.*x.^2, td(j)), ...
  242. 0, 1, 'AbsTol', 1e-14, 'ArrayValued', true)' ...
  243. + fextra .* exp(-1.0*b)';
  244. end
  245. % --- NEXI fit + data (diffusion-time subset depends on the pulse scheme) ---
  246. switch lower(pulse)
  247. case 'narrow' % 5 diffusion times
  248. ffit0 = @(p,x) [nexiSignal(x, td(1), p(1), p(3), p(4), p(4), p(2)), ...
  249. nexiSignal(x, td(2), p(1), p(3), p(4), p(4), p(2)), ...
  250. nexiSignal(x, td(3), p(1), p(3), p(4), p(4), p(2)), ...
  251. nexiSignal(x, td(4), p(1), p(3), p(4), p(4), p(2)), ...
  252. nexiSignal(x, td(5), p(1), p(3), p(4), p(4), p(2))];
  253. ffit0_corr = @(p,x) [nexiSignal(x, td(1), p(1), Dpar(i), p(3), p(3), p(2)), ...
  254. nexiSignal(x, td(2), p(1), Dpar(i), p(3), p(3), p(2)), ...
  255. nexiSignal(x, td(3), p(1), Dpar(i), p(3), p(3), p(2)), ...
  256. nexiSignal(x, td(4), p(1), Dpar(i), p(3), p(3), p(2)), ...
  257. nexiSignal(x, td(5), p(1), Dpar(i), p(3), p(3), p(2))];
  258. Yfit = [Ytmp(1,:), Ytmp(2,:), Ytmp(3,:), Ytmp(4,:), Ytmp(5,:)];
  259. case 'wide' % 3 diffusion times (t_d = 20, 30, 50 ms)
  260. ffit0 = @(p,x) [nexiSignal(x, td(1), p(1), p(3), p(4), p(4), p(2)), ...
  261. nexiSignal(x, td(2), p(1), p(3), p(4), p(4), p(2)), ...
  262. nexiSignal(x, td(3), p(1), p(3), p(4), p(4), p(2))];
  263. ffit0_corr = @(p,x) [nexiSignal(x, td(1), p(1), Dpar(i), p(3), p(3), p(2)), ...
  264. nexiSignal(x, td(2), p(1), Dpar(i), p(3), p(3), p(2)), ...
  265. nexiSignal(x, td(3), p(1), Dpar(i), p(3), p(3), p(2))];
  266. Yfit = [Ytmp(1,:), Ytmp(2,:), Ytmp(3,:)];
  267. otherwise
  268. error('pulse must be ''narrow'' or ''wide''.')
  269. end
  270. % --- Stabilize Fitting ---
  271. tmp = zeros(Nsamples, 4);
  272. resnorm = zeros(Nsamples, 1);
  273. tmp2 = zeros(Nsamples, 3);
  274. resnorm2 = zeros(Nsamples, 1);
  275. % Multiple random initializations
  276. parfor j = 1:Nsamples
  277. [tmp(j, :), resnorm(j)] = lsqcurvefit(ffit0, r0(j,:), b, Yfit, lb, ub, options);
  278. [tmp2(j,:), resnorm2(j)] = lsqcurvefit(ffit0_corr, r0_corr(j,:), b, Yfit, lb(1:end-1), ub(1:end-1), options);
  279. end
  280. % Select best fits
  281. [~, idx] = sort(resnorm);
  282. tmp = tmp(idx, :);
  283. r0_opt = mean(tmp(1:10, :), 1);
  284. [~, idx] = sort(resnorm2);
  285. tmp2 = tmp2(idx, :);
  286. r0_opt2 = mean(tmp2(1:10, :), 1);
  287. % Final fits with optimized starting point
  288. rr_nexi(i,:) = lsqcurvefit(ffit0, r0_opt, b, Yfit, lb, ub, options);
  289. rr_nexi_corr(i,:) = lsqcurvefit(ffit0_corr, r0_opt2, b, Yfit, lb(1:end-1), ub(1:end-1), options);
  290. % Progress indicator
  291. if mod(i, 5) == 0 || i == size(Yfit, 2)
  292. fprintf(' Fitted %d/%d datasets\n', i, size(Yfit, 2));
  293. end
  294. % rr_nexi(i,:) = lsqcurvefit(ffit0, r0, b, Yfit, lb, ub, options);
  295. % rr_nexi(i,:) = initModelFitting(ffit0, b, Yfit, [0 0 0 0], [inf 1 3 3], 1000);
  296. % rr_nexi_corr(i,:) = lsqcurvefit(ffit0_corr, r0_corr, b, Yfit, lb(1:end-1), ub(1:end-1), options);
  297. % rr_nexi_corr(i,:) = initModelFitting(ffit0_corr, b, Yfit, [0 0 0], [inf 1 3], 1000);
  298. end
  299. % Plot: t_ex^{NEXI}
  300. figure('Color','w'); hold on;
  301. plot(nu_th.*(1-fextra), smooth(rr_nexi(:,1)), 'k-', 'LineWidth', 4.0)
  302. plot(nu_th.*(1-fextra), smooth(rr_nexi_corr(:,1)), '-', ...
  303. 'Color', [0.64,0.08,0.18], ...
  304. 'LineWidth', 4.0)
  305. xlabel('Total spine volume fraction', 'FontName', 'Cambria', 'FontSize', 24)
  306. ylabel('Estimated t_{ex}^{NEXI} [ms^{-1}]', 'FontName', 'Cambria', 'FontSize', 24)
  307. ylim([0 1000])
  308. xlim([0 0.2])
  309. set(gca, 'FontName', 'Cambria', 'FontSize', 24, 'LineWidth', 1.5, 'Box', 'on')
  310. grid on
  311. legend({'D_i unconstrained', 'D_i constrained'}, 'Location', 'D_i unconstrained', ...
  312. 'Orientation', 'horizontal', 'FontSize', 22, 'Box', 'on')
  313. % Plot: k_ex^{NEXI}
  314. figure('Color','w'); hold on;
  315. plot(nu_th.*(1-fextra), 1./smooth(rr_nexi(:,1)), 'k-', 'LineWidth', 4.0)
  316. plot(nu_th.*(1-fextra), smooth(1./rr_nexi_corr(:,1)), '-', ...
  317. 'Color', [0.64,0.08,0.18],...
  318. 'LineWidth', 4.0)
  319. xlabel('Total spine volume fraction', 'FontName', 'Cambria', 'FontSize', 24)
  320. ylabel('Estimated k_{ex}^{NEXI} [ms^{-1}]', 'FontName', 'Cambria', 'FontSize', 24)
  321. xlim([0 0.2])
  322. ylim([0 0.1])
  323. set(gca, 'FontName', 'Cambria', 'FontSize', 24, 'LineWidth', 1.5, 'Box', 'on')
  324. grid on
  325. legend({'D_i unconstrained', 'D_i constrained'}, 'Location', 'D_i unconstrained', ...
  326. 'Orientation', 'horizontal', 'FontSize', 22, 'Box', 'on')
  327. %% ===============================================================
  328. % Analyse perpendicular signals
  329. % ===============================================================
  330. Y = [];
  331. % --- Collect perpendicular signals (field name adapts to the pulse scheme) ---
  332. for i = 1:numel(delta)
  333. s = eval(sprintf('D%03d_d%02d', delta(i), smalldelta(1)));
  334. Y = [Y, s.perpendicular];
  335. end
  336. Tperp = Y;
  337. % --- Fit monoexponential model to perpendicular signals ---
  338. monoRR = zeros(numel(nu), numel(delta));
  339. kurtRR_perp = zeros(numel(nu), numel(delta), 2);
  340. for i = 1:numel(nu)
  341. for j = 1:numel(delta)
  342. monoexpFit = @(p, x) exp(-p(1) .* x);
  343. p0 = 2;
  344. monoRR(i, j, :) = lsqcurvefit( ...
  345. monoexpFit, p0, ...
  346. b(1:2), ...
  347. Y(i, (j-1)*numel(b) + (1:2)), ...
  348. 0, 2);
  349. end
  350. end
  351. % --- Plot ADC_perp vs diffusion time (t_d) ---
  352. figure('Color', 'w'); hold on;
  353. colors = bone(numel(nu(1:2:end)) + 2);
  354. legendtxt = cell(numel(nu(1:2:end)), 1);
  355. h = gobjects(numel(nu(1:2:end)), 1); % preallocate for legend handles
  356. for j = 1:numel(nu(1:2:end))
  357. % Extract fitted ADC_perp values
  358. y = squeeze(monoRR(j, :));
  359. % Plot fitted values (lines + scatter)
  360. h(j) = plot(td, y, '-', ...
  361. 'LineWidth', 4, ...
  362. 'Color', colors(j,:), ...
  363. 'DisplayName', sprintf('\\rho = %.2f \\mum^{-1}', rho(2*(j-1)+1)));
  364. plot(td, y, 'o', ...
  365. 'MarkerSize', 10, ...
  366. 'MarkerEdgeColor', 'k', ...
  367. 'MarkerFaceColor', colors(j,:), ...
  368. 'LineWidth', 1.2);
  369. end
  370. % --- Axes and labels formatting ---
  371. xlabel('t_d [ms]');
  372. ylabel('ADC_{\perp}(t) [\mum^2/ms]');
  373. set(gca, ...
  374. 'FontName', 'Cambria', ...
  375. 'FontSize', 24, ...
  376. 'LineWidth', 1.5, ...
  377. 'Box', 'on');
  378. grid on; box on;
  379. % --- Common legend (top-centered) ---
  380. legend_handle = legend(h, 'Orientation', 'vertical', ...
  381. 'FontSize', 24, 'Box', 'on', 'Location', 'northeast');
  382. set(legend_handle, 'Units', 'normalized');
  383. % legend_pos = get(legend_handle, 'Position');
  384. % legend_pos(2) = 0.92; % push slightly upward
  385. % legend_pos(1) = 0.5 - legend_pos(3)/2; % center horizontally
  386. % set(legend_handle, 'Position', legend_pos);
  387. % ylim([0 2.5]); % optional range for ADC
  388. xlim([min(td) max(td)]);
  389. %% ==============================================
  390. % Plot D_perp(t) vs 1/t_d for all nu with linear fits
  391. % ==============================================
  392. figure('Color','w'); hold on;
  393. colors = bone(numel(nu) + 2);
  394. legendtxt = cell(numel(nu),1);
  395. h = gobjects(numel(nu),1);
  396. Reff = zeros(numel(nu),1);
  397. for j = 1:numel(nu)
  398. % Extract ADC_perp(t) for this rho
  399. Dperp_t = squeeze(monoRR(j,3:end)); % Estimated diffusivity
  400. tvals = td(3:end); % Diffusion times [ms]
  401. inv_t = 1 ./ tvals; % Inverse diffusion time [ms^-1]
  402. % --- Linear regression: D = a*(1/t) ---
  403. p = inv_t(:)\Dperp_t(:);
  404. Dfit = p.*inv_t;
  405. % Effective radius from slope: a = R^2 / 4
  406. Reff(j) = sqrt(4 * p(1));
  407. % --- Plot experimental data ---
  408. h(j) = plot(inv_t, Dperp_t, 'o', ...
  409. 'MarkerSize', 10, ...
  410. 'MarkerEdgeColor', 'k', ...
  411. 'MarkerFaceColor', colors(j,:), ...
  412. 'LineWidth', 1.2, ...
  413. 'DisplayName', sprintf('\\rho = %.2f \\mum^{-1}', rho(j)));
  414. % --- Plot fitted line ---
  415. plot(inv_t, Dfit, '-', ...
  416. 'Color', colors(j,:), ...
  417. 'LineWidth', 3);
  418. end
  419. % --- Axes formatting ---
  420. xlabel('1/t_d [ms^{-1}]', 'FontName', 'Cambria', 'FontSize', 28);
  421. ylabel('D_{\perp}(t) [\mum^2/ms]', 'FontName', 'Cambria', 'FontSize', 28);
  422. set(gca, ...
  423. 'FontName', 'Cambria', ...
  424. 'FontSize', 24, ...
  425. 'LineWidth', 1.5, ...
  426. 'Box', 'on');
  427. grid on; box on;
  428. % --- Common legend (top-centered) ---
  429. legend_handle = legend(h, 'Orientation', 'horizontal', ...
  430. 'NumColumns',2,'FontSize', 24, 'Box', 'on', 'Location', 'northwest');
  431. set(legend_handle, 'Units', 'normalized');
  432. % legend_pos = get(legend_handle, 'Position');
  433. % legend_pos(2) = 0.92; % slightly higher
  434. % legend_pos(1) = 0.5 - legend_pos(3)/2; % center align
  435. % set(legend_handle, 'Position', legend_pos);
  436. % --- Axis limits (optional) ---
  437. % ylim([0 2.5]);
  438. % xlim([min(inv_t) max(inv_t)]);
  439. % --- Display fitted effective radii ---
  440. disp(table(rho(:), Reff(:), 'VariableNames', {'rho_um_inv', 'Reff_um'}));
  441. %% ============================================================
  442. % Fit perpendicular signal using Neuman model
  443. % ============================================================
  444. figure('Color', 'w'); hold on; box on; grid on;
  445. % Neuman cylinder perpendicular signal (src/Neumann_perp.m), stacked over
  446. % gradient separations: p = [D0, R] (Neumann_perp's own convention), one
  447. % block of b-values per gradient separation listed in 'delta'.
  448. ffit_neuman = @(p, x) cell2mat(arrayfun(@(gradSep) ...
  449. neumanPerpendicular([p(1), p(2)], x, smalldelta(1), gradSep).', ...
  450. delta, 'UniformOutput', false));
  451. % Preallocate results: columns = [D0, R]
  452. rr_neuman = zeros(numel(nu), 2);
  453. % Define color gradient (blueish)
  454. colors = [zeros(size(nu')) ...
  455. 1 - (numel(nu) - (1:numel(nu))') ./ numel(nu) ...
  456. 1 - (numel(nu) - (1:numel(nu))') ./ numel(nu)] .* 0.8;
  457. % Fit and plot for each ν value
  458. for i = 1:numel(nu)
  459. Yfit = Y(i,:);
  460. % Fit parameters [D0, R]
  461. rr_neuman(i,:) = lsqcurvefit(ffit_neuman, [D, Rsh], b, Yfit, [0 0], [4 10], options);
  462. % Experimental data
  463. plot(Y(i,:), '-', ...
  464. 'MarkerEdgeColor', colors(i,:), ...
  465. 'MarkerFaceColor', colors(i,:), ...
  466. 'MarkerSize', 8, ...
  467. 'LineWidth', 3); hold on;
  468. % Fitted curve
  469. plot(ffit_neuman(rr_neuman(i,:), b), '-', ...
  470. 'Color', colors(i,:), ...
  471. 'LineWidth', 2.0);
  472. % Axes labels
  473. ylabel('S_{\perp}', 'FontName', 'Cambria', 'FontSize', 20)
  474. xlabel('Measurements', 'FontName', 'Cambria', 'FontSize', 20)
  475. end
  476. set(gca, 'FontName', 'Cambria', 'FontSize', 20)
  477. title('Neuman Model Fits for Each \nu', 'FontSize', 22)
  478. legend(arrayfun(@(x) sprintf('\\nu = %.2f', x), nu, 'UniformOutput', false), ...
  479. 'Location', 'northeastoutside', 'Box', 'off')
  480. %% ============================================================
  481. % Plot estimated effective fiber diameter
  482. % ============================================================
  483. figure('Color', 'w'); hold on; box on; grid on;
  484. % Reference expected geometric diameter
  485. plot(rho, ones(size(rho)) .* (Rsh + Ln + 2 * Rh), 'k-', 'LineWidth', 3.0)
  486. % Estimated effective radius (fitted) -- column 2 is R, see ffit_neuman above
  487. plot(rho, rr_neuman(:,2), 'k--', 'LineWidth', 3.0)
  488. plot(rho, Reff(:,1), 'r:', 'LineWidth', 3.0)
  489. % Formatting
  490. xlabel('Spine density [\mum^{-1}]', 'FontName', 'Cambria', 'FontSize', 24)
  491. ylabel('Estimated effective fiber diameter [\mum]', 'FontName', 'Cambria', 'FontSize', 24)
  492. set(gca, 'FontName', 'Cambria', 'FontSize', 24)
  493. legend({'2*R_{head}+L_n+R_{shaft}','Neuman R_{eff}', 'R^2/4t'}, ...
  494. 'Location', 'southeast', 'Box', 'off')
  495. %% ============================================================
  496. % Plot perpendicular signal vs b
  497. % ============================================================
  498. bth = linspace(0.001, max(b), 100);
  499. n = numel(nu(1:2:end)); % number of subplots
  500. left_margin = 0.05;
  501. right_margin = 0.05;
  502. space_between = 0.06;
  503. width = (1 - left_margin - right_margin - (n-1)*space_between) / n;
  504. height = 0.6;
  505. bottom = 0.15;
  506. figure('Color', 'w');
  507. hold on
  508. colors = copper(numel(delta));
  509. legendtxt = cell(numel(delta), 1);
  510. h_all = gobjects(1, numel(delta)); % preallocate graphic handles
  511. for i = 1:n
  512. left = left_margin + (i-1)*(width + space_between);
  513. ax(i) = subplot(1, n, i);
  514. hold on
  515. % Extract data
  516. Ytmp_exp = reshape(Y(2*i-1,:), [numel(b), numel(delta)]);
  517. Ytmp_th = reshape(ffit_neuman(rr_neuman(2*i-1,:), bth), [numel(bth), numel(delta)]);
  518. % Plot experimental and theoretical curves
  519. for j = 1:numel(delta)
  520. % Experimental data (scatter)
  521. h = plot(b, Ytmp_exp(:,j), 'o', ...
  522. 'MarkerSize', 12, ...
  523. 'MarkerEdgeColor', 'k', ...
  524. 'MarkerFaceColor', colors(j,:), ...
  525. 'LineWidth', .5);
  526. % plot(b, Ytmp_exp(:,j), '-', ...
  527. % 'Color', colors(j,:), ...
  528. % 'LineWidth', 2.0);
  529. % % Theoretical model (line)
  530. plot(bth, Ytmp_th(:,j), '-', ...
  531. 'Color', colors(j,:), ...
  532. 'LineWidth', 2.0);
  533. % Store handles and labels for legend (only from first subplot)
  534. if i == 1
  535. h_all(j) = h;
  536. legendtxt{j} = ['t_d = ' num2str(td(j)) ' ms'];
  537. end
  538. end
  539. % Axes formatting
  540. set(ax(i), 'Position', [left, bottom, width, height], ...
  541. 'YScale', 'log', ...
  542. 'FontName', 'Cambria', ...
  543. 'FontSize', 24, ...
  544. 'Box', 'on', ...
  545. 'LineWidth', 1.5);
  546. grid on
  547. xlabel('b [ms/\mum^2]', 'FontName', 'Cambria', 'FontSize', 24)
  548. ylabel('S_{\perp}', 'FontName', 'Cambria', 'FontSize', 24)
  549. title(['\rho = ' num2str(rho(2*i-1)) ' \mum^{-1}'], ...
  550. 'Interpreter', 'tex', 'FontSize', 24)
  551. axis([0 8 0.6 1])
  552. end
  553. % Common legend (top-centered, using stored handles)
  554. legend_handle = legend(h_all, legendtxt, ...
  555. 'Orientation', 'horizontal', ...
  556. 'FontSize', 24, ...
  557. 'Box', 'on', ...
  558. 'Location', 'northoutside');
  559. % Adjust legend position slightly higher for visibility
  560. set(legend_handle, 'Units', 'normalized');
  561. legend_pos = get(legend_handle, 'Position');
  562. legend_pos(2) = 0.9; % Move legend upward
  563. legend_pos(1) = 0.5 - legend_pos(3)/2; % Center align horizontally
  564. set(legend_handle, 'Position', legend_pos);

diffusion_signal_analysis.m at commit 8ac692e, no license · at the source

Overview

  1. Cardiff University Brain Research Imaging Centre (CUBRIC) Cardiff University Cardiff UK
  2. School of Computer Science and Informatics Cardiff University Cardiff UK
  3. Medical Radiation Physics, Lund Lund University Lund Sweden
  4. Department of Clinical Sciences Lund, Radiology Lund University Lund Sweden
Institutions: Cardiff University (United Kingdom); Lund University (Sweden)
Journal: NMR in biomedicine, volume 39, issue 10, article e70382
Dates: received 24 June 2025; accepted 17 August 2026; published online 11 September 2026; in print October 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1002/nbm.70382 · PMID 42727943 · PMCID PMC13569403 · OpenAlex W4414987736
Open access: hybrid, a free copy (OpenAlex)
Status: code verified (how the code is found and verified)
Categories: structural MRI / diffusion (modality), histology / microscopy (modality), none (in silico) (organism), computational (subfield)
Methods: Statistics, Physiology & signal measures
Keywords: dendritic spines, diffusion, exchange, microstructure, modelling, MRI, time‐dependence
MeSH: Dendritic Spines*, Diffusion Magnetic Resonance Imaging*, Water*, Animals, Computer Simulation, Diffusion, Monte Carlo Method, Time Factors (* major topic)
Topic: Advanced Neuroimaging Techniques and Applications (Radiology, Nuclear Medicine and Imaging, Medicine), according to OpenAlex
Funding: UK Research and Innovation (MR/T020296/2); Swedish Research Council (2024‐04968); Hjärnfonden (FO2024‐0335‐HK‐73)
Citations: cited by 1 paper (Europe PMC); 137 references in the paper

Abstract

Time‐dependent diffusion MRI (dMRI) using single diffusion encoding (SDE) is sensitive to water dynamics in biological tissues, yet interpreting its signals requires careful consideration of underlying microstructure. While prior work has focused on restricted/hindered diffusion and membrane permeation, additional exchange mechanisms such as diffusion‐mediated exchange between dendritic shaft and spines in gray matter (GM) remain understudied. Here, we hypothesize that water diffusion within impermeable spiny dendrites can produce time‐dependent SDE signals indistinguishable from those arising from permeative exchange; and assess to what extent spine density impacts estimates of exchange time. Using Monte Carlo simulations and analytical solutions from the narrow escape problem, we quantify spine–shaft and shaft–spine exchange times, revealing characteristic times (1–50 ms) comparable to permeative exchange estimates in the cortex. We show that a modified two‐compartment Kärger model accurately captures the time‐dependent SDE signal along spiny dendrites but yields exchange estimates that reflect total spine volume fraction rather than specific spine morphology. Simulations reveal that unaccounted diffusion‐mediated exchange from dendritic spines substantially biases Neurite Exchange Imaging (NEXI) estimates, inflating the apparent exchange rate and the inferred membrane permeability in proportion to spine volume fraction. Further, we propose an extended three‐compartment Kärger model (and its coarse‐grained version) incorporating both diffusion‐mediated exchange between dendritic shaft and spines and permeative exchange with extracellular space. Critically, while the three‐compartment Kärger model and its coarse‐grained version capture both exchange mechanisms, they cannot uniquely disentangle membrane permeability from spine volume fraction. Finally, we highlight the importance of accounting for dendritic spines when inferring membrane permeability from diffusion MRI exchange rates, as the additional membrane area contributed by spines increases the effective dendritic surface‐to‐volume ratio by approximately 24%–60% for realistic spine densities and, if neglected, leads to a corresponding overestimation of the true membrane permeability. These findings underscore the necessity of considering dendritic spine contributions when interpreting time‐dependent SDE data and caution against attributing exchange effects solely to membrane permeability. Our study further highlights the need for advanced acquisition and modeling approaches to differentiate permeative and diffusion‐mediated geometric exchange in GM.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repository

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

kdrsimsek/dendriticSpines_exchange

License: none: the authors keep all their rights
State: the link answers, verified on 1 October 2026
Evidence: files inventoried
Commit: 8ac692edcd01a7a641d734c12fe3483660728aa0, 13 September 2026
Languages: MATLAB (25), Python (1)
Size: 90 files, 26 scripts
Software Heritage: not archived
Found in: “Data Availability Statement”
Holds: README
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Optimization Toolbox (9 files), LMFIT (1 file), Matplotlib (1 file), NumPy (1 file)
Availability: 1 check, the latest on 1 October 2026: the link answers
  • 1 October 2026: the link answers
27 files

The paper's code and data availability statement is in the Data section.

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:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 26 scripts, each with its path and the digest of its content;
  • 10 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.

Data Availability Statement

All the data and analysis codes underpinning the results presented here can be found upon publication in the Cardiff University data catalogue and on Github: https://github.com/kdrsimsek/dendriticSpines_exchange.

Reproduced under the paper's license (CC BY), from the paper cited above.

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, 1 October 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 4 authors, 7 keywords, 8 MeSH terms, 3 funders, 126 references.

Cite

This paper

Şimşek, K., Chakwizira, A., Nilsson, M., & Palombo, M. (2026). The Role of Dendritic Spines in Water Exchange Measurements With Diffusion MRI: Time-Dependent Single Diffusion Encoding MRI. NMR in biomedicine, 39(10), e70382. https://doi.org/10.1002/nbm.70382

BibTeX

@article{simsek2026role,
author = {Şimşek, Kadir and Chakwizira, Arthur and Nilsson, Markus and Palombo, Marco},
title = {{The Role of Dendritic Spines in Water Exchange Measurements With Diffusion MRI: Time-Dependent Single Diffusion Encoding MRI}},
journal = {NMR in biomedicine},
year = {2026},
month = oct,
volume = {39},
number = {10},
pages = {e70382},
publisher = {Wiley},
issn = {0952-3480},
doi = {10.1002/nbm.70382},
url = {https://doi.org/10.1002/nbm.70382},
pmid = {42727943},
pmcid = {PMC13569403}
}

RIS

TY - JOUR
AU - Şimşek, Kadir
AU - Chakwizira, Arthur
AU - Nilsson, Markus
AU - Palombo, Marco
TI - The Role of Dendritic Spines in Water Exchange Measurements With Diffusion MRI: Time-Dependent Single Diffusion Encoding MRI
T2 - NMR in biomedicine
J2 - NMR Biomed
PY - 2026
DA - 2026/10/01
VL - 39
IS - 10
SP - e70382
SN - 0952-3480
PB - Wiley
DO - 10.1002/nbm.70382
UR - https://doi.org/10.1002/nbm.70382
LA - en
ER -

CSL-JSON

{
"id": "10.1002/nbm.70382",
"type": "article-journal",
"title": "The Role of Dendritic Spines in Water Exchange Measurements With Diffusion MRI: Time-Dependent Single Diffusion Encoding MRI",
"container-title": "NMR in biomedicine",
"author": [
{
"family": "Şimşek",
"given": "Kadir"
},
{
"family": "Chakwizira",
"given": "Arthur"
},
{
"family": "Nilsson",
"given": "Markus"
},
{
"family": "Palombo",
"given": "Marco"
}
],
"container-title-short": "NMR Biomed",
"volume": "39",
"issue": "10",
"page": "e70382",
"DOI": "10.1002/nbm.70382",
"PMID": "42727943",
"PMCID": "PMC13569403",
"ISSN": "0952-3480",
"publisher": "Wiley",
"URL": "https://doi.org/10.1002/nbm.70382",
"language": "en",
"issued": {
"date-parts": [
[
2026,
10,
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.1038/s41598-025-93084-4 [code]
Diffusion MRI with double diffusion encoding and variable mixing times disentangles water exchange from transient kurtosis.
Journal: Scientific reports
In common: Optimization Toolbox, histology / microscopy, structural MRI / diffusion, 26 references, author Arthur Chakwizira
[2] doi:10.1016/j.mrl.2025.200225 [code]
Passive water exchange between multiple sites can explain why apparent exchange rate constants depend on ionic and osmotic conditions in gray matter.
Journal: Magnetic resonance letters
In common: Optimization Toolbox, 30 references
[3] doi:10.1162/imag_a_00544 [code]
&lt;i&gt;In vivo&lt;/i&gt; human neurite exchange time imaging at 500 mT/m diffusion gradients: Neurite exchange time imaging on Connectome 2.0.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: Optimization Toolbox, structural MRI / diffusion, 23 references
[4] doi:10.1162/imag.a.1317 [code]
Bayesian insights into exchange and restriction in gray matter diffusion MRI.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: Matplotlib, NumPy, computational, structural MRI / diffusion, 20 references, author Marco Palombo
[5] doi:10.1162/imag.a.35 [code]
Spectral principal axis system (SPAS) and tuning of tensor-valued encoding for microscopic anisotropy and time-dependent diffusion in the rat brain.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: Optimization Toolbox, histology / microscopy, structural MRI / diffusion, 18 references, author Markus Nilsson
[6] doi:10.1162/imag_a_00104 [code]
Quantifying human gray matter microstructure using neurite exchange imaging (NEXI) and 300 mT/m gradients.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: NumPy, computational, structural MRI / diffusion, 17 references, author Marco Palombo
[7] doi:10.1038/s42003-025-09353-5 [code]
Decoding gray matter, large-scale analysis of brain cell morphometry to inform microstructural modeling of diffusion MR signals.
Journal: Communications biology
In common: structural MRI / diffusion, 17 references, author Marco Palombo
[8] doi:10.1002/mrm.70490 [code]
Dependence of the Extra-Cellular Diffusion Coefficient on the Fractions of Neurites and Cell Bodies in Gray Matter.
Journal: Magnetic resonance in medicine
In common: structural MRI / diffusion, 17 references
[9] doi:10.64898/2026.02.11.705314 [code]
Validating Neurite EXchange Imaging (NEXI) using diffusion Monte Carlo simulations in realistic numerical gray matter substrates
Journal: bioRxiv (preprint)
In common: Matplotlib, NumPy, none (in silico), computational, structural MRI / diffusion, 15 references
[10] doi:10.1162/imag_a_00335
Mean Kärger Model Water Exchange Rate in Brain.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: 14 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.

Add the badge to the code's README

OSCR: the badge of this paper

If you are an author or a maintainer of this paper's code, you can add this badge. It says what OSCR knows of the paper (its code, its validated tracing map) and links the code to this page. Paste one of these snippets under the README's title. Keep the two marks around it, so that the badge can be replaced in place and is never added twice. OSCR changes nothing in your repository.

Markdown
<!-- oscr-badge:start -->
[![OSCR](https://openscicode.org/badge/doi/10.1002/nbm.70382.svg)](https://openscicode.org/badge/doi/10.1002/nbm.70382)
<!-- oscr-badge:end -->
reStructuredText
.. oscr-badge:start

.. image:: https://openscicode.org/badge/doi/10.1002/nbm.70382.svg
   :target: https://openscicode.org/badge/doi/10.1002/nbm.70382
   :alt: OSCR

.. oscr-badge:end
HTML
<!-- oscr-badge:start -->
<a href="https://openscicode.org/badge/doi/10.1002/nbm.70382"><img src="https://openscicode.org/badge/doi/10.1002/nbm.70382.svg" alt="OSCR"></a>
<!-- oscr-badge:end -->

On GitHub, open the README, choose Edit (the pencil), paste the snippet under the title, then "Commit changes".

If you choose to, you can have the badge kept up to date for you, with oscr badge --write from the command line or with the GitHub Action in your repository's workflows. Every other form and option (a card, AsciiDoc, LaTeX, shields.io) is on the badge 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: code errors and mismatches between the code and the paper about this paper and its code, from readers and its authors, beside the paper and its tracing map.

Report a mismatch between the code and the paper · Report a code error (signed in)

Reproductions: reports from readers who ran the authors' code and did not get the paper's result, what they ran, with which environment, commit and data.

Report a reproduction failure (signed in)

Versions of its code: the releases of its code tied to a version of this paper (the preprint, the accepted manuscript, the version of record…), each with the tracing map versioned with it.

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