Skip to content

Commit

Permalink
Added functions move_betas_to_secondlvl()
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael-Sun committed Dec 1, 2023
1 parent ab264f9 commit 07248c8
Show file tree
Hide file tree
Showing 2 changed files with 219 additions and 0 deletions.
145 changes: 145 additions & 0 deletions Second_level_analysis_template_scripts/move_betas_to_secondlvl.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
function move_betas_to_secondlvl(firstlvl_dir, datadir, operation, varargin)
% MOVE_BETAS_TO_SECONDLVL Move beta images to a second-level analysis directory.
%
% This function moves or creates symbolic links to beta images from a first-level
% analysis directory to a second-level analysis directory. It is designed to be
% used with BIDS-formatted datasets and supports operations to either copy the
% beta images or create symbolic links.
%
% Inputs:
% firstlvl_dir - String. Path to the first-level analysis directory.
% datadir - String. Path to the destination directory for the second-level analysis.
% operation - String. Specify 'copy' to copy the files, or 'symlink' to create symbolic links.
% varargin - (Optional) Cell array. Specific conditions to process,
% passed in as a cell-array of char-strings e.g., {'hot', 'warm', 'imagine'}.
%
% Outputs:
% None. This function operates by side effects (file operations).
%
% Example usage:
% move_betas_to_secondlvl('/CANlab/labdata/data/WASABI/derivatives/canlab_firstlvl/sub-SID00XXXX/ses-0X/func/firstlvl/bodymap', ...
% '/CANlab/labdata/projects/WASABI/WASABI_N_of_Few/analysis/WASABI-NofFew_BodyMap/data', 'symlink');
%
% Notes:
% - This function is intended to be used as part of a SLURM job script.
% - Requires appropriate permissions to read from the source and write to the destination directories.
% - Symbolic link creation is platform dependent and may require administrative privileges.
%
% Author: Michael Sun, Ph.D.
% Created: 12/1/2023
% Last Modified: 12/1/2023

% Extract sub, ses, and task using fileparts
[path, task, ~] = fileparts(firstlvl_dir);

% Extract sub, ses, and task from name_parts
% sub = char(strcat('sub-', extractBetween(path, 'sub-', [filesep, 'ses']))); % Assuming sub-SID*
% ses = char(strcat('ses-', extractBetween(path, 'ses-', [filesep, 'func']))); % Assuming ses-*

% Creating a pattern that matches either '/' or '\'
slashPattern = '[/\\]';

% Extracting the subject ID
subPattern = strcat('sub-', '.*?(?=', slashPattern, 'ses)');
subMatch = regexp(path, subPattern, 'match');
if ~isempty(subMatch)
sub = subMatch{1};
else
sub = '';
end

% Extracting the session ID
sesPattern = strcat('ses-', '.*?(?=', slashPattern, 'func)');
sesMatch = regexp(path, sesPattern, 'match');
if ~isempty(sesMatch)
ses = sesMatch{1};
else
ses = '';
end

% Extracting task
task=['task-', task];

load(fullfile(firstlvl_dir, sub, 'SPM.mat'));
if ~exist('varargin', 'var')
conditions=varargin;
end

if ~exist('conditions', 'var')
conditions={};
end

if isempty(conditions)
% If no conditions are passed in, generate a list of conditions
% from SPM.xX.name that don't include constants or noise (R)
% regressors.

% Regular expression pattern
% Pattern for 'R' followed by one or more digits, or 'constant'
pattern = '(R\d+|constant)$';

% Finding indices of cells that do not match the pattern
idx = cellfun(@isempty, regexp(SPM.xX.name, pattern));

% The cells that do not contain 'R' followed by numbers or 'constant'
conditions = SPM.xX.name(idx);

% Remove 'Sn(*) ' prefix
pattern = 'Sn\(\d+\) ';
% Stripping the pattern from each string in result using
% regex-replace
conditions = regexprep(conditions, pattern, '');
% Remove '* *bf(*)' suffix
pattern = ' \*bf\(\d+\)';
conditions = regexprep(conditions, pattern, '');

% Extract only the unique conditions
conditions=unique(conditions);
end

for k = 1:numel(conditions)
% Search for the beta number that corresponds to the condition in
% question.
betanum=find(contains(SPM.xX.name, conditions{k}));
if ~isempty(betanum)
%
for i = 1:numel(betanum)
betafile=fullfile(firstlvl_dir, sub, ['beta_', sprintf('%04d',betanum(i)),'.nii']);
if ~isempty(sub)
bidsname=[sub,'_'];
end
if ~isempty(ses)
bidsname=[bidsname, ses,'_'];
end
run=['run-',char(extractBetween(SPM.xX.name(betanum(i)), 'Sn(', ')'))];
bidsname=sprintf('%s%s_%s.nii', bidsname, task, run);

destination_folder=fullfile(datadir,sub,conditions{k});

% Check if the destination folder exists, and create it if it does not
if ~exist(destination_folder, 'dir')
mkdir(destination_folder);
end

if strcmp(operation, 'copy')
copyfile(betafile, destination_folder);
new_betafile=fullfile(datadir,sub,conditions{k}, ['beta_', sprintf('%04d',betanum(i)),'.nii']);
renamed_betafile=fullfile(datadir,sub,conditions{k}, bidsname);
movefile(new_betafile, renamed_betafile);
elseif strcmp(operation, 'symlink')
% Create symlink using system command
% Rename the file into BIDS-format
dest_link_path = fullfile(destination_folder, bidsname);
if ispc % Check if the system is Windows
cmd = ['cmd.exe /C mklink "' dest_link_path '" "' betafile '"'];
else
cmd = sprintf('ln -s %s %s', betafile, dest_link_path);
end
system(cmd);
else
error('Invalid operation. Choose either "copy" or "symlink".')
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/bin/bash
#SBATCH --job-name=movebetas_bodymap # Job name
#SBATCH --output=log/movebetas/movebetas_bodymap_%a.out # Output file name, %a is replaced by the array index
#SBATCH --error=log/movebetas/movebetas_bodymap_%a.err # Error output file name
#SBATCH --ntasks=1 # Number of MPI ranks
#SBATCH --cpus-per-task=1 # Number of cores per task
#SBATCH --time=24:00:00 # Wall time
#SBATCH --partition=normal # Partition name
#SBATCH --array=0-108 # Array indices, replace with the number of first-level directories you have -1
#SBATCH --account=DBIC
#SBATCH --partition=standard
# Email notifications (comma-separated options: BEGIN,END,FAIL)
#SBATCH --mail-type=FAIL
#SBATCH --mail-type=END

# Output and error log directories
output_log_dir="log/movebetas"
error_log_dir="log/movebetas"

# Create the directories if they don't exist
mkdir -p "$output_log_dir"
mkdir -p "$error_log_dir"

hostname

# Enable extended globbing
shopt -s extglob

# FOR DEBUGGING
# SLURM_ARRAY_TASK_ID=0

# Set the directory paths
firstlvl_dir="/dartfs-hpc/rc/lab/C/CANlab/labdata/data/WASABI/derivatives/canlab_firstlvl"
# Second-level batch analysis directory
data_dir="/dartfs-hpc/rc/lab/C/CANlab/labdata/projects/WASABI/WASABI_N_of_Few/analysis/WASABI-NofFew_BodyMap/data"

# Set your conditions
# Define the conditions array in Bash
# conditions=("hot_leftface" "warm_leftface" "imagine_leftface"
# "hot_rightface" "warm_rightface" "imagine_rightface"
# "hot_leftarm" "warm_leftarm" "imagine_leftarm"
# "hot_rightarm" "warm_rightarm" "imagine_rightarm"
# "hot_leftleg" "warm_leftleg" "imagine_leftleg"
# "hot_rightleg" "warm_rightleg" "imagine_rightleg"
# "hot_chest" "warm_chest" "imagine_chest"
# "hot_abdomen" "warm_abdomen" "imagine_abdomen")

# Initialize an empty array to store the quoted strings
# quoted_conditions=()
# for condition in "${conditions[@]}"; do
# quoted_conditions+=("'$condition'")
# done

# Convert the quoted_conditions array into a comma-separated string
# conditions_str=$(IFS=,; echo "{${quoted_conditions[*]}}")

# If you ran many first-level GLMs, e.g., by subject or by session, you may have to do this:
# Find all the directories matching the pattern 'firstlvl/bodymapST+([1-2])'
# map_dirs=("$firstlvl_dir"/sub-*/ses-*/func/firstlvl/bodymapST+([1-2]))
map_dirs=("$firstlvl_dir"/sub-*/ses-*/func/firstlvl/bodymap)

sub=$(basename "$(dirname "$(dirname "$(dirname "$(dirname "${map_dirs[SLURM_ARRAY_TASK_ID]}")")")")")
ses=$(basename "$(dirname "$(dirname "$(dirname "${map_dirs[SLURM_ARRAY_TASK_ID]}")")")")
task=$(basename "${map_dirs[SLURM_ARRAY_TASK_ID]}")

# Print the extracted components for each 'map_dir'
echo "sub: $sub, ses: $ses, task: $task"
echo "conditions: '${conditions_str}'"

module load matlab

# Run the MATLAB function
# srun matlab -nodisplay -r "addpath(genpath('//dartfs-hpc/rc/lab/C/CANlab/modules/spm12')); addpath(genpath('//dartfs-hpc/rc/lab/C/CANlab/labdata/projects/WASABI/software')); move_betas_to_secondlvl('${map_dirs[${SLURM_ARRAY_TASK_ID}]}', '${data_dir}', 'symlink', ${conditions_str})"
srun matlab -nodisplay -r "addpath(genpath('//dartfs-hpc/rc/lab/C/CANlab/modules/spm12')); addpath(genpath('//dartfs-hpc/rc/lab/C/CANlab/labdata/projects/WASABI/software')); move_betas_to_secondlvl('${map_dirs[${SLURM_ARRAY_TASK_ID}]}', '${data_dir}', 'symlink')"

0 comments on commit 07248c8

Please sign in to comment.