process_retmap 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. #!/bin/bash
  2. set -e
  3. set -u
  4. ### Example Run & Usage
  5. # process_retmap - retinotopic mapping processing.
  6. # Takes corrected niftis and generates the phasemaps for polar angle and
  7. # eccentricity, as nifti and freesurfer overlay for surface presentation.
  8. #
  9. # Usage #
  10. # process_retmap <subject ID> <con> <exp> <clw> <ccw> <template_mask> <output_folder> <post_processing> <contract_shift> <expand_shift> <clock_shift> <counter_shift> <surface_maps> <anatomy_volume> <retmap2anat_mat> <ROI_mask>
  11. #
  12. # Input definition #
  13. # subject : Freesurfer subject ID
  14. # con : nifti for your contracting ring
  15. # exp : nifti for your expanding ring
  16. # clw : nifti for your clockwise wedge
  17. # ccw : nifti for your counter clockwise wedge
  18. # template_mask : mask to mask you phasemap, eg. brain mask, occ. lobe mask.
  19. # Needs to be coregistered to your input tSeries!
  20. # output_folder : where generate folders and save output
  21. #
  22. # post_processing : "True": the shift values if you didn't start as AFNI
  23. # intended and you want to shift them manually.
  24. # Therefore give your values
  25. #
  26. # contract_shift : range of phase shift values from 0-360
  27. # expand_shift : range of phase shift values from 0-360
  28. # clock_shift : range of phase shift values from 0-360
  29. # counter_shift : range of phase shift values from 0-360
  30. #
  31. # surface_maps : "True" if you want overlays.
  32. #
  33. # anatomy_volume : your reference anatomy for the overlay. It should
  34. # be your freesurfer anatomy, because your freesurfer
  35. # surfaces are generated from it awhile recon-all
  36. # retmap2anat_mat : a '*.mat' file used for the overlays
  37. # ROI_mask : if you want to get the overlay for your ROI, too
  38. # smooth : for fslmaths: create a gauss kernel of sigma mm and perform mean filtering
  39. #
  40. # Example without post processing and phase shift#
  41. #scripts/pyretmap/code/processing_pipeline/process_retmap \
  42. #sub-16 \
  43. #/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run001/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
  44. #/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run003/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
  45. #/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run004/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
  46. #/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run002/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
  47. #/home/data/psyinf/forrest_gump/anondata/sub016/templates/bold3Tp2/brain_mask.nii.gz \
  48. #/home/data/exppsy/spark/Study_Forrest \
  49. #False \
  50. #'' \
  51. #'' \
  52. #'' \
  53. #'' \
  54. #False \
  55. #'' \
  56. #'' \
  57. #'' \
  58. #2
  59. #~/Documents/Auswertung/paper-forrest_phase2_data/code/retmap/processing_pipeline/process_retmap \
  60. #sub-16 \
  61. #/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run001/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
  62. #/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run003/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
  63. #/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run004/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
  64. #/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run002/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
  65. #/home/data/psyinf/forrest_gump/anondata/sub016/templates/bold3Tp2/brain_mask.nii.gz \
  66. #/home/fkaule/temp \
  67. #False \
  68. #'' \
  69. #'' \
  70. #'' \
  71. #'' \
  72. #False \
  73. #'' \
  74. #'' \
  75. #'' \
  76. #2
  77. ### little helper
  78. function niigzBase
  79. {
  80. ## get basename from a niftigz path or file
  81. # usage: niigzname=$(niiBasename $inpath)
  82. # example:
  83. # echo $(niigzBase 'rightGM_dil3.nii.gz')
  84. # rightGM_dil3
  85. #
  86. echo "$(basename $1 .nii.gz)"
  87. }
  88. ### get necessary files and folders
  89. subject=${1}
  90. con=${2}
  91. exp=${3}
  92. clw=${4}
  93. ccw=${5}
  94. skipReoriANDDeobl=${6}
  95. template_mask=${7}
  96. FWHM=${8}
  97. output_folder=${9}
  98. post_processing=${10}
  99. contract_shift=${11}
  100. expand_shift=${12}
  101. clock_shift=${13}
  102. counter_shift=${14}
  103. surface_maps=${15}
  104. anatomy_volume=${16}
  105. retmap2anat_mat=${17}
  106. ROI_mask=${18}
  107. debug_mode_flag=${19}
  108. stimulus_cycle_time=32 #Tstim
  109. highpass=`bc <<< "scale=2; 2/($stimulus_cycle_time*3)"` # should be around 1/Tstim * 2/3
  110. lowpass=`bc <<< "scale=2; $highpass*3"` # app. highpass*3
  111. req_TR=`fslinfo $con | grep pixdim4 | tr -s ' '| cut -d ' ' -f 2`
  112. code_path=$(dirname $(readlink -f "$0"))
  113. sigma="$(echo "scale=2; $FWHM / 2.35" | bc)"
  114. echo $sigma
  115. echo $code_path
  116. retmapping_folder=$output_folder'/'$subject
  117. echo 'create retmap folder'
  118. rm -rf $retmapping_folder
  119. mkdir -p $retmapping_folder
  120. cd $retmapping_folder
  121. echo 'create temporary processing folder'
  122. mkdir -p 'pre_processing'
  123. declare -a order_of_processing=('contract' 'expand' 'clock' 'counter');
  124. declare -A shift=( [con]=$contract_shift [exp]=$expand_shift [clw]=$clock_shift [ccw]=$counter_shift );
  125. retmap_volumes=`fslnvols $con`
  126. waver -TR $req_TR -GAM -numout ${retmap_volumes} -inline 2@0.0 1@1.0 15@0.0 1@1.0 15@0.0 1@1.0 15@0.0 1@1.0 15@0.0 1@1.0 25@0.0 > 'refts.1D'
  127. ### processing
  128. index=0
  129. for f in $con $exp $clw $ccw; do
  130. retmap_run_folder='pre_processing/'${order_of_processing[$index]}
  131. mkdir -p $retmap_run_folder
  132. if [ "$FWHM" -gt 0 ]; then
  133. echo "Spatial Smoothing ->"
  134. sm_in="${f}"
  135. sm_out=$retmap_run_folder'/bold_sm.nii.gz'
  136. fslmaths "$f" -s $sigma $sm_out
  137. else
  138. echo "skip Spatial Smoothing ->"
  139. sm_out=$retmap_run_folder'/bold.nii.gz'
  140. cp "$f" $sm_out
  141. fi
  142. echo "Slice Time Correction ->"
  143. stcIn=$sm_out
  144. stcOut=$retmap_run_folder/$(niigzBase $stcIn)'_STC.nii.gz'
  145. 3dTshift -TR $req_TR -prefix $stcOut $stcIn
  146. if [ "$skipReoriANDDeobl" == "True" ]; then
  147. echo "skip Re-orient to standard and De-obliquing ->"
  148. reorOut=$stcOut
  149. else
  150. echo "De-obliquing ->"
  151. warpIn=$stcOut
  152. warpOut=$retmap_run_folder/$(niigzBase $stcOut)'_deobl.nii.gz'
  153. 3dWarp -prefix $warpOut -deoblique $warpIn
  154. echo "Re-orienting to standard orientation after De-obliquing ->"
  155. reorIn=$warpOut
  156. reorOut=$retmap_run_folder/$(niigzBase $warpOut)'_reor.nii.gz'
  157. fslreorient2std $reorIn $reorOut
  158. fi
  159. echo "Band Pass Filtering ->"
  160. bpIn=$reorOut
  161. bpOut=$retmap_run_folder/$(niigzBase $reorOut)'_filt.nii.gz'
  162. 3dBandpass -prefix $bpOut -norm $highpass $lowpass $bpIn
  163. if [ -f "$template_mask" ]; then
  164. echo "masking ->"
  165. maskingIn=$bpOut
  166. maskingOut=$retmap_run_folder/$(niigzBase $bpOut)'_masked.nii.gz'
  167. fslmaths $maskingIn -mas $template_mask $maskingOut
  168. else
  169. echo "skip masking ->"
  170. maskingOut=$bpOut
  171. fi
  172. # hand over output of last preProc step (here masking)
  173. preProcOut=$(basename $maskingOut)
  174. index="$((index + 1))"
  175. done
  176. mkdir -p 'raw_outputs'
  177. # 3dRetinoPhase:
  178. # the core processing. If you want to get the "rawest" version of AFNI retmap,
  179. # use this function and ignore the rest of this script.
  180. # Here you find help: [http://afni.nimh.nih.gov/pub/dist/doc/program_help/3dRetinoPhase.html]
  181. 3dRetinoPhase -con 'pre_processing/'${order_of_processing[0]}/$preProcOut \
  182. -ccw 'pre_processing/'${order_of_processing[3]}/$preProcOut \
  183. -exp 'pre_processing/'${order_of_processing[1]}/$preProcOut \
  184. -clw 'pre_processing/'${order_of_processing[2]}/$preProcOut \
  185. -prefix 'BRIK_files/retmap' \
  186. -Tstim 32 \
  187. -nrings 1 \
  188. -nwedges 1 \
  189. -pre_stim 0 \
  190. -ref_ts 'refts.1D' \
  191. -phase_estimate DELAY
  192. # AFNI2nifti:
  193. # since AFNI has its own file format we want to leave
  194. # the AFNI-universe here, transform to nifti
  195. mri_convert $(find 'BRIK_files' -name 'retmap.ecc.field*.BRIK' -type f) 'raw_outputs/combined_eccentricity_map_field.nii.gz' --in_type afni
  196. mri_convert $(find 'BRIK_files' -name 'retmap.pol.field*.BRIK' -type f) 'raw_outputs/combined_polar_map_field.nii.gz' --in_type afni
  197. mri_convert $(find 'BRIK_files' -name 'retmap.ecc-+*.BRIK' -type f) 'raw_outputs/con_eccentricity_map.nii.gz' --in_type afni
  198. mri_convert $(find 'BRIK_files' -name 'retmap.pol++*.BRIK' -type f) 'raw_outputs/clw_polar_map.nii.gz' --in_type afni
  199. mri_convert $(find 'BRIK_files' -name 'retmap.ecc++*.BRIK' -type f) 'raw_outputs/exp_eccentricity_map.nii.gz' --in_type afni
  200. mri_convert $(find 'BRIK_files' -name 'retmap.pol-+*.BRIK' -type f) 'raw_outputs/ccw_polar_map.nii.gz' --in_type afni
  201. # phaseshift and merge to efd and pfd:
  202. if [ "$post_processing" == "True" ]; then
  203. echo "Performing post processing"
  204. mkdir -p 'post_processing'
  205. # phaseshift
  206. # if there is a shift in stimulus onset, ie.:
  207. # - the polar wedge doesn't start at the upper vertical meridian.
  208. # Both (ccw & clw) need to start at the upper vertical meridian
  209. # - the exp & con rings don't start zero ..
  210. # You can phase shift them to do so and shift the output phasemap
  211. # from 3dRetinoPhase to this position.
  212. # Normally this shouldn't be necessary, unlike you do sth. special or
  213. # mess with your stimulus.
  214. for fileToShift in $(find 'raw_outputs' -name '*_map.nii.gz'); do
  215. echo 'Post processing phase shift '$fileToShift
  216. IFS='_' read -a conds <<< $(basename $fileToShift)
  217. echo ${shift[${conds[0]}]}
  218. $code_path'/RetMap_phaseshift' $fileToShift ${shift[${conds[0]}]}
  219. done
  220. # merge opposite phasemaps into fieldmaps for ECC and POL:
  221. # As we expect a phaseshift, we have to merge the opposite phasemaps
  222. # here.
  223. # The outcome is as the 'ecc.field*.BRIK' and 'pol.field*.BRIK'
  224. # output from 3dRetinoPhase. So if your stimulus is as AFNI intended,
  225. # you can stick with the 3dRetinoPhase output.
  226. $code_path'/combine_volumes' 'post_processing/con_phShift.nii.gz' 'post_processing/exp_phShift.nii.gz' 'post_processing/combined_pipeline_eccentricity.nii.gz'
  227. $code_path'/combine_volumes' 'post_processing/clw_phShift.nii.gz' 'post_processing/ccw_phShift.nii.gz' 'post_processing/combined_pipeline_polar.nii.gz'
  228. #~ #for fileToRT in $(find 'post_processing' -name '*pipeline*.nii.gz'); do
  229. #~ # echo 'Generating rtview'$fileToRT
  230. #~ # $code_path'/deg2rtview' $fileToRT
  231. #~ #done
  232. fi
  233. # get the phasemaps overlays for freesurfer surfaces
  234. if [ "$surface_maps" == "True" ]; then
  235. mkdir -p 'alignments'
  236. mkdir -p 'surface_maps'
  237. if [ "$post_processing" == "True" ]; then
  238. if [ "$debug_mode_flag" == "True" ]; then
  239. files_to_process=`find 'post_processing' -name '*.nii.gz*' -type f`
  240. else
  241. files_to_process=`find 'post_processing' -name 'combined_*.nii.gz*' -type f`
  242. fi
  243. else
  244. files_to_process=`find 'raw_outputs' -name 'combined_*.nii.gz*' -type f`
  245. fi
  246. for pm in $files_to_process; do
  247. pm_base_name=${pm##*/}
  248. echo 'coregistering to anatomy -> '$pm_base_name
  249. flirt \
  250. -in $pm \
  251. -ref "$anatomy_volume" \
  252. -out 'alignments/'${pm_base_name%.*.*}'2FS_anat.nii.gz' \
  253. -init $retmap2anat_mat \
  254. -applyxfm
  255. if [[ -f $ROI_mask ]]; then
  256. fslmaths 'alignments/'${pm_base_name%.*.*}'2FS_anat.nii.gz' -mas $ROI_mask 'alignments/'${pm_base_name%.*.*}'2FS_anat.nii.gz'
  257. fi
  258. ## left hemisphere
  259. mri_vol2surf \
  260. --hemi lh \
  261. --mov 'alignments/'${pm_base_name%.*.*}'2FS_anat.nii.gz' \
  262. --regheader $subject \
  263. --projfrac-avg 0.0 0.75 0.001 \
  264. --out 'surface_maps/'${pm_base_name%.*.*}'_lh.mgh' \
  265. --surf white \
  266. --out_type mgh
  267. ## right hemisphere
  268. mri_vol2surf \
  269. --hemi rh \
  270. --mov 'alignments/'${pm_base_name%.*.*}'2FS_anat.nii.gz' \
  271. --regheader $subject \
  272. --projfrac-avg 0.0 0.75 0.001 \
  273. --out 'surface_maps/'${pm_base_name%.*.*}'_rh.mgh' \
  274. --surf white \
  275. --out_type mgh
  276. done
  277. fi
  278. if [ "$debug_mode_flag" != "True" ]; then
  279. echo 'delete intermediate steps'
  280. rm -rf 'pre_processing'
  281. fi