FSL Feat Errors

Summary of what happened:

Hi all,

I am trying to run FSL feat in terminal with the .fsf file but it seems to just be running without anything happening. I am trying to run contrasts on a block design task where the images have already been processed using fmriprep. my script and design files are below. Any suggestions?

Command used (and if a helper script was used, a link to the helper script or the command generated):


#!/bin/bash

# Script to create and run stats-only FEAT analyses for subjects 1-10
# Optimized for preprocessed data from fMRIPrep - using prepared motion parameters

# Load FSL
module load fsl/6.0.3-cuda9.1

# Directories
FMRIPREP_DIR="/work/cnelab/dtmt_fmri/mri/bids/derivatives/fmriprep"
OUTPUT_BASE_DIR="/work/cnelab/dtmt_fmri/mri/analysis/fsl_analysis/dtmt_fmri"
CONFOUNDS_BASE_DIR="/work/cnelab/dtmt_fmri/mri/analysis/fsl_analysis/dtmt_fmri"
TIMING_DIR="/work/cnelab/dtmt_fmri/mri/analysis/timing_files"

# Parameters
TR=0.8
Z_THRESH=2.8  # p<0.005 threshold
CLUSTER_P_THRESH=0.05  # Cluster-level correction

# Create master output directory if it doesn't exist
mkdir -p "$OUTPUT_BASE_DIR"

# Function to process a single subject
process_subject() {
    local subject_num=$1
    local SUBJECT_ID="sub-${subject_num}"
    
    echo "========================================================="
    echo "Processing $SUBJECT_ID"
    echo "========================================================="
    
    # Create subject-specific directories
    local OUTPUT_DIR="${OUTPUT_BASE_DIR}/${SUBJECT_ID}"
    mkdir -p "$OUTPUT_DIR"
    
    # Input data paths
    local FUNC_DATA="${FMRIPREP_DIR}/${SUBJECT_ID}/func/${SUBJECT_ID}_task-dtmt_space-MNI152NLin2009cAsym_res-2_desc-preproc_bold.nii.gz"
    local MASK_FILE="${FMRIPREP_DIR}/${SUBJECT_ID}/func/${SUBJECT_ID}_task-dtmt_space-MNI152NLin2009cAsym_res-2_desc-brain_mask.nii.gz"
    local CONFOUNDS_FILE="${CONFOUNDS_BASE_DIR}/${SUBJECT_ID}/confounds/motion_params.txt"
    
    # Check if files exist
    if [ ! -f "$FUNC_DATA" ]; then
        echo "ERROR: Functional data not found: $FUNC_DATA"
        return 1
    fi
    
    if [ ! -f "$MASK_FILE" ]; then
        echo "ERROR: Mask file not found: $MASK_FILE"
        return 1
    fi
    
    # Check timing files
    for cond in timing_file_motor timing_file_a timing_file_b timing_file_fix; do
        if [ ! -f "${TIMING_DIR}/${cond}.txt" ]; then
            echo "ERROR: Timing file not found: ${TIMING_DIR}/${cond}.txt"
            echo "Make sure you've run the timing extraction script first"
            return 1
        fi
    done
    
    # Check for confounds file
    if [ ! -f "$CONFOUNDS_FILE" ]; then
        echo "ERROR: Confounds file not found: $CONFOUNDS_FILE"
        return 1
    fi
    
    # Additional data validation
    # Check dimensions and properties of the functional data
    local DIMS=$(fslhd "$FUNC_DATA" | grep -E "^dim[1-4]" | awk '{print $2}' | paste -sd "x")
    local NVOLS=$(fslnvols "$FUNC_DATA")
    echo "Functional data dimensions: $DIMS with $NVOLS volumes"
    
    # Check mask coverage (percentage of non-zero voxels)
    local MASK_COVERAGE=$(fslstats "$MASK_FILE" -M)
    echo "Mask coverage: $MASK_COVERAGE (should be close to 1.0 for binary mask)"
    
    # Create a stats-only design.fsf file
    local DESIGN_FILE="${OUTPUT_DIR}/design_stats_only.fsf"
    echo "Creating stats-only FEAT design file: $DESIGN_FILE"
    
    cat > "$DESIGN_FILE" << EOF
# FEAT version number
set fmri(version) 6.00

# Analysis level
set fmri(level) 1

# FEAT directory
set fmri(outputdir) "${OUTPUT_DIR}/stats_only.feat"

# Input data
set feat_files(1) "$FUNC_DATA"

# TR(s)
set fmri(tr) $TR

# Total volumes
set fmri(npts) $NVOLS

# Delete volumes
set fmri(ndelete) 0

# Pre-stats
# Skip all preprocessing
set fmri(preprocessing) 0

# Brain/background threshold
set fmri(brain_thresh) 0  # Doesn't matter with a provided mask

# Use alternative mask
set fmri(alternative_mask) 1
set fmri(alternative_mask_file) "$MASK_FILE"

# Stats mode - using FILM
set fmri(st) 1

# Enable prewhitening for better statistical accuracy
set fmri(prewhiten_yn) 1

# No motion correction
set fmri(mc) 0
set fmri(sh_yn) 0

# No slice timing correction
set fmri(st) 0

# No BET
set fmri(bet_yn) 0

# No spatial smoothing
set fmri(smooth) 0

# No temporal filtering
set fmri(temphp_yn) 0
set fmri(templp_yn) 0

# Add confound EVs from motion parameters
set fmri(confoundevs) 1
set confoundev_files(1) "$CONFOUNDS_FILE"

# EV 1: Fix
set fmri(evtitle1) "Fix"
set fmri(shape1) 3
set fmri(convolve1) 0
set fmri(custom1) "${TIMING_DIR}/timing_file_fix.txt"

# EV 2: Motor
set fmri(evtitle2) "Motor"
set fmri(shape2) 3
set fmri(convolve2) 3
set fmri(custom2) "${TIMING_DIR}/timing_file_motor.txt"

# EV 3: A
set fmri(evtitle3) "A"
set fmri(shape3) 3
set fmri(convolve3) 3
set fmri(custom3) "${TIMING_DIR}/timing_file_a.txt"

# EV 4: B
set fmri(evtitle4) "B"
set fmri(shape4) 3
set fmri(convolve4) 3
set fmri(custom4) "${TIMING_DIR}/timing_file_b.txt"

# Number of EVs
set fmri(evs_orig) 4
set fmri(evs_real) 4
set fmri(ncon_real) 7
set fmri(nftests_real) 0

# Contrast 1: Motor - Fix
set fmri(conname_real.1) "motor-fix"
set fmri(con_real1.1) 0
set fmri(con_real1.2) 1
set fmri(con_real1.3) 0
set fmri(con_real1.4) 0

# Contrast 2: A - Fix
set fmri(conname_real.2) "a-fix"
set fmri(con_real2.1) 0
set fmri(con_real2.2) 0
set fmri(con_real2.3) 1
set fmri(con_real2.4) 0

# Contrast 3: B - Fix
set fmri(conname_real.3) "b-fix"
set fmri(con_real3.1) 0
set fmri(con_real3.2) 0
set fmri(con_real3.3) 0
set fmri(con_real3.4) 1

# Contrast 4: A - B
set fmri(conname_real.4) "a-b"
set fmri(con_real4.1) 0
set fmri(con_real4.2) 0
set fmri(con_real4.3) 1
set fmri(con_real4.4) -1

# Contrast 5: B - A
set fmri(conname_real.5) "b-a"
set fmri(con_real5.1) 0
set fmri(con_real5.2) 0
set fmri(con_real5.3) -1
set fmri(con_real5.4) 1

# Contrast 6: (Motor + A + B) - 3*Fix
set fmri(conname_real.6) "task-fix"
set fmri(con_real6.1) -3
set fmri(con_real6.2) 1
set fmri(con_real6.3) 1
set fmri(con_real6.4) 1

# Contrast 7: (A + B) - 2*Motor
set fmri(conname_real.7) "cogtask-motor"
set fmri(con_real7.1) 0
set fmri(con_real7.2) -2
set fmri(con_real7.3) 1
set fmri(con_real7.4) 1

# Don't use registration (data already in standard space)
set fmri(reg_yn) 0

# Don't run non-linear reg
set fmri(nonlinear_yn) 0

# Z threshold
set fmri(z_thresh) $Z_THRESH

# Z threshold type: 1 = uncorrected, 2 = voxel, 3 = cluster
set fmri(thresh) 3

# Cluster p-threshold
set fmri(prob_thresh) $CLUSTER_P_THRESH

# Minimum cluster size in voxels
set fmri(threshmask) ""
set fmri(minclustersize) 0

# Full model setup
set fmri(mixed_yn) 1
set fmri(factmix) 1
set fmri(groupmem.1) 1
set fmri(withinmix) standard
EOF
    
    echo "Running FEAT with command-line mode for $SUBJECT_ID..."
    # Use feat_model to generate the model
    feat_model "$OUTPUT_DIR/stats_only"
    
    if [ $? -ne 0 ]; then
        echo "ERROR: feat_model failed for $SUBJECT_ID"
        return 1
    fi
    
    # Pre-create the output directory
    mkdir -p "${OUTPUT_DIR}/stats_only.feat/stats"
    
    # Run FEAT's film_gls directly
    echo "Running film_gls..."
    film_gls --in="${FUNC_DATA}" \
             --rn="${OUTPUT_DIR}/stats_only.feat" \
             --pd="${OUTPUT_DIR}/stats_only.feat/design.mat" \
             --tcon="${OUTPUT_DIR}/stats_only.feat/design.con" \
             --mode=1 \
             --out="${OUTPUT_DIR}/stats_only.feat/stats" \
             --mask="${MASK_FILE}" \
             --epith=1000 \
             --con_index=1 \
             --con_name=motor-fix \
             --con_index=2 \
             --con_name=a-fix \
             --con_index=3 \
             --con_name=b-fix \
             --con_index=4 \
             --con_name=a-b \
             --con_index=5 \
             --con_name=b-a \
             --con_index=6 \
             --con_name=task-fix \
             --con_index=7 \
             --con_name=cogtask-motor
    
    if [ $? -ne 0 ]; then
        echo "ERROR: film_gls failed for $SUBJECT_ID"
        return 1
    fi
    
    # Run FEAT's cluster
    echo "Running cluster thresholding..."
    for i in {1..7}; do
        cluster --in="${OUTPUT_DIR}/stats_only.feat/stats/zstat${i}" \
                --thresh=$Z_THRESH \
                --pthresh=$CLUSTER_P_THRESH \
                --oindex="${OUTPUT_DIR}/stats_only.feat/cluster_mask_zstat${i}" \
                --olmax="${OUTPUT_DIR}/stats_only.feat/lmax_zstat${i}.txt" \
                --mask="${MASK_FILE}"
    done
    
    if [ -f "${OUTPUT_DIR}/stats_only.feat/stats/cope1.nii.gz" ]; then
        echo "FEAT analysis complete for $SUBJECT_ID. Results are in: ${OUTPUT_DIR}/stats_only.feat"
        return 0
    else
        echo "ERROR: FEAT analysis failed for $SUBJECT_ID"
        return 1
    fi
}

# Create list for valid subjects
valid_subjects_file="${OUTPUT_BASE_DIR}/valid_feat_dirs.txt"
> "$valid_subjects_file"

# Process subjects 1-10
successful=0
failed=0

for i in {1..10}; do
    if process_subject $i; then
        echo "${OUTPUT_BASE_DIR}/sub-${i}/stats_only.feat" >> "$valid_subjects_file"
        ((successful++))
    else
        ((failed++))
    fi
    echo ""
done

# Function to create group analysis design file for a specific contrast
create_group_design() {
    local contrast_num=$1
    local contrast_name=$2
    
    echo "Creating group analysis design file for contrast $contrast_num: $contrast_name..."
    local group_design="${OUTPUT_BASE_DIR}/group_design_contrast${contrast_num}.fsf"
    
    # Create basic higher-level design file
    cat > "$group_design" << EOF
# FEAT version number
set fmri(version) 6.00

# Higher-level analysis
set fmri(level) 2

# FEAT directory
set fmri(outputdir) "${OUTPUT_BASE_DIR}/group_contrast${contrast_num}_${contrast_name}.gfeat"

# Number of inputs
set fmri(npts) $successful

# Mixed effects: 3 = FLAME 1
set fmri(mixed_yn) 3

# Higher-level model
set fmri(pluginname) "flame1"

# Use lower-level copes
set fmri(forcehigherlevel_yn) 1

# Add confound EVs text file
set fmri(confoundevs) 0

# Don't add FE stats
set fmri(fe1_yn) 0

# Z threshold
set fmri(z_thresh) $Z_THRESH

# Z threshold type: 1 = uncorrected, 2 = voxel, 3 = cluster
set fmri(thresh) 3

# Cluster p-threshold
set fmri(prob_thresh) $CLUSTER_P_THRESH

# Minimum cluster size in voxels
set fmri(threshmask) ""
set fmri(minclustersize) 0

# Motion correction
set fmri(mc) 0

# Which contrast
set fmri(conindex) $contrast_num

# Use one-sample group mean
set fmri(con_mode) 1
set fmri(con_mode1) 1

# Design matrix directory
set fmri(evs_orig) 1
set fmri(evs_real) 1
set fmri(evtitle1) "Group_Mean"

# Group membership for input 1
set fmri(groupmem.1) 1

# Input FEAT directories
EOF
    
    # Add all subject FEAT directories
    subj_count=1
    while read -r feat_dir; do
        echo "set feat_files($subj_count) \"$feat_dir\"" >> "$group_design"
        ((subj_count++))
    done < "$valid_subjects_file"
    
    echo "Group analysis design file created: $group_design"
    return 0
}

# If we have enough successful subjects, create group analysis design files
if [ $successful -ge 2 ]; then
    echo "Creating group analysis design files for all contrasts..."
    
    # Define contrast names for better file naming
    CONTRAST_NAMES=("" "motor-fix" "a-fix" "b-fix" "a-b" "b-a" "task-fix" "cogtask-motor")
    
    # Create design files for all contrasts
    for ((i=1; i<=7; i++)); do
        create_group_design $i "${CONTRAST_NAMES[$i]}"
    done
    
    # Create a single script to run all group analyses
    group_run_script="${OUTPUT_BASE_DIR}/run_all_group_analyses.sh"
    echo "#!/bin/bash" > "$group_run_script"
    echo "" >> "$group_run_script"
    echo "# Script to run all group analyses" >> "$group_run_script"
    echo "# Load FSL" >> "$group_run_script"
    echo "module load fsl/6.0.3-cuda9.1" >> "$group_run_script"
    echo "" >> "$group_run_script"
    
    for ((i=1; i<=7; i++)); do
        echo "echo \"Running group analysis for contrast $i: ${CONTRAST_NAMES[$i]}...\"" >> "$group_run_script"
        echo "feat -d ${OUTPUT_BASE_DIR}/group_design_contrast${i}.fsf" >> "$group_run_script"
        echo "" >> "$group_run_script"
    done
    
    chmod +x "$group_run_script"
    echo "Created script to run all group analyses: $group_run_script"
fi

# Summary
echo "========================================================="
echo "Analysis Summary:"
echo "Successful subjects: $successful"
echo "Failed subjects: $failed"
echo "List of valid FEAT directories saved to: $valid_subjects_file"
echo ""
if [ $successful -ge 2 ]; then
    echo "Group analysis design files created for all contrasts"
    echo "To run all group analyses: ${OUTPUT_BASE_DIR}/run_all_group_analyses.sh"
    echo "Or run individual contrasts with: feat -d ${OUTPUT_BASE_DIR}/group_design_contrast<N>.fsf"
else
    echo "Not enough successful subjects for group analysis"
fi
echo "========================================================="

Version:

Environment (Docker, Singularity / Apptainer, custom installation):

Data formatted according to a validatable standard? Please provide the output of the validator:

PASTE VALIDATOR OUTPUT HERE

Relevant log outputs (up to 20 lines):

PASTE LOG OUTPUT HERE

Screenshots / relevant information:


Hi @ET_123456, have you checked the files within the logs directory to see if any errors have occurred?