The Role of Dendritic Spines in Water Exchange Measurements With Diffusion MRI: Time-Dependent Single Diffusion Encoding MRI.
The 10 matches
- [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] § 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] § 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] § 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] § 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] § 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] § 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] § 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] § 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] § 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
- % diffusion_signal_analysis.m
- % Diffusion-signal analysis: parallel/perpendicular signal fits, exchange
- % rates, and the direction-average (Sperp=1) NEXI bias -> Figures 5, 9
- % (narrow + wide pulse via the 'pulse' switch below), plus the
- % perpendicular-signal supplementary figures. (Figure 4 -- spine<->shaft
- % exchange rates from MC particle dynamics -- is in
- % particle_dynamics_analysis.m, which it shares data with.)
- %
- % The NEXI permeability x spine-fraction bias map (Figure 10) is a separate,
- % self-contained script -- see nexi_bias_analysis.m -- since it needs none of
- % the data loaded here and mixing the two risked variable-name collisions.
- % Run from the repository root.
- clear all
- close all
- clc
- % No absolute cd: keep the repo portable for publication.
- % cd(fileparts(mfilename('fullpath')))
- addpath(genpath('src'))
- % ===================== Pulse scheme (change this one line) =====================
- % Each MATLAB script handles ONE pulse scheme per run. Set 'narrow' or 'wide':
- % the data file, gradient timings and field names below adapt automatically, so
- % the same script reproduces the corresponding figures for either dataset.
- pulse = 'wide'; % 'narrow' (delta_small = 3 ms) | 'wide' (delta_small = 15 ms)
- switch lower(pulse)
- case 'narrow'
- datafile = 'tunable_meshes_Water_narrowPulse_dt100ns.mat';
- cumulantfile = 'ADC_K_fromCumulants_narrowPulse.mat';
- smalldelta = 3; % gradient pulse duration [ms]
- delta = [5, 10, 25, 35, 55, 85, 160]; % gradient separations [ms] (incl. td = 4 ms)
- case 'wide'
- datafile = 'tunable_meshes_Water_widePulse_dt100ns.mat';
- cumulantfile = 'ADC_K_fromCumulants_widePulse.mat';
- smalldelta = 15;
- delta = [25, 35, 55, 85, 160];
- otherwise
- error('pulse must be ''narrow'' or ''wide''.')
- end
- load(fullfile('SpineMCresults', datafile)) % -> D###_d##, b, td, ...
- cumulants = load(fullfile('SpineMCresults', cumulantfile)); % ADC, K, td, spine_density
- GAMMA = 2.67513E8; % from the diffusion simulator disimpy
- smalldelta = smalldelta .* ones(size(delta)); % per-timing vector (back-compat)
- % =============================================================================
- Rh = 0.4; % effective spine head radius
- Rn = 0.125;
- Ln = 1.2;
- Rsh = 0.5;
- D = 2.0;
- De = D;
- % spine volume fraction (spines per micron)
- rho =[ 0 0.30 0.60 0.90 1.20 1.50 2.00 2.50 3.00 3.50];
- % measured volume of spines in the substrate (um^3)
- Vspine = [0 8.1003 16.1886 24.3715 32.9335 40.3329 52.1781 67.1394 80.6029 93.9811];
- % number of spines in the substrates
- Nspine = [0 30 60 90 120 150 200 250 300 350];
- % measured total volume of substrates
- Vtotal = [78.0362 87.9328 96.7014 105.5739 114.1809 122.5810 135.1033 150.7471 164.7820 178.7003];
- % spine volume fraction in the substrates
- nu = Vspine./Vtotal;
- % nu = vspine_tot./V_tot;
- options = optimset('display', 'off');
- %% ============================================================
- % Analyse Parallel Signals
- % ============================================================
- Y = [];
- Ymean = [];
- for i = 1:numel(delta)
- % Field names are D<delta>_d<smalldelta>, zero-padded (e.g. D005_d03,
- % D025_d15). This single rule covers narrow and wide pulses and the new
- % td = 4 ms (D005) timing.
- s = eval(sprintf('D%03d_d%02d', delta(i), smalldelta(1)));
- Y = [Y, s.parallel];
- Ymean = [Ymean, (s.parallel + s.perpendicular) ./ 2];
- end
- Tpar = Y;
- rr = zeros(numel(nu), 1);
- options = optimset('display','off');
- for i=1:numel(nu)
- % -------------------- Parallel signal fit --------------------
- ffit = @(p,x) modifiedKargerParallel(De, p, nu(i), x, td);
- rr(i) = initModelFitting(ffit, b, Y(i,:), 0.01, 250, 1000);
- % rr(i) = lsqcurvefit(ffit, 3.75, b, Y(i,:), 0.01, 250, options);
- end
- %% ============================================================
- % Theoretical and Estimated Exchange Rates: Spine ↔ Shaft
- % ============================================================
- % Computes theoretical first-passage times and exchange rates
- % for spine-to-shaft and shaft-to-spine diffusion, then compares
- % them to estimated values and plots both.
- % ------------------------------------------------------------
- % --- Theoretical first-passage time: Spine → Shaft ---
- Vh = (4/3) * pi .* Rh.^3;
- % Main formula
- tau_sp_sh_th = Ln .* ( ...
- 2 .* pi .* Rh.^3 + ...
- 3 .* Rn.^2 .* Ln + ...
- 2 .* pi .* Rh.^2 .* Rn .* log(Rh ./ Rn) - ...
- 2 .* Rn.^3 ) ./ (6 .* Rn.^2 .* D);
- % Conversion to rate constants
- k_sp_sh_th = 1 ./ tau_sp_sh_th;
- k_sh_sp_th = k_sp_sh_th .* nu ./ (1 - nu);
- % Total theoretical exchange rate
- k_th = k_sp_sh_th + k_sh_sp_th;
- tau_th = 1 ./ k_th;
- % --- Estimated exchange rates (from data) ---
- tau_sp_sh = rr; % Estimated spine→shaft time
- k_sp_sh = 1 ./ tau_sp_sh; % Corresponding rate
- % Estimated shaft→spine rate (depends on volume fractions)
- k_sh_sp = k_sp_sh .* nu' ./ (1 - nu');
- tau_sh_sp = 1 ./ k_sh_sp;
- % Total effective exchange rate
- k = k_sh_sp + k_sp_sh;
- tau = 1 ./ k;
- % --- Plot results ---
- figure('Color', 'w'); hold on;
- % Theoretical rates
- plot(rho(2:end), k_sp_sh_th .* ones(size(nu(2:end))), ...
- '-', 'Color', [0.15, 0.15, 0.15], 'LineWidth', 3);
- plot(rho(2:end), k_th(2:end), ...
- '-', 'Color', [0.64,0.08,0.18], 'LineWidth', 3);
- % Estimated rates
- plot(rho(2:end), smooth(k_sp_sh(2:end)), ...
- '--', 'Color', [0.15, 0.15, 0.15], 'LineWidth', 4);
- plot(rho(2:end), smooth(k(2:end)), ...
- '--', 'Color', [0.64,0.08,0.18], 'LineWidth', 4);
- % Labels and styling
- set(gca, 'FontName', 'Cambria', 'FontSize', 24);
- xlabel('Spine density [\mum^{-1}]', 'FontWeight', 'bold');
- ylabel('Exchange rate [ms^{-1}]', 'FontWeight', 'bold');
- box on; grid on;
- legend( ...
- {'k_{sp→sh} (theory)', 'k_{ex}^{DM} (theory)', ...
- 'k_{sp→sh} (simulation)', 'k_{ex}^{DM} (simulation)'}, ...
- 'Location', 'northeastoutside', 'FontSize', 24);
- % title('Exchange Rate: Spine ↔ Shaft', ...
- % 'FontWeight', 'bold', 'Interpreter', 'tex', 'Units', 'normalized', ...
- % 'Position', [0.5, 1.02, 0]);
- %% ==============================================
- % Plot parallel diffusion signals vs b
- % ==============================================
- bth = linspace(0.001, max(b), 100);
- n = numel(nu(1:2:end));
- left_margin = 0.07;
- right_margin = 0.05;
- space_between = 0.08;
- width = (1 - left_margin - right_margin - (n-1)*space_between)/n;
- height = 0.6;
- bottom = 0.15;
- figure
- colors = copper(length(delta)+1);
- for i = 1:n
- left = left_margin + (i-1)*(width + space_between);
- ax(i) = subplot(1,5,i);
- hold on
- Ytmp_exp = reshape(Y(2*i-1,:), [numel(b), numel(delta)]);
- Ytmp_th = reshape(modifiedKargerParallel(De, tau_sp_sh(2*i-1), nu(2*i-1), bth, td), [numel(bth), numel(delta)]);
- legendtxt = cell(numel(delta),1);
- for j = 1:numel(delta)
- h_exp(j) = plot(b, Ytmp_exp(:,j), 'o', 'MarkerSize', 10, ...
- 'MarkerEdgeColor','k', 'MarkerFaceColor',colors(j,:), ...
- 'LineWidth',0.5);
- plot(bth, Ytmp_th(:,j), '-', 'Color',colors(j,:), 'LineWidth',2);
- legendtxt{j} = sprintf('t_d = %.0f ms', td(j));
- end
- % Axes formatting
- set(ax(i), 'Position', [left, bottom, width, height], ...
- 'YScale', 'log', ...
- 'FontName', 'Cambria', ...
- 'FontSize', 24, ...
- 'Box', 'on', ...
- 'LineWidth', 1.5);
- grid on
- xlabel('b [ms/\mum^2]', 'FontName', 'Cambria', 'FontSize', 24)
- ylabel('S_{||}', 'FontName', 'Cambria', 'FontSize', 24)
- title(['\rho = ' num2str(rho(2*i-1)) ' \mum^{-1}'], ...
- 'Interpreter', 'tex', 'FontSize', 24)
- box on; grid on;
- axis([0 8 1e-6 1]);
- yticks([1e-6 1e-4 1e-2 1e0]);
- yticklabels({'10^{-6}','10^{-4}','10^{-2}','10^{0}'});
- end
- legend_handle = legend(h_exp, legendtxt, 'FontSize',24, ...
- 'Orientation','horizontal', 'Box','on', ...
- 'Position',[0.35 0.9 0.3 0.05]);
- %% ==============================================
- % Estimate direction-average signal assuming Sperp=1
- % (for narrow pulse scheme)
- % ==============================================
- % Empirical parallel diffusivity values [µm²/ms]
- % estimated from simulated or measured trajectories
- Dpar = [2.00410277 1.81620312 1.66844738 1.53665382 ...
- 1.42504216 1.33651321 1.22414968 1.10610485 ...
- 1.01157496 0.94218438];
- % Corresponding spine density or frequency (arbitrary units)
- % Ensure 'nu' is defined before this section, e.g.:
- % nu = linspace(0.01, 0.1, numel(Dpar));
- % (This should match your Dpar data)
- % Linear regression between Dpar and spine density
- p = polyfit(nu, Dpar, 1); % p(1) = slope, p(2) = intercept
- % Display fit coefficients
- fprintf('Linear fit: Dpar = %.4f * nu + %.4f\n', p(1), p(2));
- % Extrapolate Dpar for a continuous spine volume fraction range
- fextra = 0.25; % extracellular volume fraction
- Dpar_fit = polyval(p, nu); % extrapolated Dpar values
- nu_tot = nu .* (1-fextra);
- figure('Color', 'w'); hold on
- plot(nu_tot, Dpar, 'o', 'MarkerSize', 12, 'MarkerFaceColor', 'k', 'MarkerEdgeColor', 'k',...
- 'DisplayName', 'Simulated D_{||}', 'LineWidth',0.5)
- plot(nu_tot, Dpar_fit, '-', ...
- 'Color', [0.64,0.08,0.18],...
- 'LineWidth', 3, 'DisplayName', 'Linear fit')
- text_str = sprintf('D_{||} = %.4f * ν + %.4f', p(1), p(2));
- text(0.1, 1, text_str, ...
- 'Color', 'k', ...
- 'FontSize', 20, ...
- 'FontWeight', 'bold', ...
- 'HorizontalAlignment', 'left', ...
- 'VerticalAlignment', 'bottom')
- xlabel('Total spine volume fraction')
- ylabel('D_{||} [\mum^2/ms]')
- legend('Location', 'northeast', 'Box', 'on')
- grid on; box on
- set(gca, 'FontName', 'Cambria', 'FontSize', 24)
- % Generate Dpar values for signal simulations
- nu_th = linspace(0, max(nu), 51); % spine volume fraction [a.u.]
- Dpar = polyval(p, nu_th);
- rr_nexi = zeros(numel(nu_th),4);
- rr_nexi_corr = zeros(numel(nu_th),3);
- % Parameter bounds
- lb = [0 0 0 0]; % lower bounds
- ub = [inf 1.0 3.0 3.0]; % upper bounds
- % Number of random initializations
- Nsamples = 10;
- % Initial guesses (based on true parameters)
- r0 = [100 1 3 3] .* rand(Nsamples, 4);
- r0_corr = [100 1 3] .* rand(Nsamples, 3);
- for i = 1:numel(nu_th)
- Ytmp = zeros(numel(delta), numel(b));
- % --- Simulate signals for different diffusion times ---
- for j = 1:numel(delta)
- Ytmp(j,:) = (1-fextra) .* integral(@(x) ...
- modifiedKargerParallel(De, tau_sp_sh_th, nu_th(i), b.*x.^2, td(j)), ...
- 0, 1, 'AbsTol', 1e-14, 'ArrayValued', true)' ...
- + fextra .* exp(-1.0*b)';
- end
- % --- NEXI fit + data (diffusion-time subset depends on the pulse scheme) ---
- switch lower(pulse)
- case 'narrow' % 5 diffusion times
- ffit0 = @(p,x) [nexiSignal(x, td(1), p(1), p(3), p(4), p(4), p(2)), ...
- nexiSignal(x, td(2), p(1), p(3), p(4), p(4), p(2)), ...
- nexiSignal(x, td(3), p(1), p(3), p(4), p(4), p(2)), ...
- nexiSignal(x, td(4), p(1), p(3), p(4), p(4), p(2)), ...
- nexiSignal(x, td(5), p(1), p(3), p(4), p(4), p(2))];
- ffit0_corr = @(p,x) [nexiSignal(x, td(1), p(1), Dpar(i), p(3), p(3), p(2)), ...
- nexiSignal(x, td(2), p(1), Dpar(i), p(3), p(3), p(2)), ...
- nexiSignal(x, td(3), p(1), Dpar(i), p(3), p(3), p(2)), ...
- nexiSignal(x, td(4), p(1), Dpar(i), p(3), p(3), p(2)), ...
- nexiSignal(x, td(5), p(1), Dpar(i), p(3), p(3), p(2))];
- Yfit = [Ytmp(1,:), Ytmp(2,:), Ytmp(3,:), Ytmp(4,:), Ytmp(5,:)];
- case 'wide' % 3 diffusion times (t_d = 20, 30, 50 ms)
- ffit0 = @(p,x) [nexiSignal(x, td(1), p(1), p(3), p(4), p(4), p(2)), ...
- nexiSignal(x, td(2), p(1), p(3), p(4), p(4), p(2)), ...
- nexiSignal(x, td(3), p(1), p(3), p(4), p(4), p(2))];
- ffit0_corr = @(p,x) [nexiSignal(x, td(1), p(1), Dpar(i), p(3), p(3), p(2)), ...
- nexiSignal(x, td(2), p(1), Dpar(i), p(3), p(3), p(2)), ...
- nexiSignal(x, td(3), p(1), Dpar(i), p(3), p(3), p(2))];
- Yfit = [Ytmp(1,:), Ytmp(2,:), Ytmp(3,:)];
- otherwise
- error('pulse must be ''narrow'' or ''wide''.')
- end
- % --- Stabilize Fitting ---
- tmp = zeros(Nsamples, 4);
- resnorm = zeros(Nsamples, 1);
- tmp2 = zeros(Nsamples, 3);
- resnorm2 = zeros(Nsamples, 1);
- % Multiple random initializations
- parfor j = 1:Nsamples
- [tmp(j, :), resnorm(j)] = lsqcurvefit(ffit0, r0(j,:), b, Yfit, lb, ub, options);
- [tmp2(j,:), resnorm2(j)] = lsqcurvefit(ffit0_corr, r0_corr(j,:), b, Yfit, lb(1:end-1), ub(1:end-1), options);
- end
- % Select best fits
- [~, idx] = sort(resnorm);
- tmp = tmp(idx, :);
- r0_opt = mean(tmp(1:10, :), 1);
- [~, idx] = sort(resnorm2);
- tmp2 = tmp2(idx, :);
- r0_opt2 = mean(tmp2(1:10, :), 1);
- % Final fits with optimized starting point
- rr_nexi(i,:) = lsqcurvefit(ffit0, r0_opt, b, Yfit, lb, ub, options);
- rr_nexi_corr(i,:) = lsqcurvefit(ffit0_corr, r0_opt2, b, Yfit, lb(1:end-1), ub(1:end-1), options);
- % Progress indicator
- if mod(i, 5) == 0 || i == size(Yfit, 2)
- fprintf(' Fitted %d/%d datasets\n', i, size(Yfit, 2));
- end
- % rr_nexi(i,:) = lsqcurvefit(ffit0, r0, b, Yfit, lb, ub, options);
- % rr_nexi(i,:) = initModelFitting(ffit0, b, Yfit, [0 0 0 0], [inf 1 3 3], 1000);
- % rr_nexi_corr(i,:) = lsqcurvefit(ffit0_corr, r0_corr, b, Yfit, lb(1:end-1), ub(1:end-1), options);
- % rr_nexi_corr(i,:) = initModelFitting(ffit0_corr, b, Yfit, [0 0 0], [inf 1 3], 1000);
- end
- % Plot: t_ex^{NEXI}
- figure('Color','w'); hold on;
- plot(nu_th.*(1-fextra), smooth(rr_nexi(:,1)), 'k-', 'LineWidth', 4.0)
- plot(nu_th.*(1-fextra), smooth(rr_nexi_corr(:,1)), '-', ...
- 'Color', [0.64,0.08,0.18], ...
- 'LineWidth', 4.0)
- xlabel('Total spine volume fraction', 'FontName', 'Cambria', 'FontSize', 24)
- ylabel('Estimated t_{ex}^{NEXI} [ms^{-1}]', 'FontName', 'Cambria', 'FontSize', 24)
- ylim([0 1000])
- xlim([0 0.2])
- set(gca, 'FontName', 'Cambria', 'FontSize', 24, 'LineWidth', 1.5, 'Box', 'on')
- grid on
- legend({'D_i unconstrained', 'D_i constrained'}, 'Location', 'D_i unconstrained', ...
- 'Orientation', 'horizontal', 'FontSize', 22, 'Box', 'on')
- % Plot: k_ex^{NEXI}
- figure('Color','w'); hold on;
- plot(nu_th.*(1-fextra), 1./smooth(rr_nexi(:,1)), 'k-', 'LineWidth', 4.0)
- plot(nu_th.*(1-fextra), smooth(1./rr_nexi_corr(:,1)), '-', ...
- 'Color', [0.64,0.08,0.18],...
- 'LineWidth', 4.0)
- xlabel('Total spine volume fraction', 'FontName', 'Cambria', 'FontSize', 24)
- ylabel('Estimated k_{ex}^{NEXI} [ms^{-1}]', 'FontName', 'Cambria', 'FontSize', 24)
- xlim([0 0.2])
- ylim([0 0.1])
- set(gca, 'FontName', 'Cambria', 'FontSize', 24, 'LineWidth', 1.5, 'Box', 'on')
- grid on
- legend({'D_i unconstrained', 'D_i constrained'}, 'Location', 'D_i unconstrained', ...
- 'Orientation', 'horizontal', 'FontSize', 22, 'Box', 'on')
- %% ===============================================================
- % Analyse perpendicular signals
- % ===============================================================
- Y = [];
- % --- Collect perpendicular signals (field name adapts to the pulse scheme) ---
- for i = 1:numel(delta)
- s = eval(sprintf('D%03d_d%02d', delta(i), smalldelta(1)));
- Y = [Y, s.perpendicular];
- end
- Tperp = Y;
- % --- Fit monoexponential model to perpendicular signals ---
- monoRR = zeros(numel(nu), numel(delta));
- kurtRR_perp = zeros(numel(nu), numel(delta), 2);
- for i = 1:numel(nu)
- for j = 1:numel(delta)
- monoexpFit = @(p, x) exp(-p(1) .* x);
- p0 = 2;
- monoRR(i, j, :) = lsqcurvefit( ...
- monoexpFit, p0, ...
- b(1:2), ...
- Y(i, (j-1)*numel(b) + (1:2)), ...
- 0, 2);
- end
- end
- % --- Plot ADC_perp vs diffusion time (t_d) ---
- figure('Color', 'w'); hold on;
- colors = bone(numel(nu(1:2:end)) + 2);
- legendtxt = cell(numel(nu(1:2:end)), 1);
- h = gobjects(numel(nu(1:2:end)), 1); % preallocate for legend handles
- for j = 1:numel(nu(1:2:end))
- % Extract fitted ADC_perp values
- y = squeeze(monoRR(j, :));
- % Plot fitted values (lines + scatter)
- h(j) = plot(td, y, '-', ...
- 'LineWidth', 4, ...
- 'Color', colors(j,:), ...
- 'DisplayName', sprintf('\\rho = %.2f \\mum^{-1}', rho(2*(j-1)+1)));
- plot(td, y, 'o', ...
- 'MarkerSize', 10, ...
- 'MarkerEdgeColor', 'k', ...
- 'MarkerFaceColor', colors(j,:), ...
- 'LineWidth', 1.2);
- end
- % --- Axes and labels formatting ---
- xlabel('t_d [ms]');
- ylabel('ADC_{\perp}(t) [\mum^2/ms]');
- set(gca, ...
- 'FontName', 'Cambria', ...
- 'FontSize', 24, ...
- 'LineWidth', 1.5, ...
- 'Box', 'on');
- grid on; box on;
- % --- Common legend (top-centered) ---
- legend_handle = legend(h, 'Orientation', 'vertical', ...
- 'FontSize', 24, 'Box', 'on', 'Location', 'northeast');
- set(legend_handle, 'Units', 'normalized');
- % legend_pos = get(legend_handle, 'Position');
- % legend_pos(2) = 0.92; % push slightly upward
- % legend_pos(1) = 0.5 - legend_pos(3)/2; % center horizontally
- % set(legend_handle, 'Position', legend_pos);
- % ylim([0 2.5]); % optional range for ADC
- xlim([min(td) max(td)]);
- %% ==============================================
- % Plot D_perp(t) vs 1/t_d for all nu with linear fits
- % ==============================================
- figure('Color','w'); hold on;
- colors = bone(numel(nu) + 2);
- legendtxt = cell(numel(nu),1);
- h = gobjects(numel(nu),1);
- Reff = zeros(numel(nu),1);
- for j = 1:numel(nu)
- % Extract ADC_perp(t) for this rho
- Dperp_t = squeeze(monoRR(j,3:end)); % Estimated diffusivity
- tvals = td(3:end); % Diffusion times [ms]
- inv_t = 1 ./ tvals; % Inverse diffusion time [ms^-1]
- % --- Linear regression: D = a*(1/t) ---
- p = inv_t(:)\Dperp_t(:);
- Dfit = p.*inv_t;
- % Effective radius from slope: a = R^2 / 4
- Reff(j) = sqrt(4 * p(1));
- % --- Plot experimental data ---
- h(j) = plot(inv_t, Dperp_t, 'o', ...
- 'MarkerSize', 10, ...
- 'MarkerEdgeColor', 'k', ...
- 'MarkerFaceColor', colors(j,:), ...
- 'LineWidth', 1.2, ...
- 'DisplayName', sprintf('\\rho = %.2f \\mum^{-1}', rho(j)));
- % --- Plot fitted line ---
- plot(inv_t, Dfit, '-', ...
- 'Color', colors(j,:), ...
- 'LineWidth', 3);
- end
- % --- Axes formatting ---
- xlabel('1/t_d [ms^{-1}]', 'FontName', 'Cambria', 'FontSize', 28);
- ylabel('D_{\perp}(t) [\mum^2/ms]', 'FontName', 'Cambria', 'FontSize', 28);
- set(gca, ...
- 'FontName', 'Cambria', ...
- 'FontSize', 24, ...
- 'LineWidth', 1.5, ...
- 'Box', 'on');
- grid on; box on;
- % --- Common legend (top-centered) ---
- legend_handle = legend(h, 'Orientation', 'horizontal', ...
- 'NumColumns',2,'FontSize', 24, 'Box', 'on', 'Location', 'northwest');
- set(legend_handle, 'Units', 'normalized');
- % legend_pos = get(legend_handle, 'Position');
- % legend_pos(2) = 0.92; % slightly higher
- % legend_pos(1) = 0.5 - legend_pos(3)/2; % center align
- % set(legend_handle, 'Position', legend_pos);
- % --- Axis limits (optional) ---
- % ylim([0 2.5]);
- % xlim([min(inv_t) max(inv_t)]);
- % --- Display fitted effective radii ---
- disp(table(rho(:), Reff(:), 'VariableNames', {'rho_um_inv', 'Reff_um'}));
- %% ============================================================
- % Fit perpendicular signal using Neuman model
- % ============================================================
- figure('Color', 'w'); hold on; box on; grid on;
- % Neuman cylinder perpendicular signal (src/Neumann_perp.m), stacked over
- % gradient separations: p = [D0, R] (Neumann_perp's own convention), one
- % block of b-values per gradient separation listed in 'delta'.
- ffit_neuman = @(p, x) cell2mat(arrayfun(@(gradSep) ...
- neumanPerpendicular([p(1), p(2)], x, smalldelta(1), gradSep).', ...
- delta, 'UniformOutput', false));
- % Preallocate results: columns = [D0, R]
- rr_neuman = zeros(numel(nu), 2);
- % Define color gradient (blueish)
- colors = [zeros(size(nu')) ...
- 1 - (numel(nu) - (1:numel(nu))') ./ numel(nu) ...
- 1 - (numel(nu) - (1:numel(nu))') ./ numel(nu)] .* 0.8;
- % Fit and plot for each ν value
- for i = 1:numel(nu)
- Yfit = Y(i,:);
- % Fit parameters [D0, R]
- rr_neuman(i,:) = lsqcurvefit(ffit_neuman, [D, Rsh], b, Yfit, [0 0], [4 10], options);
- % Experimental data
- plot(Y(i,:), '-', ...
- 'MarkerEdgeColor', colors(i,:), ...
- 'MarkerFaceColor', colors(i,:), ...
- 'MarkerSize', 8, ...
- 'LineWidth', 3); hold on;
- % Fitted curve
- plot(ffit_neuman(rr_neuman(i,:), b), '-', ...
- 'Color', colors(i,:), ...
- 'LineWidth', 2.0);
- % Axes labels
- ylabel('S_{\perp}', 'FontName', 'Cambria', 'FontSize', 20)
- xlabel('Measurements', 'FontName', 'Cambria', 'FontSize', 20)
- end
- set(gca, 'FontName', 'Cambria', 'FontSize', 20)
- title('Neuman Model Fits for Each \nu', 'FontSize', 22)
- legend(arrayfun(@(x) sprintf('\\nu = %.2f', x), nu, 'UniformOutput', false), ...
- 'Location', 'northeastoutside', 'Box', 'off')
- %% ============================================================
- % Plot estimated effective fiber diameter
- % ============================================================
- figure('Color', 'w'); hold on; box on; grid on;
- % Reference expected geometric diameter
- plot(rho, ones(size(rho)) .* (Rsh + Ln + 2 * Rh), 'k-', 'LineWidth', 3.0)
- % Estimated effective radius (fitted) -- column 2 is R, see ffit_neuman above
- plot(rho, rr_neuman(:,2), 'k--', 'LineWidth', 3.0)
- plot(rho, Reff(:,1), 'r:', 'LineWidth', 3.0)
- % Formatting
- xlabel('Spine density [\mum^{-1}]', 'FontName', 'Cambria', 'FontSize', 24)
- ylabel('Estimated effective fiber diameter [\mum]', 'FontName', 'Cambria', 'FontSize', 24)
- set(gca, 'FontName', 'Cambria', 'FontSize', 24)
- legend({'2*R_{head}+L_n+R_{shaft}','Neuman R_{eff}', 'R^2/4t'}, ...
- 'Location', 'southeast', 'Box', 'off')
- %% ============================================================
- % Plot perpendicular signal vs b
- % ============================================================
- bth = linspace(0.001, max(b), 100);
- n = numel(nu(1:2:end)); % number of subplots
- left_margin = 0.05;
- right_margin = 0.05;
- space_between = 0.06;
- width = (1 - left_margin - right_margin - (n-1)*space_between) / n;
- height = 0.6;
- bottom = 0.15;
- figure('Color', 'w');
- hold on
- colors = copper(numel(delta));
- legendtxt = cell(numel(delta), 1);
- h_all = gobjects(1, numel(delta)); % preallocate graphic handles
- for i = 1:n
- left = left_margin + (i-1)*(width + space_between);
- ax(i) = subplot(1, n, i);
- hold on
- % Extract data
- Ytmp_exp = reshape(Y(2*i-1,:), [numel(b), numel(delta)]);
- Ytmp_th = reshape(ffit_neuman(rr_neuman(2*i-1,:), bth), [numel(bth), numel(delta)]);
- % Plot experimental and theoretical curves
- for j = 1:numel(delta)
- % Experimental data (scatter)
- h = plot(b, Ytmp_exp(:,j), 'o', ...
- 'MarkerSize', 12, ...
- 'MarkerEdgeColor', 'k', ...
- 'MarkerFaceColor', colors(j,:), ...
- 'LineWidth', .5);
- % plot(b, Ytmp_exp(:,j), '-', ...
- % 'Color', colors(j,:), ...
- % 'LineWidth', 2.0);
- % % Theoretical model (line)
- plot(bth, Ytmp_th(:,j), '-', ...
- 'Color', colors(j,:), ...
- 'LineWidth', 2.0);
- % Store handles and labels for legend (only from first subplot)
- if i == 1
- h_all(j) = h;
- legendtxt{j} = ['t_d = ' num2str(td(j)) ' ms'];
- end
- end
- % Axes formatting
- set(ax(i), 'Position', [left, bottom, width, height], ...
- 'YScale', 'log', ...
- 'FontName', 'Cambria', ...
- 'FontSize', 24, ...
- 'Box', 'on', ...
- 'LineWidth', 1.5);
- grid on
- xlabel('b [ms/\mum^2]', 'FontName', 'Cambria', 'FontSize', 24)
- ylabel('S_{\perp}', 'FontName', 'Cambria', 'FontSize', 24)
- title(['\rho = ' num2str(rho(2*i-1)) ' \mum^{-1}'], ...
- 'Interpreter', 'tex', 'FontSize', 24)
- axis([0 8 0.6 1])
- end
- % Common legend (top-centered, using stored handles)
- legend_handle = legend(h_all, legendtxt, ...
- 'Orientation', 'horizontal', ...
- 'FontSize', 24, ...
- 'Box', 'on', ...
- 'Location', 'northoutside');
- % Adjust legend position slightly higher for visibility
- set(legend_handle, 'Units', 'normalized');
- legend_pos = get(legend_handle, 'Position');
- legend_pos(2) = 0.9; % Move legend upward
- legend_pos(1) = 0.5 - legend_pos(3)/2; % Center align horizontally
- set(legend_handle, 'Position', legend_pos);
diffusion_signal_analysis.m at commit 8ac692e, no license · at the source
Overview
- Cardiff University Brain Research Imaging Centre (CUBRIC) Cardiff University Cardiff UK
- School of Computer Science and Informatics Cardiff University Cardiff UK
- Medical Radiation Physics, Lund Lund University Lund Sweden
- Department of Clinical Sciences Lund, Radiology Lund University Lund Sweden
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/
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
8ac692edcd01a7a641d734c12fe3483660728aa0, 13 September 2026Availability: 1 check, the latest on 1 October 2026: the link answers
- 1 October 2026: the link answers
27 files
- coarse_grained_nexi_anal
ysis.m , MATLAB, 608 lines, 2 matches - diffusion_signal_analysi
s.m , MATLAB, 692 lines, 2 matches - highb_cumulant_analysis.
m , MATLAB, 702 lines, 2 matches - main_analysis.m, MATLAB, 971 lines
- main_analysis_ub.m, MATLAB, 713 lines, 1 match
- make_all_figures.m, MATLAB, 73 lines
- nexi_bias_analysis.m, MATLAB, 286 lines, 2 matches
- particle_dynamics_analys
is.m , MATLAB, 242 lines, 1 match - permBarriers1D/
analysis.py , Python, 495 lines - simulate_spine_and_excha
nge.m , MATLAB, 599 lines - src/
biexpSignal.m , MATLAB, 10 lines - src/
coarseGrainedKargerSigna , MATLAB, 52 linesl.m - src/
extendedKargerSignal.m , MATLAB, 38 lines - src/
initModelFitting.m , MATLAB, 59 lines - src/
kargerSignal.m , MATLAB, 28 lines - src/
kargerSignalDirAvg.m , MATLAB, 19 lines - src/
modifiedKargerDirAvg.m , MATLAB, 51 lines - src/
modifiedKargerParallel.m , MATLAB, 28 lines - src/
modifiedKargerPerpendicu , MATLAB, 29 lineslar.m - src/
murdayCottsSphere.m , MATLAB, 57 lines - src/
neumanParallel.m , MATLAB, 27 lines - src/
neumanPerpAttenuation.m , MATLAB, 7 lines - src/
neumanPerpendicular.m , MATLAB, 29 lines - src/
nexiSignal.m , MATLAB, 18 lines - src/
nexiSignalOde.m , MATLAB, 23 lines - src/
vanGelderenCylinder.m , MATLAB, 35 lines - README.md, Text, 162 lines
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://
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://
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/
url = {https://
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/
VL - 39
IS - 10
SP - e70382
SN - 0952-3480
PB - Wiley
DO - 10.1002/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1002/
"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":
"volume": "39",
"issue": "10",
"page": "e70382",
"DOI": "10.1002/
"PMID": "42727943",
"PMCID": "PMC13569403",
"ISSN": "0952-3480",
"publisher": "Wiley",
"URL": "https://
"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 reportsIn 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 lettersIn 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 biologyIn 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 medicineIn 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 substratesJournal: 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.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 1 repository of the authors' code, each at its verified commit and with its license, 26 scripts, and 10 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:fb36c589062983d2…
Add the badge to the code's README
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 -->
[](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:endHTML
<!-- 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.
