-
Notifications
You must be signed in to change notification settings - Fork 1
fMRI Fear Conditioning FSL Analysis Pipeline
To detail the fMRI Fear Conditioning (version3/design3 only) FSL Feat Analysis process and scripts. Analyses were run on run1 only by MQ but scripts will be analogous for run2 reversal if someone were to set them up. The fMRI fear conditioning paradigm is detailed in the wiki "fMRI Fear Conditioning Paradigm" and the model design themselves are detailed in the wiki "Fear Conditioning Model Overview".
Various FSL feat models (mini-block, linear, split half cue and outcome) were run with the main contrast of interest being activation to aversive face when scream is absent relative to neutral face (CS+u > CS-) or the inverse (CS- > CS+u), as is consistent with most fear conditioning literature. See the "Fear Conditioning Model Overview" wiki for more details on how these models were set up.
For more information on FSL feat in general see "FSL Feat wiki"
Final statistical testing was done using FSL randomise (see: "FSL Randomise Wiki")
Script: /data/joy/BBL/projects/conteReproc2017/fearConditioningRun1/design3_run_feat.sh
Requires:
- Subject list in the form of a text file (list of bblid/datexscanid and fMRI order)
Example: bblid,datexscanid,0_2 - Templates for the model (template design.fsf which will be populated with subject-specific information)
Example:/import/monstrum/conte_815814/scripts/functional/fsf_templates/order0_2_run1_linear_mini_block_design.fsf
- Biascorrected brain output (either from ANTs or a different pipeline)
/data/joy/BBL/studies/conte/processedData/structural/conte_design3_n118_structural_201706051547/$bblid/*$scanid/antsCT/*BrainSegmentation0N4.nii.gz
Output:
- Subject-level feat output (mini block example)
/data/joy/BBL/studies/conte/processedData/fearconditioningRun1/subject_level_feats/[bblid]/[datexscanid]/[scanid]_bbr_linear_mini_block.feat
Script: /data/joy/BBL/projects/conteReproc2017/fearConditioningRun1/design3_run_feat.sh
-
For each subject in the list, create variables for their fear conditioning order and the subject's scanid and bblid
for i in `cat /data/joy/BBL/studies/conte/subjectData/design3InclusionsSubjectListFslFeat.txt`; do bblid=`echo $i | cut -d "," -f 1` datexscanid=`echo $i | cut -d "," -f 2` scanid=`echo $datexscanid | cut -d "x" -f 2` order=`echo $i | cut -d "," -f 3`
-
Create a variable for the design template and task depending on what order the subject is in
#if the subject is order 1_3 and you chose to run run1 then run the following feat design (the one commented in) template if [ $order == "1_3" ]; then fsf1=/import/monstrum/conte_815814/scripts/functional/fsf_templates/order1_3_run1_linear_mini_block_design.fsf #fsf1=/import/monstrum/conte_815814/scripts/functional/fsf_templates/order1_3_run1_linear.fsf #fsf1=/import/monstrum/conte_815814/scripts/functional/fsf_templates/order1_3_run1_split_half_sec1_sec5.fsf task=fearcondV3R1 fi #if the subject is order 0_2 and you chose to run run1 then run the following feat design (the one commented in) template if [ $order == "0_2" ]; then fsf1=/data/joy/BBL/studies/conte/fmriDesignFiles/order0_2/run1/fsf_templates/order0_2_run1_linear_mini_block_design.fsf #fsf1=/data/joy/BBL/studies/conte/fmriDesignFiles/order0_2/run1/fsf_templates/order0_2_run1_linear.fsf #fsf1=/data/joy/BBL/studies/conte/fmriDesignFiles/order0_2/run1/fsf_templates/order0_2_run1_split_half_sec1_sec5.fsf task=fearcondV3R1 fi #create a temp design.fsf which will hold subject specific data to replace the standard template for feat temp1=/data/joy/BBL/studies/conte/fmriDesignFiles/order0_2/run1/fsf_templates/${task}_temp1.fsf
-
Create a variable for how you want the feat output to be called in the subject's directory
suffix1=bbr_linear_mini_block.feat
-
Print to the screen the subject and order and create a variable for the subject's functional nifti image, print it to the screen and if one doesn't exist print an error and move to the next subject
echo $scanid echo $order #create a variable for the subject's functional nifti image, print it to the screen and if one doesn't exist print an error and move to the next subject func=$(ls /data/joy/BBL/studies/conte/rawData/$bblid/${datexscanid}/*${task}*/nifti/*fearcond*.nii.gz 2>/dev/null) echo $func if [ -z $func ]; then echo "no functional image" continue fi
-
Remove the nii.gz appendage from the file name and append the suffix you chose above for the output name then print that to the screen
func=$(echo $func | sed "s+.nii.gz++g") feat1=/data/joy/BBL/studies/conte/processedData/fearconditioningRun1/subject_level_feats/$bblid/${datexscanid}/${scanid}_${suffix1} echo $feat1
-
Do the same for the subject's biascorrected structural image and then remove the .nii.gz appendage
#create a variable for the subject's biascorrected structural image, print it to the screen and if one doesn't exist print an error and move to the next subject mprage=$(ls /data/joy/BBL/studies/conte/processedData/structural/conte_design3_n118_structural_201706051547/$bblid/${datexscanid}/antsCT/*BrainSegmentation0N4.nii.gz 2>/dev/null) if [ -z $mprage ]; then echo "no bias corrected mprage" continue fi #remove the nii.gz appendage from the file name and print that file name to the screen mprage=$(echo $mprage | sed "s+.nii.gz++g") echo $mprage
-
Copy the design template to the temp file created above
#print to the screen which feat design will be run echo $fsf1 #copy the design template to the temp file created above cp $fsf1 $temp1
-
Replace the standard template "fillers" with the subject specific paths to the output directory, functional image, and mprage image
sed -i "s|###OUTPUT###|$feat1|g" "$temp1" echo "$temp1" sed -i "s|###NIFTI###|$func|g" "$temp1" sed -i "s|###STRUCT###|$mprage|g" "$temp1"
-
Run the feat design for that subject
feat $temp1
Script: /data/joy/BBL/projects/conteReproc2017/fearConditioningRun1/conte_merge_images_mask.sh
Requires:
- Subject list in the form of a text file (list of scanids)
- Standardized stats output from feat for each subject in the list
Example:/data/joy/BBL/studies/conte/processedData/fearconditioningRun1/subject_level_feats/[bblid]/[datexscanid]/[scanid]_bbr_linear_mini_block.feat/reg_standard/stats/cope11.nii.gz
Output:
- Merged registered copes (with as many volumes as subjects in your list)
Example:/data/joy/BBL/studies/conte/subjectData/fearConditioningRun1/merged_copes/n110_bbr_linear_mini_block_run1_cope11.nii.gz
Run the script first with the following parameters:
copes="cope1"
maskflag=1
Then after the first cope is merged and the mask if created, change it to maskflag=0 and copes="cope2 ..." with as many copes as your feat output has and you wish to merge. This is so you don't spend extra time and space to merge the mask each time you merge a cope. You don't need the mask to merge 32 identical times, just once.
Script: /data/joy/BBL/projects/conteReproc2017/fearConditioningRun1/conte_merge_images_mask.sh
-
Create a variable for the subject list you pass it, the path to where the output images will go, and the suffix of the feat you wish to merge images from
scanids=$(cat /data/joy/BBL/studies/conte/subjectData/design3InclusionsSubjectList.txt) outdir=/data/joy/BBL/studies/conte/subjectData/fearConditioningRun1/merged_copes/ #the suffix of the feat which you want to merge images from nickname="bbr_linear_mini_block" feat=$nickname.feat
-
Select the copes you have in your feat output and wish to merge and the run of the data you wish to merge (V3R1 is run=1). Note the information above on running the script first with copes=1 and maskflag=1.
#variables for the level1 feat copes to merge-- can be multiple copes e.g., "cope1 cope2 cope3 cope7" #Note you'll see cope1 is separate in many so that cope1 can be run and merged with the maskflag set to 1, then can be commented out and the rest of the copes can be run without the mask flag to speed things up #copes="cope1" copes="cope2 cope3 cope4 cope5 cope6 cope7 cope8 cope9 cope10 cope11 cope12" mask="mask" varcopeflag=1 #if=1, also will merge varcopes maskflag=0 # if =1, also will merge masks run=1 #the fear conditioning run you are merging (run1 or run2 reversal)
-
Create a variable for the output log directory and remove any existing logs
logdir=/data/joy/BBL/projects/conteReproc2017/fearConditioningRun1/logs ####### #remove any existing log file for missing copes rm -f $logdir/conte_missing_copes_for_merge.txt
-
Print out which feat will be merged and the number of subjects to merge
echo "feat is $feat" nsubj=$(echo $scanids | wc | awk '{print $2}') echo "$nsubj subjects" echo "*********"
-
For each cope in the list, print out the cope and remove any existing cope and varcope lists
for c in $copes; do echo "" echo "" echo "********************" echo "now working on $c" echo "********************" rm -f copelist_tmp.txt rm -f varcopelist_tmp.txt
-
For each subject print out the scanid, and create a variable which gets the fear conditioning standardized cope image for each subject
for b in $scanids; do echo "" echo $b #create a variable which gets the fear conditioning standardized cope image for each subject image=$(ls -d /data/joy/BBL/studies/conte/processedData/fearconditioningRun1/subject_level_feats/$bblid/*$scand/${scanid}"_bbr_linear_mini_block.feat"/reg_standard/stats/${c}.nii.gz) #if that image doesn't exist then output an error and append it to the error text file if [ -z "$image" ]; then echo "COPE MISSING" echo -e"$b \t $c" >> $logdir/conte_missing_copes_for_merge.txt exit 1 fi #if it does exist print the path and output to a cope list echo $image echo $image >> copelist_tmp.txt
-
Create a variable which gets the fear conditioning standardized varcope image for each subject
#if you should also merge varcopes then if [ "$varcopeflag" == 1 ]; then echo "merging varcopes also" #create a variable which gets the fear conditioning standardized varcope image for each subject varimage=$(ls -d /data/joy/BBL/studies/conte/processedData/fearconditioningRun1/subject_level_feats/$bblid/*$scand/${scanid}"_bbr_linear_mini_block.feat"/reg_standard/stats/var${c}.nii.gz) #if that image doesn't exist then output an error and append it to the error text file if [ -z "$varimage" ]; then echo "VARCOPE MISSING" echo -e"$b \t var${c}" >> $logdir/conte_missing_copes_for_merge.txt exit 1 fi #if it does exist print the path and output to a varcope list echo $varimage echo $varimage >> varcopelist_tmp.txt fi
-
Create a variable which gets the fear conditioning standardized mask image for each subject
#if the mask flag is set to 1 then if [ "$maskflag" == 1 ]; then echo "merging masks also" #create a variable which gets the fear conditioning standardized mask image for each subject maskimage=$(ls -d /data/joy/BBL/studies/conte/processedData/fearconditioningRun1/subject_level_feats/$bblid/*$scand/${scanid}"_bbr_linear_mini_block.feat"/reg_standard/mask.nii.gz) #if that image doesn't exist then output an error and append it to the error text file if [ -z "$maskimage" ]; then echo "MASK MISSING" echo -e"$b \t mask" >> $logdir/conte_missing_copes_for_merge.txt exit 1 fi #if it does exist print the path and output to a mask list echo $maskimage echo $maskimage >> masklist_tmp.txt fi done
-
Print the number of subjects to be merged for copes and merge the copes in the cope list for each subject
echo "" echo "********************" echo "now merging $nsubj images for $c" #merge the copes in the cope list for each subject fslmerge -t ${outdir}/n${nsubj}_${nickname}_run${run}_${c} $(cat copelist_tmp.txt)
-
If you have the varcope flag set to equal 1 (varcopeflag=1) then do the same for the varcopes
#if varcope is set to 1 then if [ "$varcopeflag" == 1 ]; then #print the number of subjects to be merged for varcopes echo "" echo "now merging $nsubj images for var${c}" #merge the varcopes in the varcope list for each subject fslmerge -t ${outdir}/n${nsubj}_${nickname}_run${run}_var${c} $(cat varcopelist_tmp.txt) echo "********************" fi
-
If you have the mask flag set to equal 1 (maskflag=1) then do the same for the mask
#if mask is set to 1 then if [ "$maskflag" == 1 ]; then #print the number of subjects to be merged for the mask echo "" echo "now merging $nsubj images for mask" #merge the masks in the mask list for each subject and binarize the mask and get overlap fslmerge -t ${outdir}/n${nsubj}_mask $(cat masklist_tmp.txt) fslmaths ${outdir}/n${nsubj}_mask -Tmin -bin -mas /share/apps/fsl/5.0.8/data/standard/MNI152_T1_2mm_brain.nii.gz ${outdir}/${nickname}"_n"${nsubj}"_run"${run}"_final_maskoverlap" echo "********************" fi done
-
Print the output directory to the screen (after removing the lists of copes, etc. that you merged)
rm -f copelist_tmp.txt rm -f varcopelist_tmp.txt rm -f masklist_tmp.txt echo "output at ${outdir}/n${nsubj}_${nickname}_run${run}_${c}"
For more information on group-level feats by flame1 see the FSL Higher Level Feat Output wiki
Script: /data/joy/BBL/projects/conteReproc2017/fearConditioningRun1/makedesign.m
Requires:
- A subject clinical variable spreadsheet with the following headers (columns not labeled in sheet as it is read into matlab and matlab doesn't like headers):
/data/joy/BBL/studies/conte/subjectData/design3fMRISubjectClinicalDemoData_no_headers.csv
- 1- bblid
- 2-scanid
- 3-fmri_exclude (1=exclude, 0=include)
- 4-diagnostic group (0=NC, 1=CR, 2=P)
- 5-fmri version order (1=order1_3, 0=order0_2)
- 6- scream unpleasantness rating
- 7-cains total (negative symptoms)
- 8-positive symptoms (sips p)
- 9-anxiety rating (stai trait)
- 10-post scan ratings confidence
- 11-motion
- 12=CAINS map score
- 13=CAINS expression score
- 14=age
- 15=sex (1=male, 2=female)
- 16=race (1=caucasian, 2=non-caucasian
- 17=run1 ratings aversive - neutral
- 18=run1 neutral ratings
- 19=run1 - pre ratings aversive - neutral
- 20=run1 - pre neutral ratings
Output:
- Group-level/Higher-level design.mat and design.grp files. Example:
/data/joy/BBL/studies/conte/processedData/fearconditioningRun1/single_group_level_feats/single_group_linear_mini_block_n110/design.mat
/data/joy/BBL/studies/conte/processedData/fearconditioningRun1/single_group_level_feats/single_group_linear_mini_block_n110/design.grp
- Create an output directory for your design files and the for the ultimate group-level feat output. Example:
mdkir /data/joy/BBL/studies/conte/processedData/fearconditioningRun1/single_group_level_feats/single_group_linear_mini_block_n110/
Script: /data/joy/BBL/projects/conteReproc2017/fearConditioningRun1/makedesign.m
-
Load in the clinical and demographic data
data=load('/data/joy/BBL/studies/conte/subjectData/design3fMRISubjectClinicalDemoData.csv');
-
Create variables for the number of groups you want the analysis to include (i.e. 1=single group analysis, 3= 3 group NC, CR, SZ analysis), whether you should exclude NC's from analysis, if you wish to covary for a variable, and if you wish to demean within group
numgp=3; %1 or 2 or 3? patient=1; %exclude NC's and count patients and cr's as one single group covariate=0; %0 if only running group, 1 if including covariate(s) demean_within=0; %do you want to demean your covariate within groups or across all groups? If you want to demean within groups then set this flage to 1;
-
Exclude data based on if group is missing, if motion is > .3 (meanrelrms), and if fMRI exclude =1
%exclude data based on missing values (set to group missing right now) excludeind=find(isnan(data(:,4))); data(excludeind,:)=''; %exclude based on high motion (>.3) motionind=find(data(:,11)>.3); data(motionind,:)=''; %exclude based on fmri_exclude column exclude=find(data(:,3)==1); data=data(setdiff(1:size(data,1),exclude),:);
-
Set the indices for group inclusion/exclusion and if you set to exclude NC's from analysis do so
%dx EVs group=data(:,4); %NC=0, CR=1, P=2 ncind=find(group==0); crind=find(group==1); szind=find(group==2); ncinclude=zeros(length(group),1); ncinclude(ncind)=1; crinclude=zeros(length(group),1); crinclude(crind)=1; szinclude=zeros(length(group),1); szinclude(szind)=1; if patient==1; data(ncind,:)=''; end;
-
If you had elected to have a covariate then create a variable for the covariate
covariate1=data(:,7); %cains total
-
Create a design variable (for design.mat) depending on the parameters you set at the beginning of the script
if numgp==3 & covariate==0 & demean_within==0; design=[ncinclude crinclude szinclude];% run most basic group only no covariates model end; if numgp==1 & covariate==0 & demean_within==0; design=ones(length(data),1); end; if covariate==1 & numgp==3 & demean_within==0; design=[ncinclude crinclude szinclude covariate1 ];%add covariates in end; if covariate==1 & numgp==1 & demean_within==0; design=[ones(length(data),1) covariate1 ]; end;
-
Alternatively, if you want to have your design demean within group
if covariate==1 & numgp==3 & demean_within==1; design=[ncinclude crinclude szinclude covariate1 covariate1 covariate1]; design(ncinclude==0,4)=NaN; design(crinclude==0,5)=NaN; design(szinclude==0,6)=NaN; end;
-
Create a variable which gets the final design
designincl=design(:,:);
-
Demean the covariates (not group EV's)
szdes=size(designincl); designincl2=designincl; if covariate==1; for i=1+numgp:szdes(2); designincl2(:,i)=designincl(:,i)-nanmean(designincl(:,i)); end; end;
-
Print to the screen the number of missing values and the design matrix name to the screen
numnan=length(find(isnan(designincl2))); disp(['There were this many NaNs in the design matrix: ' num2str(numnan)]); designincl2(isnan(designincl2))=0; disp('Your final design matrix is called designincl2');
-
Create a variable for the design.grp file
designgrp=ones(length(designincl2),1);
-
Print out the design.mat template
designincl2
Copy this design.mat output into the design.mat file in the place for the design matrix which is under the following output:
/NumWaves 1
/NumPoints 110
/PPheights 1.000000e+00
/Matrix
Then print the design.grp to the screen by typing designgrp in matlab and paste this output into the design.grp file in the place for the design group matrix which is under the following output:
/NumWaves 1
/NumPoints 110
/Matrix
For more information on group-level feats by flame1 see the FSL Higher Level Feat Output wiki
Script: /data/joy/BBL/projects/conteReproc2017/fearConditioningRun1/group_flameo_conte_nogrid.sh
Requires:
- Merged cope output for all subject you wish to include in your group-level feat (by conte_merge_images_mask.sh)
- Example:
/data/joy/BBL/studies/conte/subjectData/fearConditioningRun1/merged_copes/n110_bbr_linear_mini_block_run1_cope11.nii.gz
- Example:
- design.mat, design.con, and design.grp files in the group-level feat output directory you wish the group-level feat output to be saved to. You must create these as per any group-level feat (see makedesign.m steps above for design.mat and design.grp, you must create design.con by hand).
Output:
- Group-level/Higher-level feat output for the model you run
- Example
/data/joy/BBL/studies/conte/processedData/fearconditioningRun1/single_group_level_feats/single_group_linear_mini_block_n110
- Example
Script: /data/joy/BBL/projects/conteReproc2017/fearConditioningRun1/group_flameo_conte_nogrid.sh
-
Create a variable for the number of subjects you want to include in your group-level feat, and for the output path
nsubj=n110 #eg n61 #create a variable for the path to where the output images will go and where the design files exist wd=/data/joy/BBL/studies/conte/processedData/fearconditioningRun1/single_group_level_feats/single_group_linear_mini_block_${nsubj}
-
Create a variable which gets the full list of copes you wish to include in your group-level output
#variables for the level1 feat copes ----can be multiple copes e.g., "cope1 cope2 cope3 cope7" copes="cope1 cope2 cope3 cope4 cope5 cope6 cope7 cope8 cope9 cope10 cope11 cope12"
-
Create a variable for the suffix of the feat which you want to run flame1 (group-level feat) on
nickname="bbr_linear_mini_block"
-
Print out the working directory and feat name and if the working directory doesn't exist then exit the script
echo "working directory is $wd" echo "" echo "nickname is $nickname" echo "" if [ ! -d "$wd" ]; then echo "working directory not found!! exiting!" exit 1 fi echo "*********" echo "for all analyses, lev2 cope is $lev2_cope" echo "*******"
-
For each cope in the list defined above (by variable "copes"), create variables for the merged cope, varcope, and mask files created by the conte_merge_images_mask.sh script
for c in $copes; do echo "" echo "working on $c" #create variables for the merged cope, varcope, and mask files created by the conte_merge_images_mask.sh script cfile=$(ls -d /data/joy/BBL/studies/conte/subjectData/fearConditioningRun1/merged_copes/${nsubj}_${nickname}_run${run}_${c}.nii.gz) vfile=$(ls -d /data/joy/BBL/studies/conte/subjectData/fearConditioningRun1/merged_copes/${nsubj}_${nickname}_run${run}_var${c}.nii.gz) mask=/data/joy/BBL/studies/conte/subjectData/fearConditioningRun1/merged_copes/${nickname}_${nsubj}_run${run}_final_maskoverlap.nii.gz
-
Create variable for output dir within working directory defined above and the cope number appended
outdir=${nickname}_${nsubj}_${c} #create a variable for the outpath directory outpath=$(ls -d $wd/$outdir 2> /dev/null)
-
Run flameo on the cope, varcope, mask specified with the design files in the working directory
flameo --cope=$cfile --varcope=$vfile --mask=$mask --dm=${wd}/design.mat --tc=${wd}/design.con --cs=${wd}/design.grp --runmode=flame1 --logdir=${wd}/${outdir} --npo done
FSL Randomise was run using the output from the mini-block models detailed above. These were the models that showed the most robust results for the CONTE study and therefore they were utilized for the final analyses for the fear conditioning run1 Quarmley et. al manuscript. Randomise was run several different ways including voxelwise however detailed below is the 3-ROI-mask method that was utilized for the paper as it showed the most robust results.
- Make a 3 ROI merged mask of the vmPFC, bilateral amygdala, and bilateral anterior insula neurosynth ROIs detailed above. This was done by running fslmaths -add and merging the three ROI masks together. This mask is saved here:
/import/monstrum/conte_815814/scripts/functional/roi_merge_masks/3roi_merge_fmri_paper_03312017.nii.gz
- Run randomise with the following parameters:
-
threshold-free cluster enhancement (-T)
-
5,000 permutations (-n 5000)
-
the 3 ROI mask made in the previous step (-m [mask path])
-
A merged subject-level cope (-i [4D image]) (the example below uses mini block cope11 for all 96 version3 included subjects merged together)
-
A design matrix which is simply the same as a higher-level feat design matrix.
/NumWaves 1 /NumPoints 96 /PPheights 1.000000e+00 /Matrix 1 1 1 1 1 1 ....96 times
-
A contrast matrix which in this example below is two-sided so that you will obtain output in both the positive (CS+u > CS-) and negative (CS+u < CS-) directions
/ContrastName1 group mean /ContrastName2 group mean negative /NumWaves 1 /NumContrasts 2 /PPheights 1 /RequiredEffect 0.484 /Matrix 1 -1
The template for randomise is:
randomise -i <4D input image> -o <output file-rootname> -d <design.mat> -t <design.con> [options]
An example run from monstrum with the parameters detailed above:
randomise -i /import/monstrum/conte_815814/group_results/merged_images/n96_bbr_linear_mini_block_run1_cope11.nii.gz -o /import/monstrum/conte_815814/group_results/randomise/fmri_paper_2017/cope11_3roi_merge_03212017 -d /import/monstrum/conte_815814/group_results/run1/single_group_level_feats/all_subj_single_group_level_feats/single_group_all_subj_linear_mini_block_run1_n96/design.mat -t /import/monstrum/conte_815814/group_results/randomise/design_2tail.con -m /import/monstrum/conte_815814/scripts/functional/roi_merge_masks/3roi_merge_fmri_paper_03312017 -n 5000 -T