@@ -110,11 +110,50 @@ postprocess_confounds <- function(proc_files, cfg, processing_sequence,
110110 # TODO: consider whether to worry about notch filtering AROMA components if motion parameters or FD are in confound regressors
111111 # Regress out AROMA components, if requested (overwrites file in place)
112112 if (" apply_aroma" %in% processing_sequence ) {
113- lg $ info(" Removing AROMA noise components from confounds" )
114- confound_nii <- apply_aroma(confound_nii , out_file = confound_nii ,
115- mixing_file = proc_files $ melodic_mix , noise_ics = proc_files $ noise_ics ,
116- overwrite = TRUE , lg = lg , use_R = TRUE , fsl_img = fsl_img
117- )
113+ if (is.null(proc_files $ melodic_mix ) || ! checkmate :: test_file_exists(proc_files $ melodic_mix )) {
114+ to_log(lg , " warn" , " Cannot locate melodic mixing file; skipping AROMA regression for confounds." )
115+ } else if (is.null(proc_files $ noise_ics ) || length(proc_files $ noise_ics ) == 0 ) {
116+ to_log(lg , " info" , " No AROMA noise components provided; skipping regression for confounds." )
117+ } else if (! checkmate :: test_integerish(proc_files $ noise_ics , lower = 1 , any.missing = FALSE )) {
118+ to_log(lg , " warn" , " noise_ics must be a vector of positive integers; skipping AROMA regression for confounds." )
119+ } else {
120+ nonaggressive_val <- cfg $ apply_aroma $ nonaggressive
121+ nonaggressive_flag <- if (is.null(nonaggressive_val ) || is.na(nonaggressive_val )) TRUE else isTRUE(nonaggressive_val )
122+ exclusive_flag <- ! nonaggressive_flag
123+ mode_label <- if (exclusive_flag ) " aggressive" else " non-aggressive"
124+
125+ mixing_mat <- as.matrix(data.table :: fread(proc_files $ melodic_mix , header = FALSE , data.table = FALSE ))
126+ storage.mode(mixing_mat ) <- " double"
127+ if (nrow(mixing_mat ) != nrow(confounds_to_filt )) {
128+ to_log(lg , " warn" , " Mixing matrix has {nrow(mixing_mat)} rows but confounds have {nrow(confounds_to_filt)} timepoints; skipping AROMA regression for confounds." )
129+ } else if (ncol(mixing_mat ) == 0 ) {
130+ to_log(lg , " warn" , " Mixing matrix {proc_files$melodic_mix} has no components; skipping AROMA regression for confounds." )
131+ } else {
132+ comp_idx <- sort(unique(as.integer(proc_files $ noise_ics )))
133+ invalid_idx <- comp_idx [comp_idx < 1 | comp_idx > ncol(mixing_mat )]
134+ if (length(invalid_idx ) > 0 ) {
135+ to_log(lg , " warn" , " Dropping invalid AROMA component indices for confounds: {paste(invalid_idx, collapse = ', ')}" )
136+ comp_idx <- setdiff(comp_idx , invalid_idx )
137+ }
138+ if (length(comp_idx ) == 0 ) {
139+ lg $ info(" No valid AROMA noise components remain after filtering; skipping regression for confounds." )
140+ } else {
141+ to_log(lg , " info" , " Regressing {length(comp_idx)} AROMA noise components from confounds using {mode_label} mode." )
142+ confound_names <- colnames(confounds_to_filt )
143+ resid_mat <- lmfit_residuals_mat(
144+ Y = as.matrix(confounds_to_filt ),
145+ X = mixing_mat ,
146+ include_rows = rep(TRUE , nrow(mixing_mat )),
147+ add_intercept = FALSE ,
148+ regress_cols = comp_idx ,
149+ exclusive = exclusive_flag
150+ )
151+ colnames(resid_mat ) <- confound_names
152+ confounds_to_filt <- resid_mat
153+ confound_nii <- mat_to_nii(confounds_to_filt , ni_out = confound_nii )
154+ }
155+ }
156+ }
118157 }
119158
120159 # Temporally filter confounds, if requested (overwrites file in place)
0 commit comments