data-retinotopy/code/process_retmap
fkaule 1ae1d4b8c4 ENH: if skipping a processing step, the output will not get a flag for that processing step:
no smoothing -> no "_sm" in output filename. Before it got the "_sm", no matter if smoothing was done or not.
2017-01-31 10:18:57 +01:00

322 lines
12 KiB
Bash
Executable file

#!/bin/bash
set -e
set -u
### Example Run & Usage
# process_retmap - retinotopic mapping processing.
# Takes corrected niftis and generates the phasemaps for polar angle and
# eccentricity, as nifti and freesurfer overlay for surface presentation.
#
# Usage #
# 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>
#
# Input definition #
# subject : Freesurfer subject ID
# con : nifti for your contracting ring
# exp : nifti for your expanding ring
# clw : nifti for your clockwise wedge
# ccw : nifti for your counter clockwise wedge
# template_mask : mask to mask you phasemap, eg. brain mask, occ. lobe mask.
# Needs to be coregistered to your input tSeries!
# output_folder : where generate folders and save output
#
# post_processing : "True": the shift values if you didn't start as AFNI
# intended and you want to shift them manually.
# Therefore give your values
#
# contract_shift : range of phase shift values from 0-360
# expand_shift : range of phase shift values from 0-360
# clock_shift : range of phase shift values from 0-360
# counter_shift : range of phase shift values from 0-360
#
# surface_maps : "True" if you want overlays.
#
# anatomy_volume : your reference anatomy for the overlay. It should
# be your freesurfer anatomy, because your freesurfer
# surfaces are generated from it awhile recon-all
# retmap2anat_mat : a '*.mat' file used for the overlays
# ROI_mask : if you want to get the overlay for your ROI, too
# smooth : for fslmaths: create a gauss kernel of sigma mm and perform mean filtering
#
# Example without post processing and phase shift#
#scripts/pyretmap/code/processing_pipeline/process_retmap \
#sub-16 \
#/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run001/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
#/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run003/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
#/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run004/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
#/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run002/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
#/home/data/psyinf/forrest_gump/anondata/sub016/templates/bold3Tp2/brain_mask.nii.gz \
#/home/data/exppsy/spark/Study_Forrest \
#False \
#'' \
#'' \
#'' \
#'' \
#False \
#'' \
#'' \
#'' \
#2
#~/Documents/Auswertung/paper-forrest_phase2_data/code/retmap/processing_pipeline/process_retmap \
#sub-16 \
#/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run001/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
#/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run003/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
#/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run004/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
#/home/data/psyinf/forrest_gump/anondata/sub016/BOLD/task005_run002/bold_bold3Tp2_to_subjbold3Tp2.nii.gz \
#/home/data/psyinf/forrest_gump/anondata/sub016/templates/bold3Tp2/brain_mask.nii.gz \
#/home/fkaule/temp \
#False \
#'' \
#'' \
#'' \
#'' \
#False \
#'' \
#'' \
#'' \
#2
### little helper
function niigzBase
{
## get basename from a niftigz path or file
# usage: niigzname=$(niiBasename $inpath)
# example:
# echo $(niigzBase 'rightGM_dil3.nii.gz')
# rightGM_dil3
#
echo "$(basename $1 .nii.gz)"
}
### get necessary files and folders
subject=${1}
con=${2}
exp=${3}
clw=${4}
ccw=${5}
skipReoriANDDeobl=${6}
template_mask=${7}
FWHM=${8}
output_folder=${9}
post_processing=${10}
contract_shift=${11}
expand_shift=${12}
clock_shift=${13}
counter_shift=${14}
surface_maps=${15}
anatomy_volume=${16}
retmap2anat_mat=${17}
ROI_mask=${18}
debug_mode_flag=${19}
stimulus_cycle_time=32 #Tstim
highpass=`bc <<< "scale=2; 2/($stimulus_cycle_time*3)"` # should be around 1/Tstim * 2/3
lowpass=`bc <<< "scale=2; $highpass*3"` # app. highpass*3
req_TR=`fslinfo $con | grep pixdim4 | tr -s ' '| cut -d ' ' -f 2`
code_path=$(dirname $(readlink -f "$0"))
sigma="$(echo "scale=2; $FWHM / 2.35" | bc)"
echo $sigma
echo $code_path
retmapping_folder=$output_folder'/'$subject
echo 'create retmap folder'
rm -rf $retmapping_folder
mkdir -p $retmapping_folder
cd $retmapping_folder
echo 'create temporary processing folder'
mkdir -p 'pre_processing'
declare -a order_of_processing=('contract' 'expand' 'clock' 'counter');
declare -A shift=( [con]=$contract_shift [exp]=$expand_shift [clw]=$clock_shift [ccw]=$counter_shift );
retmap_volumes=`fslnvols $con`
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'
### processing
index=0
for f in $con $exp $clw $ccw; do
retmap_run_folder='pre_processing/'${order_of_processing[$index]}
mkdir -p $retmap_run_folder
if [ "$FWHM" -gt 0 ]; then
echo "Spatial Smoothing ->"
sm_in="${f}"
sm_out=$retmap_run_folder'/bold_sm.nii.gz'
fslmaths "$f" -s $sigma $sm_out
else
echo "skip Spatial Smoothing ->"
sm_out=$retmap_run_folder'/bold.nii.gz'
cp "$f" $sm_out
fi
echo "Slice Time Correction ->"
stcIn=$sm_out
stcOut=$retmap_run_folder/$(niigzBase $stcIn)'_STC.nii.gz'
3dTshift -TR $req_TR -prefix $stcOut $stcIn
if [ "$skipReoriANDDeobl" == "True" ]; then
echo "skip Re-orient to standard and De-obliquing ->"
reorOut=$stcOut
else
echo "De-obliquing ->"
warpIn=$stcOut
warpOut=$retmap_run_folder/$(niigzBase $stcOut)'_deobl.nii.gz'
3dWarp -prefix $warpOut -deoblique $warpIn
echo "Re-orienting to standard orientation after De-obliquing ->"
reorIn=$warpOut
reorOut=$retmap_run_folder/$(niigzBase $warpOut)'_reor.nii.gz'
fslreorient2std $reorIn $reorOut
fi
echo "Band Pass Filtering ->"
bpIn=$reorOut
bpOut=$retmap_run_folder/$(niigzBase $reorOut)'_filt.nii.gz'
3dBandpass -prefix $bpOut -norm $highpass $lowpass $bpIn
if [ -f "$template_mask" ]; then
echo "masking ->"
maskingIn=$bpOut
maskingOut=$retmap_run_folder/$(niigzBase $bpOut)'_masked.nii.gz'
fslmaths $maskingIn -mas $template_mask $maskingOut
else
echo "skip masking ->"
maskingOut=$bpOut
fi
# hand over output of last preProc step (here masking)
preProcOut=$(basename $maskingOut)
index="$((index + 1))"
done
mkdir -p 'raw_outputs'
# 3dRetinoPhase:
# the core processing. If you want to get the "rawest" version of AFNI retmap,
# use this function and ignore the rest of this script.
# Here you find help: [http://afni.nimh.nih.gov/pub/dist/doc/program_help/3dRetinoPhase.html]
3dRetinoPhase -con 'pre_processing/'${order_of_processing[0]}/$preProcOut \
-ccw 'pre_processing/'${order_of_processing[3]}/$preProcOut \
-exp 'pre_processing/'${order_of_processing[1]}/$preProcOut \
-clw 'pre_processing/'${order_of_processing[2]}/$preProcOut \
-prefix 'BRIK_files/retmap' \
-Tstim 32 \
-nrings 1 \
-nwedges 1 \
-pre_stim 0 \
-ref_ts 'refts.1D' \
-phase_estimate DELAY
# AFNI2nifti:
# since AFNI has its own file format we want to leave
# the AFNI-universe here, transform to nifti
mri_convert $(find 'BRIK_files' -name 'retmap.ecc.field*.BRIK' -type f) 'raw_outputs/combined_eccentricity_map_field.nii.gz' --in_type afni
mri_convert $(find 'BRIK_files' -name 'retmap.pol.field*.BRIK' -type f) 'raw_outputs/combined_polar_map_field.nii.gz' --in_type afni
mri_convert $(find 'BRIK_files' -name 'retmap.ecc-+*.BRIK' -type f) 'raw_outputs/con_eccentricity_map.nii.gz' --in_type afni
mri_convert $(find 'BRIK_files' -name 'retmap.pol++*.BRIK' -type f) 'raw_outputs/clw_polar_map.nii.gz' --in_type afni
mri_convert $(find 'BRIK_files' -name 'retmap.ecc++*.BRIK' -type f) 'raw_outputs/exp_eccentricity_map.nii.gz' --in_type afni
mri_convert $(find 'BRIK_files' -name 'retmap.pol-+*.BRIK' -type f) 'raw_outputs/ccw_polar_map.nii.gz' --in_type afni
# phaseshift and merge to efd and pfd:
if [ "$post_processing" == "True" ]; then
echo "Performing post processing"
mkdir -p 'post_processing'
# phaseshift
# if there is a shift in stimulus onset, ie.:
# - the polar wedge doesn't start at the upper vertical meridian.
# Both (ccw & clw) need to start at the upper vertical meridian
# - the exp & con rings don't start zero ..
# You can phase shift them to do so and shift the output phasemap
# from 3dRetinoPhase to this position.
# Normally this shouldn't be necessary, unlike you do sth. special or
# mess with your stimulus.
for fileToShift in $(find 'raw_outputs' -name '*_map.nii.gz'); do
echo 'Post processing phase shift '$fileToShift
IFS='_' read -a conds <<< $(basename $fileToShift)
echo ${shift[${conds[0]}]}
$code_path'/RetMap_phaseshift' $fileToShift ${shift[${conds[0]}]}
done
# merge opposite phasemaps into fieldmaps for ECC and POL:
# As we expect a phaseshift, we have to merge the opposite phasemaps
# here.
# The outcome is as the 'ecc.field*.BRIK' and 'pol.field*.BRIK'
# output from 3dRetinoPhase. So if your stimulus is as AFNI intended,
# you can stick with the 3dRetinoPhase output.
$code_path'/combine_volumes' 'post_processing/con_phShift.nii.gz' 'post_processing/exp_phShift.nii.gz' 'post_processing/combined_pipeline_eccentricity.nii.gz'
$code_path'/combine_volumes' 'post_processing/clw_phShift.nii.gz' 'post_processing/ccw_phShift.nii.gz' 'post_processing/combined_pipeline_polar.nii.gz'
#~ #for fileToRT in $(find 'post_processing' -name '*pipeline*.nii.gz'); do
#~ # echo 'Generating rtview'$fileToRT
#~ # $code_path'/deg2rtview' $fileToRT
#~ #done
fi
# get the phasemaps overlays for freesurfer surfaces
if [ "$surface_maps" == "True" ]; then
mkdir -p 'alignments'
mkdir -p 'surface_maps'
if [ "$post_processing" == "True" ]; then
if [ "$debug_mode_flag" == "True" ]; then
files_to_process=`find 'post_processing' -name '*.nii.gz*' -type f`
else
files_to_process=`find 'post_processing' -name 'combined_*.nii.gz*' -type f`
fi
else
files_to_process=`find 'raw_outputs' -name 'combined_*.nii.gz*' -type f`
fi
for pm in $files_to_process; do
pm_base_name=${pm##*/}
echo 'coregistering to anatomy -> '$pm_base_name
flirt \
-in $pm \
-ref "$anatomy_volume" \
-out 'alignments/'${pm_base_name%.*.*}'2FS_anat.nii.gz' \
-init $retmap2anat_mat \
-applyxfm
if [[ -f $ROI_mask ]]; then
fslmaths 'alignments/'${pm_base_name%.*.*}'2FS_anat.nii.gz' -mas $ROI_mask 'alignments/'${pm_base_name%.*.*}'2FS_anat.nii.gz'
fi
## left hemisphere
mri_vol2surf \
--hemi lh \
--mov 'alignments/'${pm_base_name%.*.*}'2FS_anat.nii.gz' \
--regheader $subject \
--projfrac-avg 0.0 0.75 0.001 \
--out 'surface_maps/'${pm_base_name%.*.*}'_lh.mgh' \
--surf white \
--out_type mgh
## right hemisphere
mri_vol2surf \
--hemi rh \
--mov 'alignments/'${pm_base_name%.*.*}'2FS_anat.nii.gz' \
--regheader $subject \
--projfrac-avg 0.0 0.75 0.001 \
--out 'surface_maps/'${pm_base_name%.*.*}'_rh.mgh' \
--surf white \
--out_type mgh
done
fi
if [ "$debug_mode_flag" != "True" ]; then
echo 'delete intermediate steps'
rm -rf 'pre_processing'
fi