Axon Diameter Mapping in the Living Human Brain with Ultra-High-Gradient Diffusion MRI at 500 mT/m Gradient Strength.
The 5 matches · 1 of them tie a paragraph to a whole file, not to given lines: a weak match, whose lines are not tinted
- [1] § Methods › AxCaliber‐SMT Model Fitting › Forward Model and Assumptions ↔ AxCaliberSMT/gpuAxCaliberSMT.m, lines 81–127 · score 0.83 · AxCaliber, SMT model, axial diffusivity, CSF diffusivity, intrinsic diffusivity, extra cellular
- [2] § Methods › AxCaliber‐SMT Model Fitting › Markov Chain Monte Carlo With Ensemble Sampler With Affine Invariance ↔ utils/mcmc.m, lines 385–442 · score 0.64 · affine invariant ensemble, sampler, Goodman, Weare, MCMC, dimensional
- [3] § Methods › AxCaliber‐SMT Model Fitting › Markov Chain Monte Carlo With Ensemble Sampler With Affine Invariance ↔ utils/mcmc.m, lines 385–442 · score 0.57 · stretch move, walkers, thinned, Sampler, Affine, Ensemble
- [4] § Methods › MRI Acquisition ↔ helpers/diffusion_parameters_exporter.py, the whole file · a weak match · score 0.53 · encoding directions, pulse width, 30 ms, volumes, diffusion
- [5] § Methods › Noise Propagation From Synthetic Diffusion Signal ↔ MCRMWI/gpuMCRMWI.m, lines 566–714 · score 0.51 · intra axonal, volume fraction, forward model, component, extracellular, water
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
MATLAB · 878 lines · 48 KB · GPL-3.0 · 2 matches
- classdef mcmc < handle
- % Kwok-Shing Chan @ MGH
- % [email hidden]
- %
- % This is the class of all MCMC related functions
- %
- % Date created: 13 June 2024
- % Date modified: 7 August 2024
- % Date modified: 23 August 2024
- % Date modified: 5 October 2024
- % Date modified: 4 June 2026 (update affine-invariant method with and without global parameters)
- %
- properties (GetAccess = public, SetAccess = protected)
- end
- methods
- function out = optimisation(this, data, mask, weights, pars0, fitting, FWDfunc, varargin)
- % Input
- % ----------
- % data : N-D measurement data, First 3 dims reserve for spatial info
- % mask : M-D signal mask (M=[1,3])
- % weights : N-D weights for optimisaiton, same dim as 'data'
- % pars0 : Structure variable containing all parameters to be estimated
- % fitting : Structure variable containing all fitting algorithm setting
- % .modelParams : 1xM cell variable, name of the model parameters, e.g. {'S0','R2star','noise'};
- % .lb : 1xM numeric variable, fitting lower bound, same order as field 'modelParams', e.g. [0.5, 0, 0.001];
- % .ub : 1xM numeric variable, fitting upper bound, same order as field 'modelParams', e.g. [2, 1, 0.1];
- % .algorithm : MCMC algorithm, 'MH'|'GW'
- % .iteration : # MCMC iterations
- % .thinning : sampling interval between iterations
- % .burnin : iterations at the beginning to be discarded, if burnin>1, then the exact number will be used; if 0<burnin<1 then actual burnin = iteration*burnin
- % .repetition : # repetition of MCMC proposal
- % .xStepSize : step size of model parameter in MCMC proposal, same size and order as 'modelParams' ('MH' only)
- % .StepSize : step size for 'GW' in MCMC proposal ('GW' only)
- % .Nwalker : # random walkers ('GW' only)
- % FWDfunc : function handle of forward model
- % varargin : contains additional input requires for FWDfunc
- %
- fitting = this.check_set_default_basic(fitting);
- % Step 0: display basic messages
- this.display_basic_algorithm_parameters(fitting);
- % mask data to reduce memory load
- mask_idx = find(mask>0);
- if ~ismatrix(data); data = utils.reshape_ND2GD(data, mask_idx); else; data = data(:,mask_idx); end
- if ~ismatrix(weights); weights = utils.reshape_ND2GD(weights, mask_idx); elseif ~isempty(weights); weights = weights(:,mask_idx); end
- % data = utils.reshape_ND2GD(data,mask);
- % if ~isempty(weights); weights = utils.reshape_ND2GD(weights,mask); else; weights = ones(size(data), 'like', data); end
- pars0 = utils.reshape_ND2GD_struct(pars0,mask);
- isGlobal = false;
- for k = 1:numel(fitting.modelParams)
- if k == 1
- N = numel(pars0.(fitting.modelParams{k}));
- else
- if N ~= numel(pars0.(fitting.modelParams{k})) && numel(pars0.(fitting.modelParams{k})) == 1
- isGlobal = true;
- break;
- end
- end
- end
- % MCMC
- if strcmpi(fitting.algorithm,'mh')
- xPosterior = this.metropolis_hastings(data, pars0, weights, fitting, FWDfunc ,varargin{:});
- else
- if ~isGlobal
- xPosterior = this.goodman_weare(data, pars0, weights, fitting, FWDfunc ,varargin{:});
- else
- xPosterior = this.goodman_weare_wglobal_constant(data, pars0, weights, fitting, FWDfunc ,varargin{:});
- end
- end
- % finish up
- out = this.res2out(xPosterior,fitting,mask);
- end
- function xPosterior = metropolis_hastings(this,y,x0,weights,fitting,FWDfunc,varargin)
- % Input
- % ------
- % y : measurements, [Nmeas,Nvoxels]
- % x0 : structure array, starting points, N fields, each field 1xNvoxel
- % weights : weighting for non-linear least square fitting, same dimension as y
- % fitting : Structure variable containing all fitting algorithm setting
- % .modelParams : 1xM cell variable, name of the model parameters, e.g. {'S0','R2star','noise'};
- % .lb : 1xM numeric variable, fitting lower bound, same order as field 'modelParams', e.g. [0.5, 0, 0.001];
- % .ub : 1xM numeric variable, fitting upper bound, same order as field 'modelParams', e.g. [2, 1, 0.1];
- % .iteration : # MCMC iterations
- % .thinning : sampling interval between iterations
- % .burnin : iterations at the beginning to be discarded, if burnin>1, then the exact number will be used; if 0<burnin<1 then actual burnin = iteration*burnin
- % .repetition : # repetition of MCMC proposal
- % .xStepSize : step size of model parameter in MCMC proposal, same size and order as 'modelParams' ('MH' only)
- % FWDfunc : function handle for forward signal model
- % varargin : other input required for @FWDfunc
- %
- fitting = this.check_set_default_basic(fitting);
- if isempty(weights); weights = ones(size(y), 'like', y); end
- % Nm: # measurements; Nv: # voxels
- [Nm, Nv] = size(y);
- % Nvar: # estimation parameters
- Nvar = numel(fitting.modelParams);
- Nburnin = this.get_number_burnin(fitting);
- % Ns: # samples in posterior distribution
- Ns = numel(Nburnin+1:fitting.thinning:fitting.iteration); %floor( (fitting.iteration - floor(fitting.iteration*fitting.burnin)) / fitting.thinning );
- % convert data into single datatype for better performance and out themn into GPU
- y = gpuArray( single(y) );
- weights = gpuArray( single(weights) );
- for km = 1:Nvar; x0.(fitting.modelParams{km}) = gpuArray(single( x0.(fitting.modelParams{km}) ));end
- xStepsize = gpuArray(single(fitting.xStepSize(:)));
- % setup boundary variables
- lb = gpuArray( single(repmat(fitting.lb(:),1,Nv)));
- ub = gpuArray( single(repmat(fitting.ub(:),1,Nv)));
- % initialize array to staore all the samples
- xPosterior = zeros(Nvar, Nv, Ns, fitting.repetition,'single');
- % compute likelihood at starting points
- % logP is converted into external function for specific CUDA kernel
- % logP = @(X, Y) -sum( (this.FWD(X(1:4, :), model)-Y).^2, 1 )./(2*X(5,:).^2) + Nm/2*log(1./X(5,:).^2);
- xCurr = this.struct2array(x0,fitting.modelParams); % extract parameter structure to numeric array for faster computation
- xCurr = max(xCurr,lb); xCurr = min(xCurr,ub); % set boundary
- x0 = this.array2struct(xCurr,fitting.modelParams); % convert array back to structure for FWD function
- logP0 = arrayfun(@logP_Gaussian, sum( weights.* (FWDfunc(x0,varargin{:})-y).^2, 1 ), x0.noise, Nm);
- disp('-------------------------');
- disp('MCMC optimisation process');
- disp('-------------------------');
- % loop (multiple) proposal (same start)
- for ii = 1:fitting.repetition
- fprintf('Repetition #%i/%i \n',ii,fitting.repetition)
- % reset start point
- logPCurr = logP0;
- xCurr = this.struct2array(x0,fitting.modelParams);
- counter = 0; start = tic;
- for k = 1:fitting.iteration
- % 1. make a proposal with normal distribution
- % proposal is generated during iteration
- xProposed = xCurr + xStepsize.*randn(size(xCurr),'like',xCurr);
- % find proposal that is out of bound for exclusion
- isOutofbound = max(or(xProposed<lb, xProposed>ub),[],1);
- % replace out of bound by boundary values to avoid error when compting probability
- xProposed = max(xProposed,lb); xProposed = min(xProposed,ub);
- % convert the proposal into structure array for FWD function
- xProposed_struct = this.array2struct(xProposed,fitting.modelParams);
- % 2. Metropolis sampling
- % If the probability ratio of new to old > threshold, we take the new solution.
- % 2.1 proposal probability
- logPProposed = arrayfun(@logP_Gaussian, sum( weights.* (FWDfunc(xProposed_struct, varargin{:})-y).^2, 1 ), xProposed_struct.noise, Nm);
- % 2.2 Compute acceptance ratio based on new/old probability
- acceptanceRatio = min(exp(logPProposed-logPCurr), 1);
- isAccepted = acceptanceRatio > rand(1,Nv,'like',logPProposed);
- isAccepted(isOutofbound)= 0; % reject out of bound proposal
- % 2.3 update parameters if accepted
- logPCurr(isAccepted) = logPProposed(isAccepted);
- xCurr(:,isAccepted) = xProposed(:,isAccepted);
- % 3. Maintain the independence between iterations
- % 3.1 discard the first burnin*100% iterations
- % 3.2 keep an iteration every N iterations
- if ( k > Nburnin ) && mod(k-Nburnin+1, fitting.thinning) == 0 %( mod(k, fitting.thinning)==1 )
- counter = counter+1;
- xPosterior(:,:,counter,ii) = gather(xCurr);
- end
- % display message at 1000 iteration and every 10000 iteration
- if mod(k,fitting.iteration/50) == 0 || k == min(1e3, fitting.iteration/100)
- ET = duration(0,0,toc(start),'Format','hh:mm:ss');
- ERT = ET / (k/fitting.iteration) - ET;
- fprintf('Iteration #%6d, Elapsed time (hh:mm:ss):%s, Estimated remaining time (hh:mm:ss):%s \n',k,string(ET),string(ERT));
- end
- end
- end
- % convert final posterior distribution into structure
- xPosterior = this.array2struct(xPosterior,fitting.modelParams);
- for kvar = 1:Nvar; xPosterior.(fitting.modelParams{kvar}) = shiftdim(xPosterior.(fitting.modelParams{kvar}),1); end
- disp('The Metroplis-Hastings MCMC sampling is completed.')
- end
- function xPosterior = goodman_weare(this,y,x0,weights,fitting,modelFWD,varargin)
- % Input
- % ----------
- % y : measurements, [Nmeas,Nvoxels]
- % x0 : structure array, starting points, N fields, each field 1xNvoxel
- % weights : weighting for non-linear least square fitting, same dimension as y
- % pars0 : Structure variable containing all parameters to be estimated
- % fitting : Structure variable containing all fitting algorithm setting
- % .modelParams : 1xM cell variable, name of the model parameters, e.g. {'S0','R2star','noise'};
- % .lb : 1xM numeric variable, fitting lower bound, same order as field 'modelParams', e.g. [0.5, 0, 0.001];
- % .ub : 1xM numeric variable, fitting upper bound, same order as field 'modelParams', e.g. [2, 1, 0.1];
- % .iteration : # MCMC iterations
- % .thinning : sampling interval between iterations
- % .burnin : iterations at the beginning to be discarded, if burnin>1, then the exact number will be used; if 0<burnin<1 then actual burnin = iteration*burnin
- % .repetition : # repetition of MCMC proposal
- % .StepSize : step size for 'GW' in MCMC proposal ('GW' only)
- % .Nwalker : # random walkers ('GW' only)
- % .Ensembleupdate : (optional) ensemble update scheme:
- % 'simultaneous' - original behaviour (DEFAULT, backward compatible):
- % all walkers proposed/updated in one pass using a
- % single derangement as partners.
- % 'redblack' - affine-invariance-correct parallel update
- % (Foreman-Mackey et al. 2013): split the ensemble
- % into two halves and update each half using the
- % other (frozen) half as anchors.
- % FWDfunc : function handle of forward model
- % varargin : contains additional input requires for FWDfunc
- %
- % ENSEMBLE SAMPLERS WITH AFFINE INVARIANCE (2010) JONATHAN GOODMAN AND JONATHAN WEARE
- % Other references:
- % emcee: The MCMC Hammer (2013) https://arxiv.org/pdf/1202.3665
- % https://github.com/grinsted/gwmcmc/tree/master
- %
- fitting = this.check_set_default_basic(fitting);
- if isempty(weights); weights = ones(size(y), 'like', y); end
- % Nm: # measurements; Nv: # voxels
- [Nm, Nv] = size(y);
- % Nvar: # estimation parameters
- Nvar = numel(fitting.modelParams);
- Nburnin = this.get_number_burnin(fitting);
- % Ns: # samples in posterior distribution
- Ns = numel(Nburnin+1:fitting.thinning:fitting.iteration);
- Nwalker = fitting.Nwalker;
- StepSize = fitting.StepSize;
- % red-black update scheme
- useRedBlack = strcmpi(fitting.Ensembleupdate,'redblack');
- if useRedBlack
- if Nwalker < 2
- error('goodman_weare:Nwalker', ...
- 'redblack update needs Nwalker >= 2 (use even, >= 2*Nvar in practice).');
- end
- if mod(Nwalker,2) ~= 0
- warning('goodman_weare:Nwalker', ...
- 'Nwalker is odd; redblack halves will be unequal. Even Nwalker is conventional.');
- end
- h = floor(Nwalker/2);
- halfIdx = {1:h, h+1:Nwalker}; % {S0, S1}: complementary anchor sets
- end
- fprintf('Ensemble update scheme: %s\n', fitting.Ensembleupdate);
- % convert data into single datatype for better performance
- y = gpuArray( single(y) );
- weights = gpuArray( single(weights) );
- for km = 1:Nvar; x0.(fitting.modelParams{km}) = gpuArray(single( x0.(fitting.modelParams{km}) ));end
- % setup boundary variables
- lb = gpuArray( single(repmat(fitting.lb(:),1,Nv,Nwalker)));
- ub = gpuArray( single(repmat(fitting.ub(:),1,Nv,Nwalker)));
- % set up weight
- weights = repmat(weights,1,1,Nwalker);
- % initialize array to staore all the samples
- xPosterior = zeros(Nvar, Nv, Nwalker, Ns, fitting.repetition,'single');
- % initiate an ensemble of walkers around the starting position (0.1% full range) with Gaussian distribution
- % 1st: Nvar;2nd: Nv; 3rd: Nwalker
- xCurr = this.struct2array(x0,fitting.modelParams); % extract parameter structure to numeric array for faster computation
- xCurr = xCurr + (ub-lb)*fitting.startRange.*randn(size(ub)); % initiate starting position for all walkers
- xCurr = max(xCurr,lb); xCurr = min(xCurr,ub); % set boundary
- x0 = this.array2struct(xCurr,fitting.modelParams); % convert array back to structure for FWD function
- % compute likelihood at starting points
- logP0 = arrayfun(@logP_Gaussian, sum( weights.* (modelFWD(x0, varargin{:})-y).^2, 1 ), x0.noise, Nm);
- disp('-------------------------');
- disp('MCMC optimisation process');
- disp('-------------------------');
- for ii = 1:fitting.repetition
- fprintf('Repetition #%i/%i \n',ii,fitting.repetition)
- logPCurr= logP0;
- xCurr = this.struct2array(x0,fitting.modelParams);
- counter = 0; start = tic;
- for k = 1:fitting.iteration
- if ~useRedBlack
- % =========== LEGACY: simultaneous single-derangement update ===========
- % (identical to the original implementation; preserved for reproducibility)
- % 1.1 find a unique partner for each walker
- % 1. make a proposal with normal distribution
- % 1.1. find a unique partner for a walker k
- partner = this.find_partner(Nwalker);
- % 1.2. stretch move
- zz = ((StepSize-1)*rand(size(logP0),'like',xCurr) + 1).^2 / StepSize;
- xProposed = xCurr(:,:,partner) + (xCurr - xCurr(:,:,partner)).*zz;
- % find proposal that is out of bound for exclusion
- isOOB = max(or(xProposed<lb, xProposed>ub),[],1);
- % replace boundary values so it does not give error when compting probability
- xProposed = max(xProposed,lb); xProposed = min(xProposed,ub);
- % convert the proposal into structure array for FWD function
- xProposed_struct = this.array2struct(xProposed,fitting.modelParams);
- % 2. Metropolis sampling
- % If the probability ratio of new to old > threshold, we take the new solution.
- % 2.1 proposal probability
- logPProposed = arrayfun(@logP_Gaussian, sum( weights.* (modelFWD(xProposed_struct, varargin{:})-y).^2, 1 ), xProposed_struct.noise, Nm);
- % 2.2 Compute acceptance ratio based on z^(Nd-1)*new/old probability
- acceptanceRatio = min(zz.^(Nvar-1).*exp(logPProposed-logPCurr), 1);
- isAccepted = acceptanceRatio > rand(1,Nv,Nwalker,'like',xCurr);
- isAccepted(isOOB) = 0; % reject out of bound proposal
- % 2.3 update parameters
- logPCurr(isAccepted) = logPProposed(isAccepted);
- xCurr(:,isAccepted) = xProposed(:,isAccepted);
- else
- % =========== RED-BLACK: two complementary sub-steps per sweep ===========
- for s = 1:2
- active = halfIdx{s}; % walkers moved this sub-step
- frozen = halfIdx{3-s}; % anchors, held FIXED this sub-step
- na = numel(active);
- % stretch proposal: each active walker anchored on a RANDOM frozen
- % walker (uniform, WITH replacement -- textbook GW partner draw)
- pidx = frozen(randi(numel(frozen),1,na));
- xAnch = xCurr(:,:,pidx); % [Nvar,Nv,na] fixed
- xAct = xCurr(:,:,active); % [Nvar,Nv,na]
- zz = ((StepSize-1)*rand(1,Nv,na,'like',xCurr) + 1).^2 / StepSize;
- xProp = xAnch + (xAct - xAnch).*zz;
- lb_a = lb(:,:,active); ub_a = ub(:,:,active);
- isOOB = max(or(xProp<lb_a, xProp>ub_a),[],1);
- xProp = max(xProp,lb_a); xProp = min(xProp,ub_a);
- % proposal likelihood on the active half only
- % (two half-width evals/iter ~= one full eval: no cost regression)
- xProp_s = this.array2struct(xProp,fitting.modelParams);
- logPProp = arrayfun(@logP_Gaussian, ...
- sum( weights(:,:,active).*(modelFWD(xProp_s,varargin{:})-y).^2, 1 ), ...
- xProp_s.noise, Nm);
- % acceptance z^(Nvar-1) * pi(new)/pi(old)
- logPAct = logPCurr(:,:,active);
- aR = min(zz.^(Nvar-1).*exp(logPProp - logPAct), 1);
- acc = aR > rand(1,Nv,na,'like',xCurr);
- acc(isOOB) = 0;
- % scatter accepted moves back into the active block
- xAct(:,acc) = xProp(:,acc);
- logPAct(acc) = logPProp(acc);
- xCurr(:,:,active) = xAct;
- logPCurr(:,:,active) = logPAct;
- end
- end
- % 3. Maintain the independence between iterations
- % 3.1 discard the first burnin*100% iterations
- % 3.2 keep an iteration every N iterations
- if ( k > Nburnin ) && mod(k-Nburnin+1, fitting.thinning) == 0
- counter = counter+1;
- xPosterior(:,:,:,counter,ii) = gather(xCurr);
- end
- % display message at 1000 ietration and every 2000 iterations
- if mod(k,fitting.iteration/50) == 0 || k == min(1e2, fitting.iteration/100)
- ET = duration(0,0,toc(start),'Format','hh:mm:ss');
- ERT = ET / (k/fitting.iteration) - ET;
- fprintf('Iteration #%6d, Elapsed time (hh:mm:ss):%s, Estimated remaining time (hh:mm:ss):%s \n',k,string(ET),string(ERT));
- end
- end
- end
- % convert final posterior distribution into structure
- xPosterior = this.array2struct(xPosterior,fitting.modelParams);
- for kvar = 1:Nvar; xPosterior.(fitting.modelParams{kvar}) = shiftdim(xPosterior.(fitting.modelParams{kvar}),1); end
- disp('The affine-invariant ensemble MCMC sampling is completed.')
- end
- function xPosterior = goodman_weare_wglobal_constant(this,y,x0,weights,fitting,modelFWD,varargin)
- % Affine-invariant ensemble sampling for hierarchical / partial-pooling
- % problems with GLOBAL (shared) parameters, via block Metropolis-within-Gibbs.
- %
- % CONTRACT (scope of this sampler):
- % The log-likelihood must factorise over units (voxels) as
- % sum_z loglik(y_z | theta_z, phi)
- % i.e. given the global parameters phi, the units are conditionally
- % independent. Parameters split into LOCAL theta_z (one set per unit) and
- % GLOBAL phi (shared). Any model with this structure is supported
- % (arbitrary NND local and NGlobal global parameters); the sampler holds
- % no model-specific knowledge.
- %
- % WHICH PARAMETERS ARE GLOBAL is detected from the starting structure: a
- % field of x0 with size==1 along the voxel dimension is treated as global
- % (see check_global_constant). So {R2c,k2A}, a shared diffusivity, a global
- % B1 term, etc., all work without code changes.
- %
- % One iteration = two decoupled blocks, each a Goodman-Weare stretch move:
- % LOCAL block : propose theta, GLOBALS HELD FIXED, exponent z^(NND-1),
- % forward model evaluated at (new local, old global).
- % GLOBAL block: propose phi, LOCALS HELD FIXED at their updated values,
- % exponent z^(NGlobal-1), forward model evaluated at
- % (current local, new global); acceptance uses the summed
- % log-likelihood DIFFERENCE accumulated in double precision.
- %
- % This structure is what keeps the cached likelihood consistent with the
- % current state at all times (the previous single-eval / two-accept scheme
- % left it stale) and gives each block its correct stretch Jacobian.
- %
- % NOTES / options:
- % .StepSize : stretch scale 'a'
- % .Nwalker : # walkers (even, >= 2*max(NND,NGlobal) recommended)
- % .startRange : local walker init spread (fraction of range)
- % .globalWarmup : (optional) # global-only iterations before the joint
- % loop (locals frozen). Default 0. Helps when the global
- % posterior is very tight.
- % .Ensembleupdate : ensemble update scheme, applied to BOTH blocks:
- % 'simultaneous' - (DEFAULT, backward compatible)
- % all walkers proposed at once using a
- % single derangement as partners.
- % 'redblack' - correct parallel update
- % (Foreman-Mackey 2013): split walkers
- % into two halves and update each half
- % using the other as frozen anchors.
- % Consistent with the option in goodman_weare.
- %
- % Goodman & Weare 2010; emcee (Foreman-Mackey 2013).
- fitting = this.check_set_default_basic(fitting);
- if isempty(weights); weights = ones(size(y), 'like', y); end
- [Nm, Nv] = size(y);
- Nvar = numel(fitting.modelParams);
- Nburnin = this.get_number_burnin(fitting);
- Ns = numel(Nburnin+1:fitting.thinning:fitting.iteration);
- Nwalker = fitting.Nwalker;
- StepSize = fitting.StepSize;
- % --- ensemble update scheme (consistent with goodman_weare) -----
- useRedBlack = strcmpi(fitting.Ensembleupdate,'redblack');
- if useRedBlack
- if mod(Nwalker,2) ~= 0
- warning('goodman_weare_wglobal_constant:Nwalker', ...
- 'Nwalker is odd; red-black halves will be unequal. Even Nwalker is conventional.');
- end
- h = floor(Nwalker/2);
- halfIdx = {1:h, h+1:Nwalker};
- end
- fprintf('Ensemble update scheme: %s\n', fitting.Ensembleupdate);
- % -----------------------------------------------------------------
- % convert to single + push to GPU
- y = gpuArray( single(y) );
- weights = gpuArray( single(weights) );
- for km = 1:Nvar; x0.(fitting.modelParams{km}) = gpuArray(single( x0.(fitting.modelParams{km}) )); end
- isGlobal = this.check_global_constant(x0,fitting.modelParams);
- NGlobal = numel(isGlobal(isGlobal==1));
- NND = Nvar - NGlobal;
- if NND==0 || NGlobal==0
- error('goodman_weare_wglobal_constant:partition', ...
- 'Need at least one local and one global parameter (NND=%d, NGlobal=%d). Use goodman_weare for the all-local case.',NND,NGlobal);
- end
- % bounds
- lb = gpuArray( single(repmat(fitting.lb(isGlobal==0),1,Nv,Nwalker)));
- ub = gpuArray( single(repmat(fitting.ub(isGlobal==0),1,Nv,Nwalker)));
- lb_global = gpuArray( single(repmat(fitting.lb(isGlobal==1),1,1,Nwalker)));
- ub_global = gpuArray( single(repmat(fitting.ub(isGlobal==1),1,1,Nwalker)));
- weights = repmat(weights,1,1,Nwalker);
- xPosterior_ND = zeros(NND, Nv, Nwalker, Ns, fitting.repetition,'single');
- xPosterior_global = zeros(NGlobal, 1, Nwalker, Ns, fitting.repetition,'single');
- % --- initialise walkers -------------------------------------------------
- [xCurr_ND,xCurr_global] = this.struct2array_wglobal(x0,fitting.modelParams);
- % local: tight cloud around starting point
- xCurr_ND = xCurr_ND + (ub-lb)*fitting.startRange.*randn(size(ub));
- xCurr_ND = min(max(xCurr_ND,lb),ub);
- % GLOBAL: OVER-DISPERSED across the full prior box. Ensemble samplers
- % cannot manufacture spread a collapsed cloud lacks, and the global
- % posterior is typically very tight (informed by all voxels), so a small
- % cloud can get stuck. Over-dispersion contracts correctly; collapse does not.
- % xCurr_global = lb_global + (ub_global-lb_global).*rand(size(ub_global));
- xCurr_global = xCurr_global + (ub_global-lb_global)*fitting.startRange.*rand(size(ub_global));
- x0 = this.array2struct_wglobal(xCurr_ND,xCurr_global,fitting.modelParams,isGlobal);
- logP0 = arrayfun(@logP_Gaussian, sum( weights.* (modelFWD(x0,varargin{:})-y).^2, 1 ), x0.noise, Nm);
- disp('-------------------------');
- disp('MCMC optimisation process (block GW: local + global)');
- disp('-------------------------');
- for ii = 1:fitting.repetition
- fprintf('Repetition #%i/%i \n',ii,fitting.repetition)
- logPCurr = logP0;
- [xCurr_ND,xCurr_global] = this.struct2array_wglobal(x0,fitting.modelParams);
- % optional global-only warmup (locals frozen) to settle the tight global block
- for kw = 1:fitting.globalWarmup
- [xCurr_global,logPCurr] = this.gw_global_block( ...
- xCurr_ND,xCurr_global,logPCurr,weights,y,Nm,Nv,Nwalker, ...
- StepSize,NGlobal,lb_global,ub_global,fitting,isGlobal,modelFWD,varargin{:});
- end
- counter = 0; start = tic;
- for k = 1:fitting.iteration
- % ============ LOCAL block (globals fixed) ============
- if ~useRedBlack
- % --- simultaneous (default, original behaviour) ---
- partner = this.find_partner(Nwalker);
- zz_ND = ((StepSize-1)*rand(1,Nv,Nwalker,'like',xCurr_ND) + 1).^2 / StepSize;
- xProp_ND = xCurr_ND(:,:,partner) + (xCurr_ND - xCurr_ND(:,:,partner)).*zz_ND;
- oob_ND = max(or(xProp_ND<lb, xProp_ND>ub),[],1);
- xProp_ND = min(max(xProp_ND,lb),ub);
- s_local = this.array2struct_wglobal(xProp_ND, xCurr_global, fitting.modelParams, isGlobal);
- logP_loc = arrayfun(@logP_Gaussian, sum( weights.*(modelFWD(s_local,varargin{:})-y).^2, 1 ), s_local.noise, Nm);
- aR = min( zz_ND.^(NND-1).*exp(logP_loc - logPCurr), 1);
- acc = aR > rand(1,Nv,Nwalker,'like',xCurr_ND);
- acc(oob_ND) = 0;
- logPCurr(acc) = logP_loc(acc); % cache <- (new local, OLD global)
- xCurr_ND(:,acc) = xProp_ND(:,acc);
- else
- % --- red-black: two sub-steps over walker halves ---
- for s = 1:2
- active = halfIdx{s}; frozen = halfIdx{3-s}; na = numel(active);
- pidx = frozen(randi(numel(frozen),1,na));
- xAnch = xCurr_ND(:,:,pidx); xAct = xCurr_ND(:,:,active);
- zz_ND = ((StepSize-1)*rand(1,Nv,na,'like',xCurr_ND) + 1).^2 / StepSize;
- xProp = xAnch + (xAct - xAnch).*zz_ND;
- lb_a = lb(:,:,active); ub_a = ub(:,:,active);
- isOOB = max(or(xProp<lb_a, xProp>ub_a),[],1);
- xProp = min(max(xProp,lb_a),ub_a);
- % eval at (new local active, OLD global active) -- globals fixed this block
- s_loc = this.array2struct_wglobal(xProp, xCurr_global(:,:,active), fitting.modelParams, isGlobal);
- logP_loc = arrayfun(@logP_Gaussian, sum( weights(:,:,active).*(modelFWD(s_loc,varargin{:})-y).^2, 1 ), s_loc.noise, Nm);
- logPAct = logPCurr(:,:,active);
- aR = min( zz_ND.^(NND-1).*exp(logP_loc - logPAct), 1);
- acc = aR > rand(1,Nv,na,'like',xCurr_ND); acc(isOOB) = 0;
- xAct(:,acc) = xProp(:,acc);
- logPAct(acc) = logP_loc(acc);
- xCurr_ND(:,:,active) = xAct;
- logPCurr(:,:,active) = logPAct;
- end
- end
- % ============ GLOBAL block (locals fixed at updated values) ============
- [xCurr_global,logPCurr] = this.gw_global_block( ...
- xCurr_ND,xCurr_global,logPCurr,weights,y,Nm,Nv,Nwalker, ...
- StepSize,NGlobal,lb_global,ub_global,fitting,isGlobal,modelFWD,varargin{:});
- % thinning / burn-in
- if ( k > Nburnin ) && mod(k-Nburnin+1, fitting.thinning) == 0
- counter = counter+1;
- xPosterior_ND(:,:,:,counter,ii) = gather(xCurr_ND);
- xPosterior_global(:,:,:,counter,ii) = gather(xCurr_global);
- end
- if mod(k,fitting.iteration/50) == 0 || k == min(1e2, fitting.iteration/100)
- ET = duration(0,0,toc(start),'Format','hh:mm:ss');
- ERT = ET / (k/fitting.iteration) - ET;
- fprintf('Iteration #%6d, Elapsed time (hh:mm:ss):%s, Estimated remaining time (hh:mm:ss):%s \n',k,string(ET),string(ERT));
- end
- end
- end
- xPosterior = this.array2struct_wglobal(xPosterior_ND,xPosterior_global,fitting.modelParams,isGlobal);
- for kvar = 1:Nvar; xPosterior.(fitting.modelParams{kvar}) = shiftdim(xPosterior.(fitting.modelParams{kvar}),1); end
- disp('The block affine-invariant ensemble MCMC sampling is completed.')
- end
- % ---- GLOBAL block: one GW stretch update of phi, locals held fixed -------
- function [xCurr_global,logPCurr] = gw_global_block(this, ...
- xCurr_ND,xCurr_global,logPCurr,weights,y,Nm,Nv,Nwalker, ...
- StepSize,NGlobal,lb_global,ub_global,fitting,isGlobal,modelFWD,varargin)
- useRedBlack = strcmpi(fitting.Ensembleupdate,'redblack');
- if ~useRedBlack
- % --- simultaneous (default, original behaviour) ---
- partner = this.find_partner(Nwalker);
- zz_g = ((StepSize-1)*rand(1,1,Nwalker,'like',xCurr_global) + 1).^2 / StepSize;
- gProp = xCurr_global(:,:,partner) + (xCurr_global - xCurr_global(:,:,partner)).*zz_g;
- oob_g = max(or(gProp<lb_global, gProp>ub_global),[],1);
- gProp = min(max(gProp,lb_global),ub_global);
- s_glob = this.array2struct_wglobal(xCurr_ND, gProp, fitting.modelParams, isGlobal);
- logP_g = arrayfun(@logP_Gaussian, sum( weights.*(modelFWD(s_glob,varargin{:})-y).^2, 1 ), s_glob.noise, Nm);
- dlogP = sum( double(logP_g - logPCurr), 2 );
- aR_g = min( zz_g.^(NGlobal-1).*exp(dlogP), 1 );
- acc_g = aR_g > rand(1,1,Nwalker,'like',xCurr_global);
- acc_g(oob_g) = 0; acc_g = logical(acc_g);
- xCurr_global(:,:,acc_g) = gProp(:,:,acc_g);
- logPCurr(:,:,acc_g) = logP_g(:,:,acc_g);
- else
- % --- red-black: two sub-steps over walker halves ---
- h_g = floor(Nwalker/2); halfIdx_g = {1:h_g, h_g+1:Nwalker};
- for s = 1:2
- active = halfIdx_g{s}; frozen = halfIdx_g{3-s}; na = numel(active);
- pidx = frozen(randi(numel(frozen),1,na));
- xg_act = xCurr_global(:,:,active);
- zz_g = ((StepSize-1)*rand(1,1,na,'like',xCurr_global) + 1).^2 / StepSize;
- gProp = xCurr_global(:,:,pidx) + (xg_act - xCurr_global(:,:,pidx)).*zz_g;
- oob_g = max(or(gProp<lb_global(:,:,active), gProp>ub_global(:,:,active)),[],1);
- gProp = min(max(gProp,lb_global(:,:,active)),ub_global(:,:,active));
- % eval at (current local active, new global active) -- locals fixed this block
- s_glob = this.array2struct_wglobal(xCurr_ND(:,:,active), gProp, fitting.modelParams, isGlobal);
- logP_g = arrayfun(@logP_Gaussian, sum( weights(:,:,active).*(modelFWD(s_glob,varargin{:})-y).^2, 1 ), s_glob.noise, Nm);
- lp_act = logPCurr(:,:,active);
- dlogP = sum( double(logP_g - lp_act), 2 ); % [1,1,na], double
- aR_g = min( zz_g.^(NGlobal-1).*exp(dlogP), 1 );
- acc_g = aR_g > rand(1,1,na,'like',xCurr_global);
- acc_g(oob_g) = 0; acc_g = logical(acc_g);
- xg_act(:,:,acc_g) = gProp(:,:,acc_g);
- lp_act(:,:,acc_g) = logP_g(:,:,acc_g);
- xCurr_global(:,:,active) = xg_act;
- logPCurr(:,:,active) = lp_act;
- end
- end
- end
- end
- methods(Static)
- % check and set default fitting algorithm parameters
- function fitting2 = check_set_default_basic(fitting)
- % Input
- % -----
- % fitting : structure contains fitting algorithm parameters
- % .iteration : no. of maximum MCMC iterations, default = 200k
- % .repetition : no. of MCMC repetitions, default = 1
- % .thinning : MCMC thinning interval, default = every 20 iterations
- % .burnin : MCMC burn-in ratio, default = 10%
- % .metric : method to compute expected valur from posterior distribution, 'mean' (default) | 'median'
- % .algorithm : MCMC algorithm 'MH': Metropolis-Hastings; 'GW': Goodman-Weare, 'MH' (default) | 'GW'
- % .StepSize : Step size for Goodman-Weare, default = 2
- % .Nwalker : number of walkers for Goodman-Weare, default = 50
- %
- fitting2 = fitting;
- % get fitting algorithm setting
- if ~isfield(fitting,'iteration'); fitting2.iteration = 2e5; end
- if ~isfield(fitting,'thinning'); fitting2.thinning = 20; end % thinning, sampled every 100 interval
- if ~isfield(fitting,'metric'); fitting2.metric = {'mean','std'}; end
- if ~isfield(fitting,'burnin'); fitting2.burnin = 0.1; end % 10% burnin
- if ~isfield(fitting,'repetition'); fitting2.repetition = 1; end
- if ~isfield(fitting,'outputFilename'); fitting2.outputFilename = []; end
- if ~isfield(fitting,'algorithm'); fitting2.algorithm = 'MH'; end
- if ~isfield(fitting,'StepSize'); fitting2.StepSize = 2; end
- if ~isfield(fitting,'Nwalker'); fitting2.Nwalker = 50; end
- if ~isfield(fitting,'ub'); fitting2.ub = []; end
- if ~isfield(fitting,'lb'); fitting2.lb = []; end
- if ~isfield(fitting,'startRange'); fitting2.startRange = 0.001; end
- % --- choose ensemble update scheme (default = original behaviour) ----
- if ~isfield(fitting,'Ensembleupdate'); fitting2.Ensembleupdate = 'simultaneous'; end
- if ~isfield(fitting,'globalWarmup'); fitting2.globalWarmup = 0; end
- if any(ismember(fitting2.metric,'mode'))
- if ~isfield(fitting,'Nbin'); fitting2.Nbin = 1001; end
- end
- if ~isfield(fitting,'autoMemManage'); fitting2.autoMemManage = true; end
- if ~iscell(fitting2.metric)
- fitting2.metric = cellstr(fitting2.metric);
- end
- if strcmpi(fitting2.algorithm ,'gw'); fitting2.algorithm = 'ensemble'; end % legacy
- end
- % display fitting algorithm parameters
- function display_basic_algorithm_parameters(fitting)
- if strcmpi( fitting.algorithm, 'ensemble'); algorithm = 'Affine-Invariant Ensemble';
- else; algorithm = 'Metropolis-Hastings'; end
- disp('----------------------------------------------------');
- disp('Markov Chain Monte Carlo (MCMC) algorithm parameters');
- disp('----------------------------------------------------');
- disp(['Algorithm : ', algorithm]);
- disp(['No. of iterations : ', num2str(fitting.iteration)]);
- disp(['No. of repetitions: ', num2str(fitting.repetition)])
- disp(['Thinning : ', num2str(fitting.thinning)]);
- disp(['Burn-in (#iter.) : ' num2str(mcmc.get_number_burnin(fitting))])
- disp(['Metric(s) : ', cell2str(fitting.metric)]);
- if strcmpi( fitting.algorithm, 'ensemble'); disp(['Step size : ', num2str(fitting.StepSize) ]); end
- if strcmpi( fitting.algorithm, 'ensemble'); disp(['No. of walkers : ', num2str(fitting.Nwalker) ]); end
- end
- % save the mcmc output structure variable into disk space
- function save_mcmc_output(outputFilename,out)
- % Input
- % ------------------
- % outputFilename : output filename
- % out : output structure of askadam
- %
- % save the estimation results if the output filename is provided
- if ~isempty(outputFilename)
- [output_dir,~,~] = fileparts(outputFilename);
- if ~exist(output_dir,'dir')
- mkdir(output_dir);
- end
- save(outputFilename,'out');
- fprintf('Estimation output is saved at %s\n',outputFilename);
- end
- end
- % convert numerical array into structure variable for FWD function
- function x_struct = array2struct(x,fields)
- for k = 1:numel(fields)
- x_struct.(fields{k}) = x(k,:,:,:,:,:);
- end
- end
- % convert structure variable into numerical array
- function x = struct2array(x_struct,fields)
- nVol = size(x_struct.(fields{1}),2);
- nWalker = size(x_struct.(fields{1}),3);
- x = gpuArray(zeros(numel(fields),nVol,nWalker,"single"));
- for k = 1:numel(fields)
- x(k,:,:) = x_struct.(fields{k});
- end
- end
- function x_struct = array2struct_wglobal(x_ND,x_global,fields, isGlobal)
- ctr_global = 1; ctr_ND = 1;
- for k = 1:numel(fields)
- if isGlobal(k)
- x_struct.(fields{k}) = x_global(ctr_global,:,:,:,:,:);
- ctr_global = ctr_global + 1;
- else
- x_struct.(fields{k}) = x_ND(ctr_ND,:,:,:,:,:);
- ctr_ND = ctr_ND +1;
- end
- end
- end
- function [x_ND,x_global] = struct2array_wglobal(x_struct,fields)
- % check if the fitting parameter is global or voxel
- isGlobal = mcmc.check_global_constant(x_struct,fields);
- nVol = 0; for k = 1:numel(fields); nVol = max(size(x_struct.(fields{k}),2),nVol); end
- nWalker = size(x_struct.(fields{1}),3);
- x_ND = gpuArray(zeros(numel(isGlobal(isGlobal==0)),nVol,nWalker,"single"));
- x_global = gpuArray(zeros(numel(isGlobal(isGlobal==1)),1,nWalker,"single"));
- ctr_global = 1; ctr_ND = 1;
- for k = 1:numel(fields)
- if isGlobal(k)
- x_global(ctr_global,1,:) = x_struct.(fields{k});
- ctr_global = ctr_global +1;
- else
- x_ND(ctr_ND,:,:) = x_struct.(fields{k});
- ctr_ND = ctr_ND +1;
- end
- end
- end
- function isGlobal = check_global_constant(x_struct,fields)
- % check if the fitting parameter is global or voxel
- isGlobal = zeros(numel(fields),1);
- for k = 1:numel(fields)
- if size(x_struct.(fields{k}),2) > 1
- isGlobal(k) = false;
- else
- isGlobal(k) = true;
- end
- end
- end
- % compute the number of iteration requires for burn-in
- function Nburnin = get_number_burnin(fitting)
- if fitting.burnin < 1
- Nburnin = floor(fitting.iteration*fitting.burnin);
- else
- Nburnin = fitting.burnin;
- end
- end
- % find a unique partner for an index
- function partner = find_partner(maxIndex)
- isSelfPartner = true;
- while isSelfPartner
- partner = randperm(maxIndex);
- isSelfPartner = any(partner == 1:maxIndex,'all');
- end
- end
- % convert estimation into organised output structure
- function out = res2out(xPosterior,fitting,mask)
- % store the unshaped posterior into out
- out.posterior = xPosterior;
- % compute additional metric if specified
- fields = fieldnames(xPosterior);
- % Nvox = size(xPosterior.(fields{1}),1);
- Nsample = prod(size(xPosterior.(fields{1}),2:5));
- metrics = fitting.metric;
- if ~isempty(metrics)
- for km = 1:numel(metrics)
- switch lower(metrics{km})
- case 'mean'
- for kvar=1:numel(fields)
- tmp = mean( reshape( xPosterior.(fields{kvar}), [size(xPosterior.(fields{kvar}),1), Nsample]),2);
- tmp = utils.reshape_ND2image(tmp,mask);
- out.mean.(fields{kvar}) = tmp;
- end
- case 'median'
- for kvar=1:numel(fields)
- tmp = median( reshape( xPosterior.(fields{kvar}), [size(xPosterior.(fields{kvar}),1), Nsample]),2);
- tmp = utils.reshape_ND2image(tmp,mask);
- out.median.(fields{kvar}) = tmp;
- end
- case 'std'
- for kvar=1:numel(fields)
- tmp = std( reshape( xPosterior.(fields{kvar}), [size(xPosterior.(fields{kvar}),1), Nsample]),[],2);
- tmp = utils.reshape_ND2image(tmp,mask);
- out.std.(fields{kvar}) = tmp;
- end
- case 'iqr'
- for kvar=1:numel(fields)
- tmp = iqr( reshape( xPosterior.(fields{kvar}), [size(xPosterior.(fields{kvar}),1), Nsample]),2);
- tmp = utils.reshape_ND2image(tmp,mask);
- out.iqr.(fields{kvar}) = tmp;
- end
- case 'mode'
- for kvar=1:numel(fields)
- Nbin = fitting.Nbin;
- idx = find(ismember(fitting.modelParams,fields{kvar}));
- edges = linspace(fitting.lb(idx)-1e-8,fitting.ub(idx)+1e-8,Nbin);
- tmp = reshape( xPosterior.(fields{kvar}), [size(xPosterior.(fields{kvar}),1), Nsample]);
- tmp = mode(discretize(tmp,edges),2);
- tmp = (edges(tmp) + edges(tmp+1)) / 2;
- tmp = utils.reshape_ND2image(tmp.',mask);
- out.mode.(fields{kvar}) = tmp;
- end
- end
- end
- end
- end
- % make sure all network parameters stay between 0 and 1
- function parameters = set_boundary(parameters,ub,lb)
- field = fieldnames(parameters);
- for k = 1:numel(field)
- parameters.(field{k}) = max(parameters.(field{k}),lb(k)); % Lower bound
- parameters.(field{k}) = min(parameters.(field{k}),ub(k)); % upper bound
- end
- end
- end
- end
mcmc.m at commit 05f49d4, under GPL-3.0 · at the source
Overview
- Athinoula A. Martinos Center for Biomedical Imaging, Department of Radiology, Massachusetts General Hospital, Charlestown, Massachusetts, USA
- Harvard Medical School, Boston, Massachusetts, USA
- Department of Biomedical Engineering, Ulsan National Institute of Science and Technology, Ulsan, South Korea
- Institute of Medical Physics and Radiation Protection, Mittelhessen University of Applied Sciences, Giessen, Germany
- Department of Diagnostic and Interventional Radiology, University Hospital Marburg, Philipps University of Marburg, Marburg, Germany
- Harvard‐MIT Division of Health Sciences and Technology, Massachusetts Institute of Technology, Cambridge, Massachusetts, USA
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.
yixinma9/diffusion_preproc_C2
59032d4f5ea70d3fbe37d93ae8d4d049e217d315, 7 August 2025Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
17 files
- denoise/
rician_correct_mppca.sh , Shell, 146 lines - helpers/
__init__.py , Python, 1 line - helpers/
concat_dwis.py , Python, 146 lines - helpers/
create_index_helper.py , Python, 15 lines - helpers/
dcm2bids_exportparam_con , Python, 16 linescat_helper.py - helpers/
dcm2bids_runner.py , Python, 21 lines - helpers/
degibbs_helper.py , Python, 27 lines - helpers/
denoise_helper.py , Python, 18 lines - helpers/
diffusion_parameters_exp , Python, 95 lines, 1 matchorter.py - helpers/
eddy_helper.py , Python, 37 lines - helpers/
generate_masks_helper.py , Python, 28 lines - helpers/
gnc_anat_helper.py , Python, 19 lines - helpers/
gnc_helper.py , Python, 16 lines - helpers/
interpolation_eddy_gnc_h , Python, 67 lineselper.py - helpers/
topup_helper.py , Python, 37 lines - run.py, Python, 1,314 lines
- readme.md, Text, 150 lines
kschan0214/gacelle
05f49d48dac7926b6c69a5612ec5dfca7f8cee1b, 9 September 2026Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
213 files
- AxCaliberSMT/
demo_gpuAxCaliberSMT_Noi , MATLAB, 113 linessePropagation.m - AxCaliberSMT/
demo_gpuAxCaliberSMT_inv , MATLAB, 110 linesivoData.m - AxCaliberSMT/
gpuAxCaliberSMT.m , MATLAB, 816 lines, 1 match - AxCaliberSMT/
private/ , MATLAB, 26 linesAxCaliberSMT_signal_comb ine.m - AxCaliberSMT/
private/ , MATLAB, 27 linesAxCaliberSMT_vanGelderen _decay_part1.m - AxCaliberSMT/
private/ , MATLAB, 22 linesAxCaliberSMT_vanGelderen _decay_part2.m - AxCaliberSMT/
private/ , MATLAB, 7 linesMEAxCaliberSMT_signal_co mbine.m - AxCaliberSMT/
private/ , MATLAB, 6 linesdiffusion_relaxation_SMT _sphere_unrestricted.m - AxCaliberSMT/
private/ , MATLAB, 5 linesdiffusion_relaxation_SMT _stick.m - AxCaliberSMT/
private/ , MATLAB, 9 linesdiffusion_relaxation_SMT _zeppelin.m - AxCaliberSMT/
sandbox/ , MATLAB, 118 linesdemo_gpuMEAxCaliberSMT_N oisePropagation.m - AxCaliberSMT/
sandbox/ , MATLAB, 75 linesdeprecated/ demo_gpuAxCaliberSMT_Noi sePropagation_mcmc.m - AxCaliberSMT/
sandbox/ , MATLAB, 73 linesdeprecated/ demo_gpuAxCaliberSMTmcmc _NoisePropagation.m - AxCaliberSMT/
sandbox/ , MATLAB, 246 linesdeprecated/ demo_gpuAxCaliberSMTmcmc _invivoData.m - AxCaliberSMT/
sandbox/ , MATLAB, 88 linesdeprecated/ demo_gpuMEAxCaliberSMT_N oisePropagation_mcmc.m - AxCaliberSMT/
sandbox/ , MATLAB, 564 linesdeprecated/ gpuAxCaliberSMTmcmc.m - AxCaliberSMT/
sandbox/ , MATLAB, 819 linesdeprecated/ gpuMEAxCaliberSMTmcmc.m - AxCaliberSMT/
sandbox/ , MATLAB, 677 linesgpuAxonalT2model.m - AxCaliberSMT/
sandbox/ , MATLAB, 1,431 linesgpuMEAxCaliberSMT.m - AxCaliberSMT/
sandbox/ , MATLAB, 829 linesgpuMEAxCaliberSMT_gammaD ist.m - AxCaliberSMT/
sandbox/ , MATLAB, 830 linesgpuMEAxCaliberSMT_gammaD ist_sd.m - AxCaliberSMT/
sandbox/ , MATLAB, 817 linesgpuMEAxCaliberSMTmcmc_up date.m - MCRMWI/
EPGXgen_net/ , MATLAB, 194 linesfeature_preprocess_MCRMW I_MLP_EPGX_leakyrelu.m - MCRMWI/
EPGXgen_net/ , MATLAB, 47 linesmlp_model_leakyRelu.m - MCRMWI/
EPGXgen_net/ , MATLAB, 31 linesmodelGradients_mcr_1d.m - MCRMWI/
EPGXgen_net/ , MATLAB, 4 linesmodel_GRE_steadystate_Bl och.m - MCRMWI/
EPGXgen_net/ , MATLAB, 76 linesmodel_mcr_ann_1d.m - MCRMWI/
EPGXgen_net/ , MATLAB, 17 linesmpl_training/ README.m - MCRMWI/
EPGXgen_net/ , MATLAB, 130 linesmpl_training/ Step01_create_epgx_dicti onary_rfphase50.m - MCRMWI/
EPGXgen_net/ , MATLAB, 260 linesmpl_training/ Step02_train_mlp_epgx_AN N_phase_N2e6.m - MCRMWI/
EPGXgen_net/ , MATLAB, 285 linesmpl_training/ Step03_train_mlp_epgx_AN N_magn_N2e6.m - MCRMWI/
EPGXgen_net/ , MATLAB, 358 linesmpl_training/ Step04_validate_ANN_2025 0819.m - MCRMWI/
EPGXgen_net/ , MATLAB, 21 linesmpl_training/ compute_number_learnable _params.m - MCRMWI/
EPGXgen_net/ , MATLAB, 80 linesmpl_training/ create_mlp.m - MCRMWI/
EPGXgen_net/ , MATLAB, 194 linesmpl_training/ feature_preprocess_MCRMW I_MLP_EPGX_leakyrelu.m - MCRMWI/
EPGXgen_net/ , MATLAB, 64 linesmpl_training/ modelGradients_mlp_epgx_ ANN_corr_L1.m - MCRMWI/
EPGXgen_net/ , MATLAB, 4 linesmpl_training/ rand_in_range.m - MCRMWI/
demo_gpuGREMWI_invivo.m , MATLAB, 162 lines - MCRMWI/
demo_gpuGREMWI_noiseProp , MATLAB, 145 linesagation.m - MCRMWI/
demo_gpuMCRMWI_invivo.m , MATLAB, 168 lines - MCRMWI/
demo_gpuMCRMWI_noiseProp , MATLAB, 143 linesagation.m - MCRMWI/
despot1.m , MATLAB, 258 lines - MCRMWI/
gpuGREMWI.m , MATLAB, 915 lines - MCRMWI/
gpuMCRMWI.m , MATLAB, 1,207 lines, 1 match - MCRMWI/
private/ , MATLAB, 8 linesMCRMWI_Simag.m - MCRMWI/
private/ , MATLAB, 8 linesMCRMWI_Sreal.m - MCRMWI/
private/ , MATLAB, 15 linescompute_gremwi_signal.m - MCRMWI/
private/ , MATLAB, 7 linesgremwi_S0_compartments.m - MCRMWI/
private/ , MATLAB, 5 lineshcfm_fibre_volume_fracti on.m - MCRMWI/
private/ , MATLAB, 5 lineshcfm_gratio.m - MCRMWI/
private/ , MATLAB, 33 linesmodel_BM_2T1_analytical. m - MCRMWI/
private/ , MATLAB, 8 linesmodel_Bloch_2T1.m - MCRMWI/
private/ , MATLAB, 28 linesmodel_DIMWI.m - MCRMWI/
sandbox/ , MATLAB, 1,109 linesgpuMCRMWImcmc.m - MCRMWI/
signal_steadystate_Bloch , MATLAB, 27 lines.m - MCRMWI/
validation_MCRMWI.m , MATLAB, 96 lines - NEXI/
NEXI.m , MATLAB, 406 lines - NEXI/
NEXIrotinv.m , MATLAB, 485 lines - NEXI/
demo_gpuNEXI_NoisePropag , MATLAB, 133 linesation.m - NEXI/
demo_gpuNEXI_NoisePropag , MATLAB, 123 linesation_advanced.m - NEXI/
demo_gpuNEXI_invivo.m , MATLAB, 81 lines - NEXI/
gpuNEXI.m , MATLAB, 1,347 lines - NEXI/
private/ , MATLAB, 19 linesNEXI_M.m - NEXI/
private/ , MATLAB, 16 linesNEXI_MSl2.m - NEXI/
sandbox/ , MATLAB, 273 linesgpuNEXIdot.m - NEXI/
sandbox/ , MATLAB, 776 linesgpuNEXIrice.m - R1R2s/
demo_gpuJointR1R2starMap , MATLAB, 103 linesping_NoisePropagation.m - R1R2s/
demo_gpuJointR1R2starMap , MATLAB, 100 linesping_invivo.m - R1R2s/
gpuJointR1R2starMapping. , MATLAB, 624 linesm - R1R2s/
private/ , MATLAB, 14 linesmodel_jointR1R2s_singlec ompartment.m - R1R2s/
sandbox/ , MATLAB, 167 linesMEDI_spatial_tv_wCSF.m - R1R2s/
sandbox/ , MATLAB, 573 linesgpuJointR1R2starChiMappi ng.m - R2star/
demo_gpuR2starMapping_No , MATLAB, 97 linesisePropagation.m - R2star/
demo_gpuR2starMapping_in , MATLAB, 88 linesvivo.m - R2star/
gpuR2starMapping.m , MATLAB, 533 lines - R2star/
private/ , MATLAB, 10 linesmodel_R2s_singlecompartm ent.m - SANDI/
demo_gpuSANDI_NoisePropa , MATLAB, 120 linesgation.m - SANDI/
demo_invivo.m , MATLAB, 77 lines - SANDI/
gpuSANDI.m , MATLAB, 759 lines - SANDI/
private/ , MATLAB, 16 linesC_arrayfun.m - SANDI/
private/ , MATLAB, 35 linesCsum_arrayfun.m - SANDI/
private/ , MATLAB, 36 linesdiffusion_sphere_restric ted_wide_Sl0_arrayfun.m - SANDI/
private/ , MATLAB, 3 linessignal_SANDI.m - SANDI/
sandbox/ , MATLAB, 737 linesgpuSANDI_fromSANDIX.m - addpath_gacelle.m, MATLAB, 47 lines
- docs/
conf.py , Python, 50 lines - examples/
Example_monoexponential_ , MATLAB, 32 linesFWD_GD.m - examples/
Example_monoexponential_ , MATLAB, 31 linesFWD_askadam_3D_Strategy1 .m - examples/
Example_monoexponential_ , MATLAB, 43 linesFWD_askadam_3D_Strategy2 .m - examples/
Example_monoexponential_ , MATLAB, 80 linesautomem.m - examples/
Example_monoexponential_ , MATLAB, 76 linesestimate_askadam.m - examples/
Example_monoexponential_ , MATLAB, 82 linesestimate_askadam_3D_Stra tegy1.m - examples/
Example_monoexponential_ , MATLAB, 82 linesestimate_askadam_3D_Stra tegy2.m - examples/
Example_monoexponential_ , MATLAB, 251 linesestimate_askadam_3D_wReg _Stra1.m - examples/
Example_monoexponential_ , MATLAB, 253 linesestimate_askadam_3D_wReg _Stra2.m - examples/
Example_monoexponential_ , MATLAB, 79 linesestimate_mcmc.m - examples/
Example_monoexponential_ , MATLAB, 81 linesestimate_mcmc_MH.m - examples/
Example_monoexponential_ , MATLAB, 83 linesestimate_mcmc_ensemble.m - examples/
demo_convergence_usage.m , MATLAB, 319 lines - examples/
demo_convergence_usage2. , MATLAB, 520 linesm - mcmicro/
demo_invivo.m , MATLAB, 51 lines - mcmicro/
demo_noise_propagation.m , MATLAB, 96 lines - mcmicro/
demo_noise_propagation_w , MATLAB, 84 linesR2.m - mcmicro/
gpumcmicro.m , MATLAB, 719 lines - mcmicro/
private/ , MATLAB, 34 linesdiffusion_relaxation_sph erical_mean_combine.m - qsm/
+MEDI_helper/ , MATLAB, 31 linesSMV.m - qsm/
+MEDI_helper/ , MATLAB, 54 linescompute_preconditioner.m - qsm/
+MEDI_helper/ , MATLAB, 142 linesextract_CSF.m - qsm/
+MEDI_helper/ , MATLAB, 82 linesfgrad.m - qsm/
+MEDI_helper/ , MATLAB, 26 linesgradient_mask.m - qsm/
+MEDI_helper/ , MATLAB, 65 linessphere_kernel.m - qsm/
demo_gpuPDF_invivo.m , MATLAB, 80 lines - qsm/
gpuPDF.m , MATLAB, 572 lines - qsm/
gpumcTFI.m , MATLAB, 838 lines - qsm/
private/ , MATLAB, 24 linesR2star_trapezoidal.m - qsm/
private/ , MATLAB, 171 linescheck_padsize.m - qsm/
private/ , MATLAB, 16 linescrop_padding.m - qsm/
private/ , MATLAB, 31 linesdipole_kernel.m - qsm/
sandbox/ , MATLAB, 1,349 lines(backup)gpumcTFI.m - qsm/
sandbox/ , MATLAB, 1,362 lines(backup2)gpumcTFI.m - qsm/
sandbox/ , MATLAB, 784 lines(backup20260729)gpumcTFI .m - qsm/
sandbox/ , MATLAB, 114 linesdemo_gpuTFIR2star_invivo .m - qsm/
sandbox/ , MATLAB, 113 linesdemo_gpuTFI_invivo.m - qsm/
sandbox/ , MATLAB, 141 linesdemo_gpumcTFI_invivo.m - qsm/
sandbox/ , MATLAB, 118 linesestimate_noise_map.m - qsm/
sandbox/ , MATLAB, 1,331 linesgpuMETFI.m - qsm/
sandbox/ , MATLAB, 1,349 linesgpuMETFIv2.m - qsm/
sandbox/ , MATLAB, 1,292 linesgpuTFI.m - qsm/
sandbox/ , MATLAB, 1,495 linesgpuTFIR2star.m - qsm/
sandbox/ , MATLAB, 1,505 linesgpuTFIS0R2star.m - recon/
apply_sense_2D.m , MATLAB, 38 lines - sandbox/
DWI/ , MATLAB, 758 linesgpuStick.m - sandbox/
SANDIX/ , MATLAB, 737 linesgpuSANDIX.m - tests/
+gacelletest/ , MATLAB, 26 linesassumeGPU.m - tests/
ClassAvailabilityTest.m , MATLAB, 94 lines - tests/
SmokeFit_AxCaliberSMTTes , MATLAB, 60 linest.m - tests/
SmokeFit_GREMWITest.m , MATLAB, 78 lines - tests/
SmokeFit_JointR1R2starMa , MATLAB, 65 linesppingTest.m - tests/
SmokeFit_MCRMWITest.m , MATLAB, 110 lines - tests/
SmokeFit_NEXITest.m , MATLAB, 60 lines - tests/
SmokeFit_R2starMappingTe , MATLAB, 55 linesst.m - tests/
SmokeFit_SANDITest.m , MATLAB, 61 lines - tests/
SmokeFit_gpuPDFTest.m , MATLAB, 75 lines - tests/
SmokeFit_gpumcTFITest.m , MATLAB, 88 lines - tests/
SmokeFit_mcmicroTest.m , MATLAB, 52 lines - tests/
run_tests.m , MATLAB, 34 lines - utils/
DWIutility.m , MATLAB, 876 lines - utils/
HCFM.m , MATLAB, 278 lines - utils/
MWIutility.m , MATLAB, 181 lines - utils/
SMEXSH.m , MATLAB, 229 lines - utils/
Spherical-Harmonic-Trans , MATLAB, 62 linesform/ Fdirs2grid.m - utils/
Spherical-Harmonic-Trans , MATLAB, 641 linesform/ TEST_SCRIPTS_SHT.m - utils/
Spherical-Harmonic-Trans , MATLAB, 34 linesform/ checkCondNumberSHT.m - utils/
Spherical-Harmonic-Trans , MATLAB, 27 linesform/ complex2realCoeffs.m - utils/
Spherical-Harmonic-Trans , MATLAB, 49 linesform/ complex2realSHMtx.m - utils/
Spherical-Harmonic-Trans , MATLAB, 31 linesform/ conjCoeffs.m - utils/
Spherical-Harmonic-Trans , MATLAB, 38 linesform/ directSHT.m - utils/
Spherical-Harmonic-Trans , MATLAB, 52 linesform/ euler2rotationMatrix.m - utils/
Spherical-Harmonic-Trans , MATLAB, 45 linesform/ gaunt_mtx.m - utils/
Spherical-Harmonic-Trans , MATLAB, 45 linesform/ gaunt_mtx_fast.m - utils/
Spherical-Harmonic-Trans , MATLAB, 39 linesform/ getFliegeNodes.m - utils/
Spherical-Harmonic-Trans , MATLAB, 58 linesform/ getRealGauntMtx.m - utils/
Spherical-Harmonic-Trans , MATLAB, 89 linesform/ getSH.m - utils/
Spherical-Harmonic-Trans , MATLAB, 188 linesform/ getSHrotMtx.m - utils/
Spherical-Harmonic-Trans , MATLAB, 39 linesform/ getTdesign.m - utils/
Spherical-Harmonic-Trans , MATLAB, 27 linesform/ getVoronoiWeights.m - utils/
Spherical-Harmonic-Trans , MATLAB, 49 linesform/ grid2dirs.m - utils/
Spherical-Harmonic-Trans , MATLAB, 28 linesform/ inverseSHT.m - utils/
Spherical-Harmonic-Trans , MATLAB, 40 linesform/ leastSquaresSHT.m - utils/
Spherical-Harmonic-Trans , MATLAB, 37 linesform/ legendre2.m - utils/
Spherical-Harmonic-Trans , MATLAB, 98 linesform/ plotSphFunctionCoeffs.m - utils/
Spherical-Harmonic-Trans , MATLAB, 86 linesform/ plotSphFunctionGrid.m - utils/
Spherical-Harmonic-Trans , MATLAB, 78 linesform/ plotSphFunctionTriangle. m - utils/
Spherical-Harmonic-Trans , MATLAB, 27 linesform/ real2complexCoeffs.m - utils/
Spherical-Harmonic-Trans , MATLAB, 49 linesform/ real2complexSHMtx.m - utils/
Spherical-Harmonic-Trans , MATLAB, 49 linesform/ replicatePerOrder.m - utils/
Spherical-Harmonic-Trans , MATLAB, 33 linesform/ rotateAxisCoeffs.m - utils/
Spherical-Harmonic-Trans , MATLAB, 35 linesform/ sphConvolution.m - utils/
Spherical-Harmonic-Trans , MATLAB, 43 linesform/ sphDelaunay.m - utils/
Spherical-Harmonic-Trans , MATLAB, 39 linesform/ sphMultiplication.m - utils/
Spherical-Harmonic-Trans , MATLAB, 125 linesform/ sphVoronoi.m - utils/
Spherical-Harmonic-Trans , MATLAB, 65 linesform/ sphVoronoiAreas.m - utils/
Spherical-Harmonic-Trans , MATLAB, 64 linesform/ sym_w3j.m - utils/
Spherical-Harmonic-Trans , MATLAB, 19 linesform/ unitCart2sph.m - utils/
Spherical-Harmonic-Trans , MATLAB, 19 linesform/ unitSph2cart.m - utils/
Spherical-Harmonic-Trans , MATLAB, 51 linesform/ w3j.m - utils/
Spherical-Harmonic-Trans , MATLAB, 68 linesform/ w3j_stirling.m - utils/
Spherical-Harmonic-Trans , MATLAB, 80 linesform/ wignerD.m - utils/
askadam.m , MATLAB, 1,246 lines - utils/
cell2num2str.m , MATLAB, 5 lines - utils/
cell2str.m , MATLAB, 5 lines - utils/
check_dwi_invivo_demo_da , MATLAB, 17 linesta.m - utils/
check_gre_invivo_demo_da , MATLAB, 58 linesta.m - utils/
development/ , MATLAB, 327 linesdeprecated/ mcmc_deprecated.m - utils/
gacelleFFT.m , MATLAB, 228 lines - utils/
gacelle_besseli.m , MATLAB, 9 lines - utils/
gacelle_trapz.m , MATLAB, 61 lines - utils/
logP.m , MATLAB, 22 lines - utils/
logP_Gaussian.m , MATLAB, 22 lines - utils/
mcmc.m , MATLAB, 878 lines, 2 matches - utils/
polyfit3D_NthOrder.m , MATLAB, 40 lines - utils/
rician.m , MATLAB, 61 lines - utils/
rotational_invariant.m , MATLAB, 237 lines - utils/
rotinv/ , MATLAB, 29 linesdiffusion_axisym_gaussia n_Sl0.m - utils/
rotinv/ , MATLAB, 24 linesdiffusion_sphere_Sl0.m - utils/
rotinv/ , MATLAB, 31 linesdiffusion_sphere_restric ted_narrow_Sl0.m - utils/
rotinv/ , MATLAB, 49 linesdiffusion_sphere_restric ted_wide_Sl0.m - utils/
rotinv/ , MATLAB, 27 linesdiffusion_stick_Sl0.m - utils/
signal_G_finitePulses.m , MATLAB, 48 lines - utils/
spatial_total_variation. , MATLAB, 87 linesm - utils/
utils.m , MATLAB, 1,793 lines - LICENSE, License, 674 lines
- README.md, Text, 100 lines
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;
- 227 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.
Data availability statement
The paper has a 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 says that the data are available on request
Read it in the paper: doi.org/10.1002/hbm.70553.
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, 11 authors, 10 MeSH terms, 12 funders, 87 references.
Cite
This paper
Ma, Y., Eskandarian, L., Chan, K., Lee, H., Ramos‐Llordén, G., Bhatt, A., Gerold, J., Mahmutovic, M., Keil, B., Lee, H., & Huang, S. Y. (2026). Axon Diameter Mapping in the Living Human Brain with Ultra-High-Gradient Diffusion MRI at 500 mT/
BibTeX
@article{ma2026axon,
author = {Ma, Yixin and Eskandarian, Laleh and Chan, Kwok‐Shing and Lee, Hansol and Ramos‐Llordén, Gabriel and Bhatt, Aneri and Gerold, Julianna and Mahmutovic, Mirsad and Keil, Boris and Lee, Hong‐Hsi and Huang, Susie Y},
title = {{Axon Diameter Mapping in the Living Human Brain with Ultra-High-Gradient Diffusion MRI at 500 mT/
journal = {Human brain mapping},
year = {2026},
month = jun,
volume = {47},
number = {8},
pages = {e70553},
publisher = {Wiley},
issn = {1065-9471},
doi = {10.1002/
url = {https://
pmid = {42240067},
pmcid = {PMC13266422}
}
RIS
TY - JOUR
AU - Ma, Yixin
AU - Eskandarian, Laleh
AU - Chan, Kwok‐Shing
AU - Lee, Hansol
AU - Ramos‐Llordén, Gabriel
AU - Bhatt, Aneri
AU - Gerold, Julianna
AU - Mahmutovic, Mirsad
AU - Keil, Boris
AU - Lee, Hong‐Hsi
AU - Huang, Susie Y
TI - Axon Diameter Mapping in the Living Human Brain with Ultra-High-Gradient Diffusion MRI at 500 mT/
T2 - Human brain mapping
J2 - Hum Brain Mapp
PY - 2026
DA - 2026/
VL - 47
IS - 8
SP - e70553
SN - 1065-9471
PB - Wiley
DO - 10.1002/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1002/
"type": "article-journal",
"title": "Axon Diameter Mapping in the Living Human Brain with Ultra-High-Gradient Diffusion MRI at 500 mT/
"container-title": "Human brain mapping",
"author": [
{
"family": "Ma",
"given": "Yixin"
},
{
"family": "Eskandarian",
"given": "Laleh"
},
{
"family": "Chan",
"given": "Kwok‐Shing"
},
{
"family": "Lee",
"given": "Hansol"
},
{
"family": "Ramos‐Llordén",
"given": "Gabriel"
},
{
"family": "Bhatt",
"given": "Aneri"
},
{
"family": "Gerold",
"given": "Julianna"
},
{
"family": "Mahmutovic",
"given": "Mirsad"
},
{
"family": "Keil",
"given": "Boris"
},
{
"family": "Lee",
"given": "Hong‐Hsi"
},
{
"family": "Huang",
"given": "Susie Y"
}
],
"container-title-short":
"volume": "47",
"issue": "8",
"page": "e70553",
"DOI": "10.1002/
"PMID": "42240067",
"PMCID": "PMC13266422",
"ISSN": "1065-9471",
"publisher": "Wiley",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
6,
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.1109/tmi.2026.3664328 [code]
- Axon Diameter Mapping From Myelin Water Diffusion MRI.Journal: IEEE transactions on medical imagingIn common: MRtrix3, Optimization Toolbox, Image Processing Toolbox, 1 other tool, structural MRI / diffusion, 23 references, 2 authors
- [2] 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, author Hansol Lee
- [3] 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 medicineIn common: FSL, NumPy, structural MRI / diffusion, 16 references
- [4] doi:10.1371/journal.pbio.3003861
- Learning engages transient and sustained cellular mechanisms in the human brain.Journal: PLoS biologyIn common: structural MRI / diffusion, 12 references
- [5] doi:10.1038/s41467-026-71151-2 [code]
- Common and distinct neural correlates of social interaction processing and theory of mind in narratives.Journal: Nature communicationsIn common: MRtrix3, Optimization Toolbox, Parallel Computing Toolbox, 6 other tools, 1 reference
- [6] 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: NiBabel, NumPy, structural MRI / diffusion, 8 references
- [7] 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 reportsIn common: MRtrix3, FSL, Image Processing Toolbox, 3 other tools, structural MRI / diffusion, 4 references
- [8] doi:10.7554/elife.107661 [code]
- In vivo mapping of striatal neurodegeneration in Huntington's disease with Soma and Neurite Density Imaging.Journal: eLifeIn common: Deep Learning Toolbox, Optimization Toolbox, Image Processing Toolbox, 1 other tool, structural MRI / diffusion, 4 references
- [9] doi:10.1038/s43856-026-01614-6 [code]
- Simulation-based inference at the theoretical limit for fast, robust microstructural MRI with minimal diffusion data.Journal: Communications medicineIn common: NumPy, structural MRI / diffusion, 7 references
- [10] doi:10.1038/s41586-026-10631-3 [code]
- A prognostic human brain network for diffuse midline glioma.Journal: NatureIn common: Optimization Toolbox, Parallel Computing Toolbox, FreeSurfer, 5 other tools, 1 reference
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: 2 repositories of the authors' code, each at its verified commit and with its license, 227 scripts, and 5 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:1e9c2cf5ae632637…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
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.
