Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 40 additions & 2 deletions R/postprocess_confounds.R
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ postprocess_confounds <- function(proc_files, cfg, processing_sequence,
#' `motion_param_<1,25>` expands to `motion_param_1` and
#' `motion_param_25`. Patterns without angle brackets are treated as
#' regular expressions evaluated against the available column names.
#' In addition, common motion-confound sets can be requested using the
#' shortcuts `"6p"`, `"12p"`, `"24p"`, and `"36p"` which expand to the
#' corresponding standard collections of parameters.
#'
#' @param patterns Character vector of column patterns.
#' @param available Character vector of available column names.
Expand All @@ -198,8 +201,43 @@ postprocess_confounds <- function(proc_files, cfg, processing_sequence,
expand_confound_columns <- function(patterns = NULL, available) {
if (is.null(patterns) || length(patterns) == 0 || all(is.na(patterns))) return(NULL) # nothing to expand
checkmate::assert_character(patterns, all.missing = FALSE)
patterns <- na.omit(patterns) # just in case
checkmate::assert_character(available)
patterns <- na.omit(patterns) # just in case
checkmate::assert_character(available)

# expand standard motion/confound sets if present
shortcuts <- list(
"6p" = c("rot_x", "rot_y", "rot_z", "trans_x", "trans_y", "trans_z"),
"12p" = c(
"rot_x", "rot_x_derivative1", "rot_y", "rot_y_derivative1",
"rot_z", "rot_z_derivative1", "trans_x", "trans_x_derivative1",
"trans_y", "trans_y_derivative1", "trans_z", "trans_z_derivative1"
),
"24p" = c(
"rot_x", "rot_x_derivative1", "rot_x_derivative1_power2", "rot_x_power2",
"rot_y", "rot_y_derivative1", "rot_y_derivative1_power2", "rot_y_power2",
"rot_z", "rot_z_derivative1", "rot_z_derivative1_power2", "rot_z_power2",
"trans_x", "trans_x_derivative1", "trans_x_derivative1_power2", "trans_x_power2",
"trans_y", "trans_y_derivative1", "trans_y_derivative1_power2", "trans_y_power2",
"trans_z", "trans_z_derivative1", "trans_z_derivative1_power2", "trans_z_power2"
),
"36p" = c(
"csf", "csf_derivative1", "csf_derivative1_power2", "csf_power2",
"global_signal", "global_signal_derivative1", "global_signal_derivative1_power2",
"global_signal_power2",
"rot_x", "rot_x_derivative1", "rot_x_derivative1_power2", "rot_x_power2",
"rot_y", "rot_y_derivative1", "rot_y_derivative1_power2", "rot_y_power2",
"rot_z", "rot_z_derivative1", "rot_z_derivative1_power2", "rot_z_power2",
"trans_x", "trans_x_derivative1", "trans_x_derivative1_power2", "trans_x_power2",
"trans_y", "trans_y_derivative1", "trans_y_derivative1_power2", "trans_y_power2",
"trans_z", "trans_z_derivative1", "trans_z_derivative1_power2", "trans_z_power2",
"white_matter", "white_matter_derivative1", "white_matter_derivative1_power2",
"white_matter_power2"
)
)
if (any(patterns %in% names(shortcuts))) {
expanded <- unlist(shortcuts[patterns[patterns %in% names(shortcuts)]], use.names = FALSE)
patterns <- c(setdiff(patterns, names(shortcuts)), expanded)
}

res <- unlist(lapply(patterns, function(pat) {
if (is.na(pat) || pat == "") return(character())
Expand Down
47 changes: 47 additions & 0 deletions tests/testthat/test-expand_confound_columns.R
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,50 @@ test_that("expand_confound_columns expands regex and angle brackets", {
# ensure that bad regexs return nothing
expect_null(expand_confound_columns("csfsdflkj", available))
})

test_that("expand_confound_columns expands motion/confound shortcuts", {
available <- c(
"csf", "csf_derivative1", "csf_derivative1_power2", "csf_power2",
"global_signal", "global_signal_derivative1", "global_signal_derivative1_power2",
"global_signal_power2",
"rot_x", "rot_x_derivative1", "rot_x_derivative1_power2", "rot_x_power2",
"rot_y", "rot_y_derivative1", "rot_y_derivative1_power2", "rot_y_power2",
"rot_z", "rot_z_derivative1", "rot_z_derivative1_power2", "rot_z_power2",
"trans_x", "trans_x_derivative1", "trans_x_derivative1_power2", "trans_x_power2",
"trans_y", "trans_y_derivative1", "trans_y_derivative1_power2", "trans_y_power2",
"trans_z", "trans_z_derivative1", "trans_z_derivative1_power2", "trans_z_power2",
"white_matter", "white_matter_derivative1", "white_matter_derivative1_power2",
"white_matter_power2"
)

expect_setequal(
expand_confound_columns("6p", available),
c("rot_x", "rot_y", "rot_z", "trans_x", "trans_y", "trans_z")
)

expect_setequal(
expand_confound_columns("12p", available),
c(
"rot_x", "rot_x_derivative1", "rot_y", "rot_y_derivative1",
"rot_z", "rot_z_derivative1", "trans_x", "trans_x_derivative1",
"trans_y", "trans_y_derivative1", "trans_z", "trans_z_derivative1"
)
)

expect_setequal(
expand_confound_columns("24p", available),
c(
"rot_x", "rot_x_derivative1", "rot_x_derivative1_power2", "rot_x_power2",
"rot_y", "rot_y_derivative1", "rot_y_derivative1_power2", "rot_y_power2",
"rot_z", "rot_z_derivative1", "rot_z_derivative1_power2", "rot_z_power2",
"trans_x", "trans_x_derivative1", "trans_x_derivative1_power2", "trans_x_power2",
"trans_y", "trans_y_derivative1", "trans_y_derivative1_power2", "trans_y_power2",
"trans_z", "trans_z_derivative1", "trans_z_derivative1_power2", "trans_z_power2"
)
)

expect_setequal(
expand_confound_columns("36p", available),
available
)
})
4 changes: 4 additions & 0 deletions vignettes/postprocessing.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ or numeric ranges inside angle brackets. For example
pattern like `^trans_` will match all six motion parameters. This expansion
is implemented in `expand_confound_columns()`.【F:R/postprocess_functions.R†L996-L1036】

Standard motion-confound bundles can also be selected using shortcuts such as
`"6p"`, `"12p"`, `"24p"`, or `"36p"` to request common sets of motion
parameters and their derivatives/squared terms.

Filtered confounds (listed in `columns`) undergo the same temporal
filtering as the BOLD data, while unfiltered confounds (listed in
`noproc_columns`) are appended without processing. Typical unfiltered
Expand Down
Loading