process_retmap 12 KB

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