OSCR

Meningeal CSF transport varies across parasagittal dura subregions with age in humans.

Code ↔ Paper

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

The 4 matches · 1 of them tie a paragraph to a whole file, not to given lines: a weak match, whose lines are not tinted
  1. [1] § Methods › Imaging ↔ ASL_main.m, lines 42–103 · score 0.60 · SLIP series, 3000 ms, volumes, M0, slices, TI
  2. [2] § Results ↔ asl_subroutines/aslFitParams.m, the whole file · a weak match · score 0.55 · full width, Peak heights, FWHM, AUC, TTP, curve
  3. [3] § Results ↔ ASL_main.m, lines 42–103 · score 0.51 · subtraction maps, 3000 ms, zoomed, overlays, colormaps, M0
  4. [4] § Results ↔ asl_subroutines/aslFit.m, lines 209–293 · score 0.51 · bi component, TTPG, R2, FWHM, AUC, PH

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 · 719 lines · 24 KB · MIT · 2 matches

  1. %% ========================================================================
  2. % Top level code for perfusion anlysis
  3. %
  4. %==========================================================================
  5. %
  6. % 05/2025 - VM for Canon ([email hidden]) v2.0
  7. %
  8. %==========================================================================
  9. %
  10. % expected folder strucutre:
  11. %
  12. % ---|Subject
  13. % |---pre/post/postN folders
  14. % required|--- roi [dicom folder] + (Horos roi *.csv file)
  15. % required|--- tslip [dicom folderS]
  16. % optional|--- Control [dicom folderS] if opp. tag (MT cancel)
  17. % optional|--- M0 [dicom folder] optional
  18. %
  19. % use ExportRoi Plugin from:
  20. % https://horosproject.org/horos-content/plugins/horos/ExportROIs/
  21. %
  22. %% ========================================================================
  23. clear all
  24. clc
  25. tic
  26. start_directory=pwd;
  27. % SUBJECTS list
  28. list = dir3();
  29. if exist('progress.mat','file')
  30. load('progress.mat')
  31. if ii>numel(list)
  32. disp('All data processed!');
  33. return
  34. end
  35. else
  36. %% Define parameters
  37. %--------------------------------------------------------------------------
  38. param.acq_type = 'bright'; % bright (NonSelect+Select); dark (Select)
  39. %param.acq_dim = '2d'; % 2d (single T-SLIP series with multiple TI)
  40. param.acq_dim = '3d'; % 3d (every TI separate series)
  41. %param.TI = [1000, 500];
  42. param.dicomScale = true; % MUST BE ON
  43. param.perVoxelCalc = true; % more prone to error
  44. param.T1 = 2000; % fixed CSF T1 for bi-component fit:
  45. % Blood use 1500, CSF use 3000
  46. param.registration = 'all'; % rigid body registration to M0:
  47. % extreme (myocardium)
  48. % all all images to M0
  49. % auto automatic
  50. % off
  51. %------acquisition with fixed RO-------------------------------------------
  52. param.fixedRO = false; % BBIRprep WIP1
  53. %param.bpm = 70; % heart rate
  54. %--------------------------------------------------------------------------
  55. param.filter_median3D = true; % for 3D volume median filter across slices
  56. param.filter_median2D = true; % additional median for slice of interest
  57. param.filter_sd = true; % doubleSD window for per ROI average
  58. param.noiseM0 = false; % dont normalize to noise
  59. param.absValue = false; % subtraction as absolute value
  60. param.nullPointFilter = [false,750];% remove short TI [bool, filter]
  61. param.filter_lowpass = 'lowPass'; % 'lowPass' 'movinAver' 'off'
  62. param.fitplot = {'bi','gm','biC'}; % 'gkm','gm', 'gmf', 'gs', 'bi' list them in cell
  63. %--------------------------------------------------------------------------
  64. % average across slices in 3D volume ONLY FOR LARGE PERFUSION VOLUME
  65. param.averageSlices = false;
  66. %--------------------------------------------------------------------------
  67. % to print TEs on colormap, use "other" for SeriesID
  68. param.dataType = 'regular';
  69. % use false for NIH (Arial font) and true (latex) for publications
  70. param.latex = true;
  71. %--------------------------------------------------------------------------
  72. % colormaps
  73. % varibles with two values 1 - plot/dont plot; 2 - zoom to roi / full FOV
  74. param.visible = false; % dont show figures, plot silently
  75. param.allslices = false; % if 3D colormaps for all slices
  76. param.paleteview = [false,false]; % does all TIs
  77. param.subtractionMap = [false,false]; % abs(ON-OFF)
  78. param.montageALL = [false,false]; % grayscale: ON, OFF, Control
  79. param.sir2Dcmap = [false,true]; % 2D SIR
  80. param.sir2DcmapFull = false; % to overlay entire FOV
  81. param.contrastNorm = true; % enchance contrast, not true Signal
  82. %--------------------------------------------------------------------------
  83. param.SIRLim = 100; %default limit for plots
  84. param.SIRClim = 100; %default limit for colormaps
  85. param.TILim = 5000; %custom x axis limits
  86. %--------------------------------------------------------------------------
  87. % only for advanced user, keep these as is
  88. param.nonAlternate = false; % if control is acquired sep.
  89. param.advancedGKM=false; % advanced GKM Fit
  90. % Check parameters
  91. param = tslipParamCheck(param);
  92. if isfield(param,'TI')
  93. param.TI0=param.TI; % for 2D
  94. end
  95. %% PROCESSING
  96. %==========================================================================
  97. % structure with results: appended at each subject
  98. ResultM = [];
  99. ResultP = [];
  100. ii=1;
  101. jj=1;
  102. end
  103. %************************************************************ LOOP: SUBJECT
  104. for i=ii:numel(list)
  105. cd(list(i,1).name)
  106. % GROUP/CATEGORY list (such as activity/pre-post/etc)
  107. list2 = dir3();
  108. %**************************************************LOOP: GROUP/CATEGORY
  109. for j=jj:numel(list2)
  110. if jj==1
  111. RM=[];
  112. RP=[];
  113. end
  114. % Subject/Study info
  115. Subject.ID = list(i,1).name;
  116. Subject.study = list2(j,1).name;
  117. q=1; % study results index
  118. cd(list2(j,1).name)
  119. %----------------------------------------------------- START: read data
  120. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start: read ROI
  121. cd roi
  122. csv=dir('*.csv');
  123. fname = [list(i,1).name,' ',list2(j,1).name,];
  124. ROI = horos2matlabTSLIP(csv,fname,true,param);
  125. % Find the indices of all 1s in the array create combined Full
  126. ROI.maskF = sum(~isnan(ROI.maskIm), 3) > 0;
  127. [row, col] = find(ROI.maskF == 1);
  128. % Find the minimum and maximum row and column indices
  129. n=10; %padding
  130. ROI.mtop = max(min(row) - n, 1);
  131. ROI.mbottom = min(max(row) + n, size(ROI.maskF, 1));
  132. ROI.mleft = max(min(col) - n, 1);
  133. ROI.mright = min(max(col) + n, size(ROI.maskF, 2));
  134. cd .. % out of 'roi'
  135. % do MICO for MPRAGE or T1w (MPRAGE is priority)
  136. if isfolder('MPRAGE')
  137. cd 'MPRAGE'
  138. MPRAGE2FASE('MPRAGE','FASE2D')
  139. seriesPath=fullfile(pwd,'Image4Segmentation');
  140. evalc('R = aslMICO(seriesPath, param, true);');
  141. if ~isempty(R)
  142. ROI = mergeASLroi(ROI, R);
  143. end
  144. cd ..
  145. elseif ~isfolder('MPRAGE') && isfolder('T1w')
  146. seriesPath=fullfile(pwd,'T1w');
  147. evalc('R = aslMICO(seriesPath, param, true);');
  148. if ~isempty(R)
  149. ROI = mergeASLroi(ROI, R);
  150. end
  151. end
  152. clearvars csv fname n row col
  153. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End: read ROI
  154. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start: read M0
  155. if exist('M0','dir')
  156. [M0,VM0]=readTslip('M0',ROI,param);
  157. if ~isempty(VM0) && strcmp(param.acq_dim,'3d') %only created for 3d
  158. V.M0 = VM0.On;
  159. end
  160. if isempty(VM0) && strcmp(param.acq_dim,'2d') %only created for 3d
  161. M0=M0(:,:,1);
  162. end
  163. % M0 should only have single series
  164. if isfield(M0,'Ctrl') && isfield(M0,'Ctrl_roi') ...
  165. && ~isempty([M0.Ctrl]) && ~isempty(Ctrl_roi)
  166. M0.On = M0.Ctrl;
  167. M0.On_roi = M0.Ctrl_roi;
  168. M0=rmfield(M0,'Ctrl');
  169. M0=rmfield(M0,'Ctrl_roi');
  170. end
  171. clearvars VM0
  172. end
  173. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End: read M0
  174. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start: read CONTROL
  175. if exist('Control','dir')
  176. [Control,VC]=readTslip('control',ROI,param);
  177. if ~isempty(VC)&& strcmp(param.acq_dim,'3d') %only created for 3d
  178. V.Ctrl=VC.On;
  179. end
  180. % control should only have ON series
  181. if isfield(Control,'Ctrl') && isfield(Control,'Ctrl_roi')
  182. Control=rmfield(Control,'Ctrl');
  183. Control=rmfield(Control,'Ctrl_roi');
  184. end
  185. clearvars VC
  186. end
  187. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End: read Control
  188. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start: read TSLIP
  189. if exist('tslip','dir')
  190. [TSlip,VT,param]=readTslip('tslip',ROI,param);
  191. if ~isempty(VT)&& strcmp(param.acq_dim,'3d') %only created for 3d
  192. V.On=VT.On;
  193. if isfield(VT,'Ctrl')
  194. V.Ctrl=VT.Ctrl;
  195. end
  196. if ~isfield(V,'M0') && strcmp(param.acq_type,'bright') && ...
  197. strcmp(param.acq_dim,'3d') && ~isfield(VT,'Ctrl')
  198. V.M0 = V.Ctrl(:,:,:,end);
  199. param.nonAlternate=true;
  200. elseif ~isfield(V,'M0') && strcmp(param.acq_type,'dark') && ...
  201. strcmp(param.acq_dim,'3d') && ~isfield(VT,'Ctrl')
  202. V.M0 = V.Ctrl;
  203. param.nonAlternate=true;
  204. elseif ~isfield(V,'M0') && strcmp(param.acq_type,'bright') && ...
  205. strcmp(param.acq_dim,'3d')
  206. V.M0 = VT.Ctrl(:,:,:,end);
  207. elseif ~isfield(V,'M0') && strcmp(param.acq_type,'dark') && ...
  208. strcmp(param.acq_dim,'3d')
  209. V.M0 = VT.Ctrl;
  210. end
  211. end
  212. clearvars VT
  213. else
  214. error('Data should have tslip folder');
  215. end
  216. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End: read TSLIP
  217. %------------------------------------------------------- END: read data
  218. nTIs=numel(TSlip);
  219. %------------------------------------------------ START: ararys for SIR
  220. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start: denominator
  221. if exist('M0','var')
  222. A.M0=TslipStuct2Array(M0,'On',param.dicomScale);
  223. m0=squeeze(TslipStuct2Array(M0,'On_roi',...
  224. param.dicomScale));
  225. elseif ~exist('M0','var') && strcmp(param.acq_dim,'3d') ...
  226. && ~param.nonAlternate
  227. A.M0=repmat(TslipStuct2Array(TSlip(end),'Ctrl',param.dicomScale),[1,1,nTIs]);
  228. m0=squeeze(TslipStuct2Array(TSlip(end),'Ctrl_roi',...
  229. param.dicomScale));
  230. elseif ~exist('M0','var') && strcmp(param.acq_dim,'3d') ...
  231. && param.nonAlternate
  232. A.M0=repmat(TslipStuct2Array(Control(end),'On',param.dicomScale),[1,1,nTIs]);
  233. m0=squeeze(TslipStuct2Array(TSlip(end),'On_roi',...
  234. param.dicomScale));
  235. elseif ~exist('M0','var') && strcmp(param.acq_dim,'2d')
  236. A.M0=repmat(TslipStuct2Array(Control(end),'On',param.dicomScale),[1,1,nTIs]);
  237. m0=squeeze(TslipStuct2Array(TSlip(end),'On_roi',...
  238. param.dicomScale));
  239. end
  240. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End: denominator
  241. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start: On
  242. A.On=TslipStuct2Array(TSlip,'On',param.dicomScale);
  243. on=squeeze(TslipStuct2Array(TSlip,'On_roi',param.dicomScale));
  244. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End: On
  245. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start: Control
  246. if exist('Control','var')
  247. A.Ctrl=TslipStuct2Array(Control,'On',param.dicomScale);
  248. ctrl=squeeze(TslipStuct2Array(Control,'On_roi',param.dicomScale));
  249. else
  250. A.Ctrl=TslipStuct2Array(TSlip,'Ctrl',param.dicomScale);
  251. ctrl=squeeze(TslipStuct2Array(TSlip,'Ctrl_roi',...
  252. param.dicomScale));
  253. end
  254. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End: Control
  255. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start: check m0
  256. if size(m0,2)~=size(on,2)
  257. m0=repmat(m0,[1,size(on,2)]);
  258. end
  259. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End: check m0
  260. %-------------------------------------------------- END: ararys for SIR
  261. %%-------------------------------------check if pre-null point to be removed
  262. % check dims of M0 and m0 cause sometimes they are acquired seperat;y
  263. % with less dT
  264. if size(A.M0,3)>1 && size(A.M0,3) ~= size(A.On,3)
  265. A.M0=A.M0(:,:,1);
  266. end
  267. if min(size(m0))>1
  268. if size(m0, 2) > 1 && size(m0,2) ~= size(on,2)
  269. m0=m0(:,1);
  270. end
  271. else
  272. if size(m0, 1) > 1 && size(m0,1) ~= size(on,1)
  273. m0=m0(1);
  274. end
  275. end
  276. if param.nullPointFilter(1)
  277. % Get TI values from the structure and find indices below the threshold
  278. TI_values = [TSlip.TI];
  279. idx = TI_values < param.nullPointFilter(2); % Logical indexing is more efficient than `find`
  280. % Conditional checks before modifying arrays to avoid errors
  281. if exist('Control','var')
  282. Control(idx) = [];
  283. end
  284. if exist('M0', 'var') && size(M0, 2) > 1 && size(M0, 2)== size(TSlip, 2)
  285. M0(idx) = [];
  286. end
  287. % Remove entries based on identified indices
  288. TSlip(idx) = [];
  289. if min(size(m0))>1
  290. if size(m0, 2) > 1 && size(m0,2) == size(on,2)
  291. m0(:, idx) = [];
  292. else
  293. m0=m0(:,1);
  294. end
  295. elseif size(ROI.name,1)>1 && size(m0,2) == 1
  296. else
  297. if size(m0, 1) > 1 && size(m0,1) == size(on,1)
  298. m0(idx) = [];
  299. else
  300. m0=m0(1);
  301. end
  302. end
  303. if size(size(on))<2
  304. on(idx) = [];
  305. ctrl(idx) = [];
  306. else
  307. on(:, idx) = [];
  308. ctrl(:, idx) = [];
  309. end
  310. if isfield(A, 'M0') && size(A.M0,3)==size(A.On,3)
  311. A.M0(:, :, idx) = [];
  312. else
  313. end
  314. % Update fields within structure A
  315. A.On(:, :, idx) = [];
  316. A.Ctrl(:, :, idx) = [];
  317. % Check acquisition dimension and update variables accordingly
  318. if strcmp(param.acq_dim, '3d')
  319. V.On(:, :, :, idx) = [];
  320. V.Ctrl(:, :, :, idx) = [];
  321. if isfield(V, 'M0') && size(V.M0, 4) > 1
  322. V.M0(:, :, :, idx) = [];
  323. end
  324. elseif strcmp(param.acq_dim, '2d')
  325. param.TI(1) = TI_values(1);
  326. end
  327. end
  328. nTIs=max(size([TSlip.TI]));
  329. clearvars idx TI_values
  330. %%-------------------------------------------------------------------------
  331. if ~strcmpi(param.registration,'off')
  332. A=ASL_imReg(A, param);
  333. end
  334. %-------------------------------------------------- START: get noise
  335. %masks for colormaps
  336. if strcmp(param.acq_dim,'3d') && ~isempty(V)
  337. ROI.mask=UTEsMask(mat2gray(max(V.Ctrl,[],[3,4])),0.02);
  338. if param.noiseM0
  339. ROI.noiseLevel = std(V.On(V.On.*abs(ROI.mask-1) ~= 0), 0,"all", "omitnan");
  340. temp = ones(size(V.On));
  341. temp(abs(V.On-V.Ctrl) < ROI.noiseLevel/sqrt(2)) = NaN;
  342. ROI.Noise=temp.*ROI.mask;
  343. end
  344. else
  345. ROI.mask=UTEsMask(mat2gray(max(A.Ctrl,[],[3,4])),0.02);
  346. if param.noiseM0
  347. ROI.noiseLevel = std(A.On(A.On.*abs(ROI.mask-1) ~= 0),0, "all", "omitnan");
  348. temp = ones(size(A.On));
  349. temp(abs(A.On-A.Ctrl) < ROI.noiseLevel/sqrt(2)) = NaN;
  350. ROI.Noise=temp.*ROI.mask;
  351. end
  352. end
  353. % mean recalcs with Noise mask
  354. if param.noiseM0
  355. on=squeeze(mean(permute(repmat(A.On.*ROI.Noise,...
  356. [1,1,1,size(ROI.maskIm,3)]),[1,2,4,3]).*repmat...
  357. (ROI.maskIm,[1,1,1,size(A.On,3)]),[1,2],'omitnan'));
  358. ctrl=squeeze(mean(permute(repmat(A.Ctrl.*ROI.Noise,...
  359. [1,1,1,size(ROI.maskIm,3)]),[1,2,4,3]).*repmat...
  360. (ROI.maskIm,[1,1,1,size(A.Ctrl,3)]),[1,2],'omitnan'));
  361. m0=squeeze(mean(permute(repmat(A.M0.*ROI.Noise,...
  362. [1,1,1,size(ROI.maskIm,3)]),[1,2,4,3]).*repmat...
  363. (ROI.maskIm,[1,1,1,size(A.M0,3)]),[1,2],'omitnan'));
  364. on(isnan(on))=0;
  365. ctrl(isnan(ctrl))=0;
  366. m0(isnan(m0))=0;
  367. on(isinf(on))=0;
  368. ctrl(isinf(ctrl))=0;
  369. m0(isinf(m0))=0;
  370. end
  371. clearvars temp
  372. %-------------------------------------------------- END: get noise
  373. %------------------------------------------------- START: calculate SIR
  374. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start: full array
  375. if strcmp(param.acq_dim,'3d') && ~isempty(V)
  376. tmpOn = V.On;
  377. tmpCtrl = V.Ctrl;
  378. tmpM0 = V.M0;
  379. if param.noiseM0
  380. tmpM0=tmpM0.*ROI.Noise;
  381. end
  382. if param.filter_median3D
  383. tmpOn = arrayfun(@(i) medfilt3(tmpOn(:,:,:,i)), ...
  384. 1:size(tmpOn,4), 'UniformOutput', false);
  385. tmpOn = cat(4, tmpOn{:});
  386. tmpCtrl = arrayfun(@(i) medfilt3(tmpCtrl(:,:,:,i)), ...
  387. 1:size(tmpCtrl,4), 'UniformOutput', false);
  388. tmpCtrl = cat(4, tmpCtrl{:});
  389. tmpM0 = arrayfun(@(i) medfilt3(tmpM0(:,:,:,i)), ...
  390. 1:size(tmpM0,4), 'UniformOutput', false);
  391. tmpM0 = cat(4, tmpM0{:});
  392. end
  393. if param.absValue
  394. V.SUBT=abs(tmpOn-tmpCtrl);
  395. elseif ~param.absValue && strcmp(param.acq_type,'bright')
  396. V.SUBT=tmpOn-tmpCtrl;
  397. V.SUBT(V.SUBT<0)=0;
  398. else
  399. V.SUBT=tmpCtrl-tmpOn;
  400. V.SUBT(V.SUBT<0)=0;
  401. end
  402. if param.noiseM0
  403. V.SUBT=V.SUBT.*ROI.Noise;
  404. end
  405. V.SIR=V.SUBT./tmpM0;
  406. V.SUBT(isinf(V.SUBT))=NaN;
  407. V.SIR(isinf(V.SIR))=NaN;
  408. clearvars tmp tmpOn tmpCtrl tmpM0
  409. end
  410. if param.filter_median2D
  411. % Preallocate arrays with the same size as A.On
  412. tmpOn = zeros(size(A.On));
  413. tmpCtrl = tmpOn;
  414. % Check if A.M0 has multiple slices and preallocate accordingly
  415. if size(A.M0, 3) > 1
  416. tmpM0 = zeros(size(A.M0));
  417. end
  418. % Apply median filtering across all time points (nTIs)
  419. for t = 1:nTIs
  420. tmpOn(:, :, t) = medfilt2(A.On(:, :, t));
  421. tmpCtrl(:, :, t) = medfilt2(A.Ctrl(:, :, t));
  422. if size(A.M0, 3) > 1
  423. tmpM0(:, :, t) = medfilt2(A.M0(:, :, t));
  424. end
  425. end
  426. % Handle the case where A.M0 has only one slice
  427. if size(A.M0, 3) == 1
  428. tmpM0 = medfilt2(A.M0);
  429. end
  430. else
  431. tmpOn=A.On;
  432. tmpCtrl=A.Ctrl;
  433. tmpM0=A.M0;
  434. end
  435. if param.absValue
  436. A.SUBT=abs(tmpOn-tmpCtrl);
  437. elseif ~param.absValue && strcmp(param.acq_type,'bright')
  438. A.SUBT=tmpOn-tmpCtrl;
  439. A.SUBT(A.SUBT<0)=0;
  440. else
  441. A.SUBT=tmpCtrl-tmpOn;
  442. A.SUBT(A.SUBT<0)=0;
  443. end
  444. if param.noiseM0
  445. A.SUBT = A.SUBT.*ROI.Noise;
  446. end
  447. A.SIR=A.SUBT./tmpM0;
  448. A.SUBT(isinf(A.SUBT))=NaN;
  449. A.SIR(isinf(A.SIR))=NaN;
  450. clearvars tmpOn tmpCtrl tmpM0 t
  451. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End: full array
  452. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start: roi quantification
  453. if param.absValue
  454. SIR.mean=abs(on-ctrl)./m0;
  455. elseif ~param.absValue && strcmp(param.acq_type,'bright')
  456. temp=(on-ctrl)./m0;
  457. temp(temp<0)=0;
  458. SIR.mean=temp;
  459. else
  460. temp=(ctrl-on)./m0;
  461. temp(temp<0)=0;
  462. SIR.mean=temp;
  463. end
  464. clearvars on ctrl m0 tmp
  465. if param.perVoxelCalc
  466. pp=[];
  467. for m=1:size(ROI.maskIm,3)
  468. tmp=A.SIR.*repmat(ROI.maskIm(:,:,m),[1,1,nTIs]);
  469. tmp=(mean(tmp,[1,2],'omitnan'));
  470. pp=cat(1,pp,tmp);
  471. end
  472. SIR.pp=squeeze(pp);
  473. end
  474. clearvars tmp pp m
  475. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End: roi quantification
  476. %--------------------------------------------------- END: calculate SIR
  477. %----------------------------------------------------------- START: fit
  478. if param.fixedRO
  479. if param.perVoxelCalc
  480. [rM,rP]=aslFixedRO(SIR,[TSlip.TI],Subject,ROI,param,A.M0(:,:,1));
  481. else
  482. rM=aslFixedRO(SIR,[TSlip.TI],Subject,ROI,param,A.M0(:,:,1));
  483. end
  484. else
  485. if param.perVoxelCalc
  486. [rM,rP]=aslFit(SIR,[TSlip.TI],Subject,ROI,param,A.M0(:,:,1));
  487. else
  488. rM=aslFit(SIR,[TSlip.TI],Subject,ROI,param,A.M0(:,:,1));
  489. end
  490. end
  491. %------------------------------------------------------------- END: fit
  492. cd ..
  493. %----------------------------------------------------- START: colormaps
  494. mkdir('colormaps')
  495. cd('colormaps')
  496. if strcmp(param.acq_dim, '3d') && ~isempty(V) && param.allslices
  497. tempSUBT = mat2gray(V.SUBT .* ROI.mask);
  498. slice_indices = 1:size(V.On, 3);
  499. data_source = V;
  500. else
  501. slice_indices = ROI.slice_number;
  502. data_source = A;
  503. end
  504. for s = slice_indices
  505. if strcmp(param.acq_dim, '3d') && ~isempty(V) && param.allslices
  506. B = structfun(@(field) squeeze(field(:,:,s,:)), V,...
  507. 'UniformOutput', false);
  508. B.SUBT = squeeze(tempSUBT(:,:,s,:));
  509. else
  510. B = A;
  511. end
  512. operations = {
  513. 'palette', @paleteCMap, param.paleteview(1);
  514. 'montage', @tslipmontage, param.montageALL(1);
  515. 'subtraction', @(B, ROI, TI, s, param) perfusionCMap(B, ...
  516. ROI, TI, s, param, 'SUBT'), param.subtractionMap(1);
  517. 'SIR', @(B, ROI, TI, s, param) perfusionCMap(B, ROI, TI, ...
  518. s, param, 'SIR'), param.sir2Dcmap(1);
  519. };
  520. for x = 1:size(operations, 1)
  521. if operations{x, 3}
  522. mkdir(operations{x, 1});
  523. cd(operations{x, 1});
  524. operations{x, 2}(B, ROI, [TSlip.TI], s, param);
  525. cd ..;
  526. end
  527. end
  528. clearvars B x operations slice_indices s data_source
  529. end
  530. cd ..
  531. %------------------------------------------------------- END: colormaps
  532. if param.perVoxelCalc
  533. RM=[RM,rM];
  534. RP=[RP,rP];
  535. clearvars rM rP
  536. ii=i;
  537. jj=j+1;
  538. save([start_directory,'/progress.mat'],'ResultM','ResultP',...
  539. 'RM','RP','ii','jj','list','list2','param')
  540. else
  541. RM=[RM,rM];
  542. clearvars rM
  543. ii=i;
  544. jj=j+1;
  545. save([start_directory,'/progress.mat'],'ResultM','RM','ii','jj',...
  546. 'list','list2','param')
  547. end
  548. cd ..
  549. end
  550. %**************************************************LOOP: GROUP/CATEGORY
  551. if param.perVoxelCalc
  552. ResultM=[ResultM,RM];
  553. ResultP=[ResultP,RP];
  554. clearvars RM RP
  555. ii=i+1;
  556. jj=1;
  557. save([start_directory,'/progress.mat'],'ResultM','ResultP','ii','jj',...
  558. 'list','list2','param')
  559. else
  560. ResultM=[ResultM,RM];
  561. clearvars RM
  562. ii=i+1;
  563. jj=1;
  564. save([start_directory,'/progress.mat'],'ResultM','ii','jj',...
  565. 'list','list2','param')
  566. end
  567. cd ..
  568. end
  569. %************************************************************ LOOP: SUBJECT
  570. data_directory=pwd;
  571. folder_results = ['results_', char(datetime('today'), 'yyMMdd')];
  572. mkdir(folder_results);
  573. movePDFs(data_directory, folder_results)
  574. cd(folder_results)
  575. if param.perVoxelCalc
  576. aslResults2XLS(ResultM, 'ResultMean.xlsx',param)
  577. aslResults2XLS(ResultP, 'ResultPP.xlsx',param)
  578. save('results.mat', 'ResultM','ResultP')
  579. else
  580. aslResults2XLS(ResultM, 'ResultMean.xlsx',param)
  581. save('results.mat', 'ResultM')
  582. end
  583. toc

ASL_main.m at commit 3c137e3, under MIT · at the source

Overview

Authors: Vadim Malis1, Hye Na Jung1,2, Yoshiki Kuwatsuru1,3, Won C Bae1, Mitsue Miyazaki1
  1. Department of Radiology, University of California San Diego, La Jolla, CA, USA
  2. Department of Radiology, Korea University Guro Hospital, Seoul, Republic of Korea
  3. Department of Radiology, Juntendo University, Tokyo, Japan
Institutions: University of California San Diego (United States); Korea University Guro Hospital (South Korea); Juntendo University (Japan)
Dates: received 21 January 2026; accepted 16 May 2026; published online 1 June 2026; in print September 2026
Type: Research article · Language: English
License: CC BY-NC
Identifiers: DOI 10.1177/0271678x261455452 · PMID 42219987 · PMCID PMC13272186 · OpenAlex W7163058769
Open access: hybrid, a free copy (OpenAlex)
Status: code verified
Categories: structural MRI / diffusion (modality), human (organism)
Methods: Statistics, fMRI & imaging
Keywords: Aging, cerebrospinal fluid, meningeal transport, neurofluid physiology, Time-SLIP MRI
MeSH: Aging*, Cerebrospinal Fluid*, Dura Mater*, Meninges*, Adult, Aged, Aged, 80 and over, Female, Humans, Magnetic Resonance Imaging, Male, Middle Aged, Young Adult (* major topic)
Topic: Cerebrospinal fluid and hydrocephalus (Cellular and Molecular Neuroscience, Neuroscience), according to OpenAlex
Funding: Canon Medical Systems (35938); NIA NIH HHS (R01 AG087407, R01 AG076692); National Institutes of Health (R01AG076692 and R01AG087407)
Citations: not cited yet (Europe PMC); 35 references in the paper

Abstract

Cerebrospinal fluid (CSF) transport along meningeal pathways contributes to brain fluid homeostasis and is thought to change with aging, yet quantitative, region-resolved measurements across lifespan remain limited. We hypothesized that meningeal CSF transport dynamics exhibit region-specific age associations rather than uniform decline. We applied non-contrast time-spatial labeling inversion pulse (Time-SLIP) MRI combined with a bi-component analytical model to characterize CSF transport dynamics in a healthy, activity-controlled cohort of 64 adults aged 19–86 years. Signal increase ratio time courses were decomposed into a fast Gaussian bulk-displacement and a slower Γ-variate perfusion-like component. Linear mixed-effects models were used to assess regional and age-related effects. Model fits were robust across all participants (R2 = 0.97). CSF transport metrics differed significantly across parasagittal dura subregions and the superior sagittal sinus. Age associations were heterogeneous: the perfusion-like component declined with age in upper parasagittal dura, increased in lower parasagittal regions, and remained relatively stable within the superior sagittal sinus. Additional timing and amplitude parameters exhibited region-specific age trajectories. These findings demonstrate regionally heterogeneous aging effects on meningeal CSF transport dynamics and suggest age-related redistribution rather than uniform decline, providing a noninvasive framework for assessing physiological remodeling of CSF transport with aging.

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

Repository

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

vmalis/TimeSLIP-CSF-transport

License: MIT
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 3c137e3f5ba114855c1a7bbee1ec12c2bd81249e, 21 January 2026
Languages: MATLAB (67), Java (1)
Size: 119 files, 68 scripts
Software Heritage: not archived
Found in: “Data and code availability”
Holds: README, license file, documentation
Not found: CITATION.cff, environment file, tests, continuous integration
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
70 files

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

Tracing map

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

What the map holds:

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

All analysis code used in this study is publicly available at GitHub (https://github.com/vmalis/TimeSLIP-CSF-transport). An anonymized Time-SLIP MRI test dataset supporting the findings of this work is available via Zenodo (https://doi.org/10.5281/zenodo.17982328).

Reproduced under the paper's license (CC BY-NC), 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, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 5 authors, 5 keywords, 13 MeSH terms, 3 funders, 34 references.

Cite

This paper

Malis, V., Jung, H. N., Kuwatsuru, Y., Bae, W. C., & Miyazaki, M. (2026). Meningeal CSF transport varies across parasagittal dura subregions with age in humans. Journal of cerebral blood flow and metabolism : official journal of the International Society of Cerebral Blood Flow and Metabolism, 46(9), 0271678X261455452. https://doi.org/10.1177/0271678x261455452

BibTeX

@article{malis2026meningeal,
author = {Malis, Vadim and Jung, Hye Na and Kuwatsuru, Yoshiki and Bae, Won C and Miyazaki, Mitsue},
title = {{Meningeal CSF transport varies across parasagittal dura subregions with age in humans}},
journal = {Journal of cerebral blood flow and metabolism : official journal of the International Society of Cerebral Blood Flow and Metabolism},
year = {2026},
month = jun,
volume = {46},
number = {9},
pages = {0271678X261455452},
publisher = {SAGE Publications},
issn = {0271-678X},
doi = {10.1177/0271678x261455452},
url = {https://doi.org/10.1177/0271678x261455452},
pmid = {42219987},
pmcid = {PMC13272186}
}

RIS

TY - JOUR
AU - Malis, Vadim
AU - Jung, Hye Na
AU - Kuwatsuru, Yoshiki
AU - Bae, Won C
AU - Miyazaki, Mitsue
TI - Meningeal CSF transport varies across parasagittal dura subregions with age in humans
T2 - Journal of cerebral blood flow and metabolism : official journal of the International Society of Cerebral Blood Flow and Metabolism
J2 - J Cereb Blood Flow Metab
PY - 2026
DA - 2026/06/01
VL - 46
IS - 9
SP - 0271678X261455452
SN - 0271-678X
PB - SAGE Publications
DO - 10.1177/0271678x261455452
UR - https://doi.org/10.1177/0271678x261455452
LA - en
ER -

CSL-JSON

{
"id": "10.1177/0271678x261455452",
"type": "article-journal",
"title": "Meningeal CSF transport varies across parasagittal dura subregions with age in humans",
"container-title": "Journal of cerebral blood flow and metabolism : official journal of the International Society of Cerebral Blood Flow and Metabolism",
"author": [
{
"family": "Malis",
"given": "Vadim"
},
{
"family": "Jung",
"given": "Hye Na"
},
{
"family": "Kuwatsuru",
"given": "Yoshiki"
},
{
"family": "Bae",
"given": "Won C"
},
{
"family": "Miyazaki",
"given": "Mitsue"
}
],
"container-title-short": "J Cereb Blood Flow Metab",
"volume": "46",
"issue": "9",
"page": "0271678X261455452",
"DOI": "10.1177/0271678x261455452",
"PMID": "42219987",
"PMCID": "PMC13272186",
"ISSN": "0271-678X",
"publisher": "SAGE Publications",
"URL": "https://doi.org/10.1177/0271678x261455452",
"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.1002/hbm.70602 [code]
Neuroimaging Correlates of Post-Stroke Pain After Ischemic Stroke: Secondary Analysis of the INSPiRE-TMS Trial.
Journal: Human brain mapping
In common: export_fig, Curve Fitting Toolbox, Optimization Toolbox, 2 other tools
[2] doi:10.1038/s41586-026-10631-3 [code]
A prognostic human brain network for diffuse midline glioma.
Journal: Nature
In common: export_fig, Curve Fitting Toolbox, Optimization Toolbox, 2 other tools
[3] doi:10.1111/ene.70678 [code]
Who Falls After a Stroke? Evidence From a Prospective Stroke Cohort.
Journal: European journal of neurology
In common: export_fig, Curve Fitting Toolbox, Optimization Toolbox, 2 other tools
[4] doi:10.1016/j.celrep.2026.117404 [code]
Action and rest tremor map to distinct networks within the primary motor cortex.
Journal: Cell reports
In common: export_fig, Curve Fitting Toolbox, Optimization Toolbox, 2 other tools
[5] doi:10.1002/ana.78206 [code]
Multimodal Image Guidance in Subthalamic Deep Brain Stimulation for Parkinson's Disease.
Journal: Annals of neurology
In common: export_fig, Curve Fitting Toolbox, Optimization Toolbox, 2 other tools
[6] doi:10.1523/jneurosci.2001-25.2026 [code]
Dynamics of Dentate Gyrus Place Cells and Dentate Spikes during Spatial and Nonspatial Changes in Environments.
Journal: The Journal of neuroscience : the official journal of the Society for Neuroscience
In common: export_fig, Curve Fitting Toolbox, Optimization Toolbox, 2 other tools
[7] doi:10.1038/s41593-026-02357-2 [code]
Experience reorganizes content-specific memory traces in macaques.
Journal: Nature neuroscience
In common: export_fig, Curve Fitting Toolbox, Optimization Toolbox, 2 other tools
[8] doi:10.3390/biomedicines14081670 [code]
Limited Detectability of Network Functional Alterations in a Tauopathy Model Using Mouse Primary Cortical Cultures.
Journal: Biomedicines
In common: export_fig, Curve Fitting Toolbox, Optimization Toolbox, 2 other tools
[9] doi:10.1038/s41467-026-75347-4 [code]
Sleep reveals dynamics integrating and segregating movement and stimulus representations in V1.
Journal: Nature communications
In common: export_fig, Curve Fitting Toolbox, Optimization Toolbox, 2 other tools
[10] doi:10.1016/j.celrep.2026.117646 [code]
Medial entorhinal-hippocampal desynchronization parallels the emergence of memory impairment in a mouse model of Alzheimer's disease pathology.
Journal: Cell reports
In common: export_fig, Curve Fitting Toolbox, Optimization Toolbox, 2 other tools

Contribute

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

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

Request its removal

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

Discussion, reproductions, activity

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

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

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