Scheduled service maintenance on November 22


On Friday, November 22, 2024, between 06:00 CET and 18:00 CET, GIN services will undergo planned maintenance. Extended service interruptions should be expected. We will try to keep downtimes to a minimum, but recommend that users avoid critical tasks, large data uploads, or DOI requests during this time.

We apologize for any inconvenience.

pRF_FitModel_LISA_cv_neggain.m 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. function pRF_FitModel_LISA_cv(Monkey,Session,Slices,HRF,numWorkers,modeltype,cv,resfld)
  2. % This is the script that runs the pRF fit
  3. % it should be compiled and called from run_CompiledMatlab_LISA.sh
  4. % This means it cannot use 'addpath', instead toolboxes or required
  5. % function should be added when it is compiled usin -a /toolbox etc.
  6. % compile on LISA with:
  7. % module load matlab
  8. % echo "mcc -m $HOME/PRF/Code/pRF_FitModel_LISA.m -a $HOME/PRF/Code/HRF -a $HOME/PRF/Code/analyzePRF -a $HOME/PRF/Code/NIfTI" | matlab -nodisplay
  9. % module unload matlab
  10. % The uncompiled version of this function should be in
  11. % $HOME/PRF/Code
  12. % this compiled function will be running from:
  13. % "$TMPDIR"/PRF
  14. % Data will be in
  15. % "$TMPDIR"/PRF
  16. % MAKE SURE TO:
  17. % save results in "$TMPDIR"/PRF/Results/%MONKEY/$SESS/$SLICES
  18. % fits the prf model to voxels
  19. % <Monkey> string, no caps
  20. % <Session> string YYYYMMDD
  21. % <Slices> range of slices x:xx
  22. % <HRF> HRF function to use (won't be used if <modeltype> is an ephys variant
  23. % <numWorkers> can be used to cap the # of parallel processes, leave [] to
  24. % maximize
  25. % <modeltype> specifies what kind of model to fit ('css','css_ephys','linear','linear_ephys')
  26. % <cv> type of crossvalidation (0,1,2)
  27. DEBUG=false;
  28. if DEBUG
  29. Monkey = 'M02'; %#ok<*UNRCH>
  30. Session = 'AllSessions-avg-cv';
  31. Slices = 01:5;
  32. HRF = 'HRF_monkey';
  33. numWorkers = [];
  34. modeltype = 'css';
  35. cv = 0;
  36. fprintf('RUNNING IN DEBUG MODE! CHANGE THIS FLAG FOR PRODUCTION!\n');
  37. end
  38. %% These are fixed for this configuration =================================
  39. TR=2.5;
  40. if strcmp(Monkey, 'M02') && strcmp(Session,'20160721')
  41. TR=3;
  42. end
  43. doUpsample=true;
  44. mlroot = pwd; % this is $TMPDIR/PRF when running it on LISA (fast disks)
  45. %% Prep & Load ============================================================
  46. % change characters to numbers
  47. if ischar(Slices); slices = eval(Slices); else slices = Slices; end
  48. if ischar(numWorkers); numWorkers = eval(numWorkers); end
  49. if ischar(cv); cv = eval(cv); end
  50. SliceLabel = [num2str(slices(1),'%02d') '-' num2str(slices(end),'%02d')];
  51. % Notification of the fact that we're starting
  52. disp(['Starting script for job ' Monkey ', ' Session ', Slices ' Slices])
  53. % Link to the brain mask
  54. if strcmp(Monkey, 'M01')
  55. BrainMask_file = [mlroot '/T1_to_func_brainmask_zcrop.nii'];
  56. elseif strcmp(Monkey, 'M02')
  57. BrainMask_file = [mlroot '/HiRes_to_T1_mean.nii_shadowreg_M02_brainmask.nii'];
  58. end
  59. % make outputfolder
  60. % result_folder = [mlroot '/Results/' Monkey '/' Session '/Slices_' SliceLabel];
  61. result_folder = [mlroot '/Results/' Monkey '/' resfld '/Slices_' SliceLabel];
  62. if ~exist(result_folder,'dir')
  63. mkdir(result_folder);
  64. end
  65. fprintf(['Saving results in: ' result_folder]);
  66. %% MODEL PRFs /SESSION ====================================================
  67. % Do the pRF model fit on a session/day basis. Concatenate runs.
  68. % Number of parallel processes might need to be restricted beause of memory
  69. % limitations. Set numWorkers at the start of this function.
  70. % Modeling everything together may be overkill (size wise).
  71. % get the brain mask ----
  72. fprintf('\nUnpacking BrainMask');
  73. mask_nii=load_nii(BrainMask_file);%load_nii(uz_nii{1});
  74. fprintf(' ...done\n');
  75. fprintf(['=== Fitting pRF model for ses-' Session ' ===\n']);
  76. fprintf('Loading data...\n');
  77. load(fullfile(mlroot,Session)); %#ok<*LOAD>
  78. % The crucial variables in thes files are:
  79. % stim >> a structure with fields norm and inv
  80. % norm >> stimulus in normal order. cell array.
  81. % inv >> stimulus in inverse order. cell array.
  82. % sess_wmeanBOLD >> weighted average BOLD response
  83. % >> 4d array of epi-volumes in time (4th dimension)
  84. % sess_wmeanBOLD >> weighted average BOLD response for inverse stimuli
  85. % >> 4d array of epi-volumes in time (4th dimension)
  86. % concatenate -----
  87. stimulus={};fmri_data={};
  88. fprintf('Concatenating stimuli and volumes...\n');
  89. if iscell(sess_wmeanBOLD)
  90. for RUNNR = 1:length(sess_wmeanBOLD)
  91. fmri_data{(RUNNR-1)+RUNNR}=sess_wmeanBOLD{RUNNR}(:,:,slices,:); %#ok<*IDISVAR,*NODEF>
  92. stimulus{(RUNNR-1)+RUNNR}=[];
  93. for voln = 1:size(stim.norm{RUNNR},2)
  94. stimulus{(RUNNR-1)+RUNNR} = cat(3, stimulus{(RUNNR-1)+RUNNR}, stim.norm{RUNNR}{voln}); %#ok<*AGROW>
  95. end
  96. if exist('sess_wmeanBOLD_inv') && ~isempty(sess_wmeanBOLD_inv{RUNNR}) %#ok<*EXIST>
  97. fmri_data{RUNNR+RUNNR}=sess_wmeanBOLD_inv{RUNNR}(:,:,slices,:);
  98. stimulus{RUNNR+RUNNR}=[];
  99. for voln = 1:size(stim.inv{RUNNR},2)
  100. stimulus{RUNNR+RUNNR} = cat(3, stimulus{RUNNR+RUNNR}, stim.inv{RUNNR}{voln});
  101. end
  102. end
  103. end
  104. else % for the xval = 0 data
  105. fmri_data{1}=sess_wmeanBOLD(:,:,slices,:);
  106. stimulus{1}=[];
  107. for voln = 1:size(stim.norm,2)
  108. stimulus{1} = cat(3, stimulus{1}, stim.norm{voln}); %#ok<*AGROW>
  109. end
  110. if exist('sess_wmeanBOLD_inv') && ~isempty(sess_wmeanBOLD_inv) %#ok<*EXIST>
  111. fmri_data{2}=sess_wmeanBOLD_inv(:,:,slices,:);
  112. stimulus{2}=[];
  113. for voln = 1:size(stim.inv,2)
  114. stimulus{2} = cat(3, stimulus{2}, stim.inv{voln});
  115. end
  116. end
  117. end
  118. % clear empty cell for non-existing inverse stimuli
  119. if length(fmri_data)>1 && isempty(fmri_data{2})
  120. fmri_data(2)=[];
  121. stimulus(2)=[];
  122. end
  123. % fit pRF -----
  124. % get indices to mask voxels > 0
  125. options.vxs = find(mask_nii.img(:,:,slices)>0);
  126. options.display = 'final';
  127. if strcmp(HRF,'HRF_monkey')
  128. load(fullfile(mlroot,'HRF',HRF),'customHRF_rs','customHRF_rsus');
  129. if doUpsample
  130. options.hrf = customHRF_rsus;
  131. else
  132. options.hrf = customHRF_rs;
  133. end
  134. end
  135. % set crossvalidation option
  136. options.xvalmode = cv; % two-fold cross-validation (first half of runs; second half of runs)
  137. % no denoising for average BOLD traces
  138. options.wantglmdenoise = 0;
  139. % set typicalgain to a lower value because it's %BOLD change now and not raw data
  140. options.typicalgain = 0.25;
  141. % allow negative gain factors
  142. options.allowneggain = true;
  143. % start a parallel pool of workers
  144. if ~isempty(numWorkers)
  145. parpool(numWorkers);
  146. else
  147. % if numWorkers = []
  148. % don't predefine the number of workers
  149. % let it take the max available when running
  150. end
  151. % run analyzePRF tool
  152. if doUpsample % tr = TR/2
  153. result = analyzePRF_modeltype(stimulus,fmri_data,TR/2,options,modeltype);
  154. else
  155. result = analyzePRF_modeltype(stimulus,fmri_data,TR,options,modeltype);
  156. end
  157. load(fullfile(mlroot,[Monkey '_refhdr']));
  158. result.hdr_ref = ref_hdr;
  159. % save the result ----
  160. fprintf('\nSaving the result: ');
  161. save(fullfile(result_folder,['pRF_Sess-' Session]),...
  162. 'result','-v7.3');
  163. % also save as nifti files
  164. % angle ---
  165. fprintf('Angles ');
  166. nii = make_nii(result.ang,[1 1 1],[],32,...
  167. 'pRF fit: Angles (deg)');
  168. nii.hdr.hist = result.hdr_ref.hist;
  169. save_nii(nii, fullfile(result_folder, [Session '_ang.nii']));
  170. gzip(fullfile(result_folder, [Session '_ang.nii']));
  171. delete(fullfile(result_folder, [Session '_ang.nii']));
  172. % ecc ---
  173. fprintf('Ecc ');
  174. nii = make_nii(result.ecc,[1 1 1],[],32,...
  175. 'pRF fit: Eccentricity (pix)');
  176. nii.hdr.hist = result.hdr_ref.hist;
  177. save_nii(nii, fullfile(result_folder, [Session '_ecc.nii']));
  178. gzip(fullfile(result_folder, [Session '_ecc.nii']));
  179. delete(fullfile(result_folder, [Session '_ecc.nii']));
  180. % size ---
  181. fprintf('Size ');
  182. nii = make_nii(result.rfsize,[1 1 1],[],32,...
  183. 'pRF fit: RF size (pix)');
  184. nii.hdr.hist = result.hdr_ref.hist;
  185. save_nii(nii, fullfile(result_folder, [Session '_rfsize.nii']));
  186. gzip(fullfile(result_folder, [Session '_rfsize.nii']));
  187. delete(fullfile(result_folder, [Session '_rfsize.nii']));
  188. % R^2 Goodness of fit ---
  189. fprintf('R2 ');
  190. nii = make_nii(result.R2,[1 1 1],[],32,...
  191. 'pRF fit: R2 Goodnes off fit');
  192. nii.hdr.hist = result.hdr_ref.hist;
  193. save_nii(nii, fullfile(result_folder, [Session '_R2.nii']));
  194. gzip(fullfile(result_folder, [Session '_R2.nii']));
  195. delete(fullfile(result_folder, [Session '_R2.nii']));
  196. cd ..
  197. fprintf('>> Done!\n');