pRF_CreateParallel4LISA_worker_ephys.m 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. function pRF_CreateParallel4LISA_worker_ephys(...
  2. parallel_fun, joblist, parallel_fun_dir, job_name)
  3. % This function serves to create parallel Jobs for a given script
  4. % to parallalise it for a given list of jobs.
  5. %
  6. % Therefore, it creates executable sh-scripts, which execute each single
  7. % job, as well as one script which passes all the single job scripts to
  8. % the cluster computer. (LISA @ SurfSara).
  9. %
  10. % This version requsts 600MB free on the host machine. If your job does not
  11. % require free memory (also matlab already needs quite a bit), use
  12. % create_parallel_nomem.m.
  13. %
  14. % IMPORTANT: The function runs on linux: all pathes must be linux style
  15. %
  16. % PARAMETERS
  17. % parallel_fun: name of the function (e.g. 'example_function', NOT
  18. % 'example_script.m', 'example_function()', etc.). This
  19. % function must take exactly 1 argument as input. For an
  20. % example, see parallel_example_fun.m;
  21. %
  22. % joblist: a structure with information on what jobs to create, with how
  23. % many parallel processes, and how to split volumes in
  24. % slice-chunks
  25. %
  26. % parallel_fun_dir: path to parallel_fun, will be used to add to the
  27. % matlab path on the remote machines
  28. %
  29. % OPTIONAL
  30. % job_name: string to identify your job. Subdirectories with this name will
  31. % be created inside the specified batch directory and the log
  32. % directory, so that multiple jobs can be executed at the same time.
  33. % If no jobname is given, the name of prallel_fun together with the
  34. % current date and time will be used as job name.
  35. %% basic input checks -----------------------------------------------------
  36. % check if parallel_fun ends with .m or ()
  37. if length(parallel_fun) >= 2 && (strcmp(parallel_fun(end-1:end), '.m') || ...
  38. strcmp(parallel_fun(end-1:end), '()'))
  39. parallel_fun = parallel_fun(1:end-2);
  40. end
  41. %% set parameters ---------------------------------------------------------
  42. % default name for jobs
  43. if ~exist('job_name', 'var')
  44. job_name = [parallel_fun '_' datestr(now, 'yyyymmddTHHMMSS')];
  45. end
  46. % project_dir on LISA
  47. project_dir = '/home/pcklink/PRF'; % must be the ABSOLUTE path
  48. % log dir on LISA
  49. log_file_dir = [project_dir '/Logs/']; % add jobname
  50. % set local log folder
  51. log_file_dir_local = [pwd '/Logs/']; % add jobname
  52. % job files will be locally written to:
  53. cd ..
  54. batch_dir = fullfile(pwd, 'Jobs', ['JOBS_' job_name]); % add jobname
  55. %% location of scripts ----------------------------------------------------
  56. % set location of execute_matlab_process.sh
  57. execute_matlab_process_sh = ['$TMPDIR/PRF/BashScripts/'...
  58. 'pRF_run_analyzePRF_LISA_ephys.sh']; % must be ABSOLUTE path
  59. %% PROCESSING STARTS FROM HERE (no more parameters to check) ==============
  60. %% create batch & log folder ----------------------------------------------
  61. disp('Creating batch & log folders')
  62. [success, message] = mkdir(batch_dir);
  63. if ~success
  64. error(['Could not create directory for batch_dir: ' message])
  65. end
  66. if ispc
  67. error('Windows will not work due to path definitions. Run on Linux')
  68. else
  69. [success, message] = mkdir(log_file_dir_local);
  70. if ~success
  71. error(['Could not create directory for log_file_dir_local: ' message])
  72. end
  73. end
  74. %% Check if main batch files already exists -------------------------------
  75. % set initial behaviour, if you want to overwrite sh-files which are there
  76. overwrite_file = 'ask';
  77. disp('Creating batch files')
  78. % check if main sh-file to start all jobs exists
  79. filename_all = sprintf(['send_all_prf-fitting_jobs_' joblist.monkey '.sh']);
  80. fullfilename_all = [batch_dir '/' filename_all];
  81. if exist(fullfilename_all, 'file')
  82. disp(' ')
  83. disp(['File ' fullfilename_all ' already exist.'])
  84. overwrite_file = input('Should it be overwritten? [y, n, a (all)]: ', 's');
  85. if ~(strcmpi(overwrite_file, 'y') || strcmpi(overwrite_file, 'a'))
  86. error(['File ' filename_all ' already exists and should not be '...
  87. 'overwritten. Solve problem and start again.'])
  88. end
  89. delete(fullfilename_all)
  90. end
  91. %% Create the batch files -------------------------------------------------
  92. % The main batch file handles passing the single job batch files to the
  93. display(['Creating main batch file: ' fullfilename_all])
  94. fid_commit_all = fopen(fullfilename_all, 'w');
  95. % ensure that the right shell is used !#/bin/sh
  96. fprintf(fid_commit_all, '#!/bin/bash\n');
  97. % add comment that THIS file submits the stuff to condor
  98. fprintf(fid_commit_all, '#\n');
  99. fprintf(fid_commit_all, ['# This bash-script submits all jobs to the server, '...
  100. 'instead of running them locally.\n']);
  101. fprintf(fid_commit_all, ['# If you want to submit only some jobs to the server,'...
  102. 'simply add a "#" in front of \n' ...
  103. '#the ones you like to ommit and execute the script then.\n']);
  104. fprintf(fid_commit_all, '#\n');
  105. fprintf(fid_commit_all, '\nmkdir -p $HOME/PRF/Logs/slurm\n');
  106. fprintf(fid_commit_all, 'cd $HOME/PRF/Logs/slurm\n');
  107. fprintf(fid_commit_all, 'chmod +x $HOME/PRF/Code/Jobs/*\n\n');
  108. % create all single job batchfiles, and add for each a call in the main
  109. % batch file
  110. for job_ind = 1:length(joblist.sessinc)
  111. for job_ind2 = 1:length(joblist.instances)
  112. %% create batchfile for current job -------------------------------
  113. % create/overwrite file
  114. filename = sprintf('run_job_Ses-%s_%s_%s_%s.sh', joblist.sessions{...
  115. joblist.sessinc(job_ind),1},num2str(job_ind2),job_name,joblist.monkey);
  116. fullfilename = [batch_dir '/' filename];
  117. disp(['Creating Batch file for Job ' num2str(job_ind) '_' num2str(job_ind2) ': ' fullfilename])
  118. if exist(fullfilename, 'file')
  119. if ~strcmpi(overwrite_file, 'a')
  120. disp(' ')
  121. disp(['File ' fullfilename ' already exist.'])
  122. overwrite_file = input('Should it be overwritten? [y, n, a (all)]: ', 's');
  123. if ~(strcmpi(overwrite_file, 'y') || strcmpi(overwrite_file, 'a'))
  124. error(['File ' filename ' already exists and should not be '...
  125. 'overwritten. Solve problem and start again.'])
  126. end
  127. end
  128. delete(fullfilename)
  129. end
  130. % open single subject file
  131. fid_single = fopen(fullfilename , 'w');
  132. % ==== SLURM ====
  133. % ensure that the right shell is used !#/bin/bash
  134. fprintf(fid_single, '#!/bin/bash\n');
  135. % SLURM definitions
  136. fprintf(fid_single, '#SBATCH -N 1 --ntasks-per-node=16\n');
  137. fprintf(fid_single, '#SBATCH -t 05:00:00\n');
  138. fprintf(fid_single, '#SBATCH --mail-type=END\n');
  139. fprintf(fid_single, '#SBATCH --mail-user=p.c.klink@gmail.com\n');
  140. fprintf(fid_single, '\n');
  141. fprintf(fid_single, 'source ~/.bash_profile\n');
  142. fprintf(fid_single, 'source ~/.bashrc\n');
  143. fprintf(fid_single, 'umask u+rwx,g+rwx\n\n');
  144. % information
  145. fprintf(fid_single, 'echo job id $SLURM_JOBID\n');
  146. fprintf(fid_single, 'echo job name $SLURM_JOB_NAME\n');
  147. fprintf(fid_single, 'echo submitted by $SLURM_JOB_ACCOUNT\n');
  148. fprintf(fid_single, 'echo from $SLURM_SUBMIT_DIR\n');
  149. fprintf(fid_single, 'echo the allocated nodes are: $SLURM_JOB_NODELIST\n');
  150. % SLURM requirements
  151. fprintf(fid_single, '\nmodule load pre2019\n');
  152. % add a comment what this script does
  153. jobnameline = ['\n# INFO: ' job_name '_' joblist.sessions{...
  154. joblist.sessinc(job_ind),1} '_' ...
  155. joblist.instances{job_ind2} '\n'];
  156. try
  157. fprintf(fid_single, jobnameline);
  158. catch ME
  159. disp(ME);
  160. end
  161. fprintf(fid_single, '\n');
  162. fprintf(fid_single,'mkdir -p $TMPDIR/PRF\n');
  163. fprintf(fid_single,'mkdir -p $TMPDIR/PRF/Logs/\n');
  164. % fprintf(fid_single,['cp -r $HOME/PRF/Data/' joblist.type '/' joblist.monkey '/' ...
  165. % joblist.sessions{joblist.sessinc(job_ind),1} '* $TMPDIR/PRF\n']);
  166. fprintf(fid_single, 'cp -r $HOME/PRF/Code/* $TMPDIR/PRF\n');
  167. fprintf(fid_single,'cd $TMPDIR/PRF\n\n');
  168. fprintf(fid_single,['chmod +x ' execute_matlab_process_sh '\n\n']);
  169. % exec parfun (Monkey,Session,Slices,HRF,numWorkers,modeltype,cv)
  170. line = sprintf('%s \\\n\t%s %s %s %s [%s] \\\n\t%s %s %s %s %s \\\n\t', ...
  171. execute_matlab_process_sh, parallel_fun, ...
  172. joblist.monkey, joblist.sessions{joblist.sessinc(job_ind),1}, ...
  173. joblist.instances{job_ind2},...
  174. num2str(joblist.sessions{joblist.sessinc(job_ind),2}),...
  175. joblist.modeltype,...
  176. num2str(joblist.xvalmode),...
  177. joblist.resfld,...
  178. log_file_dir, parallel_fun_dir);
  179. logline= ['$TMPDIR/PRF/Logs/Log_' joblist.monkey '_' ...
  180. joblist.sessions{joblist.sessinc(job_ind),1} '_' ...
  181. joblist.instances{job_ind2} '_' ...
  182. joblist.modeltype ...
  183. '_xval' num2str(joblist.xvalmode) '.txt'];
  184. fprintf(fid_single, '%s %s %s\n\n', line, '|& tee', logline);
  185. fprintf(fid_single,['cp ' logline ' $HOME/PRF/Logs/\n']);
  186. % finally: pass exit status of execute_matlab_process.sh to LISA
  187. fprintf(fid_single, 'exit $?\n');
  188. fclose(fid_single);
  189. disp(['Adding ' fullfilename ' to original batch file.']);
  190. fullfilename2 = ['$HOME/PRF/Code/Jobs/' filename];
  191. line = sprintf('%s %s', 'sbatch ', fullfilename2);
  192. fprintf(fid_commit_all, '%s\n', line);
  193. end
  194. fprintf(fid_commit_all, '\n');
  195. end
  196. fclose(fid_commit_all);
  197. system(['chmod +x ' fullfilename_all]);
  198. end