Skip to content

Commit 4b70329

Browse files
Merge pull request #24 from UNCDEPENdLab/codex/validate-fmriprep-outputs-before-postprocessing
Validate fmriprep completion before postprocessing
2 parents dc8a387 + 5094573 commit 4b70329

2 files changed

Lines changed: 90 additions & 0 deletions

File tree

R/pipeline_functions.R

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,84 @@ validate_exists <- function(input, description = "", directory = FALSE, prompt_c
181181
return(TRUE)
182182
}
183183

184+
#' Check whether a pipeline step is complete
185+
#'
186+
#' Determines if the expected output directory and `.complete` marker
187+
#' are present for a given subject/session and processing step.
188+
#'
189+
#' @param scfg Study configuration list
190+
#' @param sub_id Subject identifier
191+
#' @param ses_id Optional session identifier
192+
#' @param step_name Name of the processing step
193+
#' @param pp_stream Name of the postprocessing stream when `step_name` is
194+
#' "postprocess"
195+
#' @return List containing `complete` (logical), `dir`, and
196+
#' `complete_file`
197+
#' @keywords internal
198+
is_step_complete <- function(scfg, sub_id, ses_id = NULL,
199+
step_name, pp_stream = NULL) {
200+
checkmate::assert_choice(step_name,
201+
c("bids_conversion", "mriqc", "fmriprep", "aroma", "postprocess"))
202+
if (is.null(ses_id) || is.na(ses_id)) ses_id <- NULL
203+
204+
session_level <- step_name %in% c("bids_conversion", "postprocess")
205+
name_tag <- step_name
206+
if (step_name == "postprocess") {
207+
checkmate::assert_string(pp_stream)
208+
name_tag <- glue("{step_name}_{pp_stream}")
209+
}
210+
211+
sub_str <- glue("_sub-{sub_id}")
212+
if (session_level && !is.null(ses_id)) {
213+
sub_str <- glue("{sub_str}_ses-{ses_id}")
214+
}
215+
216+
complete_file <- file.path(
217+
scfg$metadata$log_directory,
218+
glue("sub-{sub_id}"),
219+
glue(".{name_tag}{sub_str}_complete")
220+
)
221+
222+
out_dir <- switch(step_name,
223+
bids_conversion = if (session_level && !is.null(ses_id)) {
224+
file.path(scfg$metadata$bids_directory, glue("sub-{sub_id}"),
225+
glue("ses-{ses_id}"))
226+
} else {
227+
file.path(scfg$metadata$bids_directory, glue("sub-{sub_id}"))
228+
},
229+
mriqc = if (!is.null(ses_id)) {
230+
file.path(scfg$metadata$mriqc_directory, glue("sub-{sub_id}"),
231+
glue("ses-{ses_id}"))
232+
} else {
233+
file.path(scfg$metadata$mriqc_directory, glue("sub-{sub_id}"))
234+
},
235+
fmriprep = if (!is.null(ses_id)) {
236+
file.path(scfg$metadata$fmriprep_directory, glue("sub-{sub_id}"),
237+
glue("ses-{ses_id}"))
238+
} else {
239+
file.path(scfg$metadata$fmriprep_directory, glue("sub-{sub_id}"))
240+
},
241+
aroma = if (!is.null(ses_id)) {
242+
file.path(scfg$metadata$fmriprep_directory, glue("sub-{sub_id}"),
243+
glue("ses-{ses_id}"))
244+
} else {
245+
file.path(scfg$metadata$fmriprep_directory, glue("sub-{sub_id}"))
246+
},
247+
postprocess = if (!is.null(ses_id)) {
248+
file.path(scfg$metadata$fmriprep_directory, glue("sub-{sub_id}"),
249+
glue("ses-{ses_id}"))
250+
} else {
251+
file.path(scfg$metadata$fmriprep_directory, glue("sub-{sub_id}"))
252+
}
253+
)
254+
255+
complete <- checkmate::test_directory_exists(out_dir) &&
256+
checkmate::test_file_exists(complete_file)
257+
258+
list(complete = complete, dir = out_dir, complete_file = complete_file)
259+
}
260+
261+
184262
#' helper function to extract capturing groups from a string
185263
#' @param strings a character vector containing the strings to be processed
186264
#' @param pattern a regex pattern to match the strings

R/process_subject.R

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,18 @@ process_subject <- function(scfg, sub_cfg = NULL, steps = NULL, postprocess_stre
182182
## Handle aroma
183183
aroma_id <- submit_step("aroma", parent_ids = c(bids_conversion_ids, fmriprep_id))
184184

185+
## If postprocessing is requested without rerunning fmriprep, validate
186+
## that the expected fmriprep outputs exist before scheduling jobs
187+
if (isTRUE(steps["postprocess"]) && !isTRUE(steps["fmriprep"])) {
188+
chk <- is_step_complete(scfg, sub_id, step_name = "fmriprep")
189+
if (!chk$complete) {
190+
lg$warn(glue(
191+
"Exiting process_subject for {sub_id} because fmriprep outputs are missing (expected {chk$dir} and {basename(chk$complete_file)})"
192+
))
193+
return(TRUE)
194+
}
195+
}
196+
185197
## Handle postprocessing (session-level, multiple configs)
186198
postprocess_ids <- c()
187199
if (isTRUE(steps["postprocess"])) {

0 commit comments

Comments
 (0)