Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
7 changes: 7 additions & 0 deletions conf/modules/harmonization.config
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ includeConfig '../../subworkflows/nf-neuro/harmonization/nextflow.config'

process {
withName: ".*:HARMONIZATION:CLINICALCOMBAT" {
ext.regul_ref = params.harmonization_regul_ref
ext.regul_mov = params.harmonization_regul_mov
ext.nu = params.harmonization_nu
ext.tau = params.harmonization_tau
ext.limit_age = params.harmonization_limit_age
ext.ignore_sex = params.harmonization_ignore_sex
ext.ignore_handedness = params.harmonization_ignore_handedness
publishDir = [
[
path: "${params.outdir}/harmonization_models/",
Expand Down
7 changes: 7 additions & 0 deletions nextflow.config
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,13 @@ params {

//**Harmonization**//
harmonization_reference = null
harmonization_regul_ref = 0
harmonization_regul_mov = -1
harmonization_nu = 5
harmonization_tau = 2
harmonization_limit_age = false
harmonization_ignore_sex = false
harmonization_ignore_handedness = false

//**Output in original space**//
output_orig_space = false
Expand Down
41 changes: 41 additions & 0 deletions nextflow_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,47 @@
"type": "string",
"description": "TSV file of the reference site used to harmonize the current site (e.g. the output TSV from stats/metrics in roi).",
"help_text": "TSV file of the reference site used to harmonize the current site (e.g. the output TSV from stats/metrics in roi)."
},
"harmonization_ignore_sex": {
"type": "boolean",
"default": false,
"description": "If set, ignore the sex covariate in the data.",
Comment thread
arnaudbore marked this conversation as resolved.
Outdated
"help_text": "If set, ignore the sex covariate in the data."
Comment thread
arnaudbore marked this conversation as resolved.
Outdated
},
"harmonization_ignore_handedness": {
"type": "boolean",
"default": false,
"description": "If set, ignore the handedness covariate in the data.",
Comment thread
arnaudbore marked this conversation as resolved.
Outdated
"help_text": "If set, ignore the handedness covariate in the data."
Comment thread
arnaudbore marked this conversation as resolved.
Outdated
},
"harmonization_regul_ref": {
"type": "number",
"default": 0,
"description": "Regularization parameter for the reference site data.",
"help_text": "Regularization parameter for the reference site data."
},
"harmonization_regul_mov": {
"type": "number",
"default": -1,
"description": "Regularization parameter for the moving site data. Set to '-1' for automatic tuning [default=0 for pairwise; -1 for clinical].",
"help_text": "Regularization parameter for the moving site data. Set to '-1' for automatic tuning [default=0 for pairwise; -1 for clinical]"
},
"harmonization_nu": {
"type": "number",
"default": 5,
"description": "Combat Clinical hyperparameter for the standard deviation estimation of the moving site data. It must be >=0. [5]",
"help_text": "Combat Clinical hyperparameter for the standard deviation estimation of the moving site data. It must be >=0. [5]"
},
"harmonization_tau": {
"type": "number",
"default": 2,
"description": "Combat Clinical hyperparameter for the covariate fit of the moving site data. It must be >= 1.",
"help_text": "Combat Clinical hyperparameter for the covariate fit of the moving site data. It must be >= 1."
},
"harmonization_limit_age": {
"type": "boolean",
"description": "If set, exclude reference site subjects with age outside the range of the moving site subject ages.",
"help_text": "If set, exclude reference site subjects with age outside the range of the moving site subject ages."
}
},
"help_text": "Parameters to configure the harmonization subworkflow."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,8 +336,8 @@ workflow PIPELINE_INITIALISATION {
readout: readout,
pe: pe_check.pe,
age: item.meta.age,
sex: item.meta.sex ? (item.meta.sex?.toLowerCase().contains("f") ? 2 : item.meta.sex.toLowerCase().contains("m") ? 1 : 0) : 0,
handedness: item.meta.handedness ? (item.meta.handedness?.toLowerCase().contains("r") ? 1 : item.meta.handedness?.toLowerCase().contains("l") ? 2 : "NA") : "NA",
sex: item.meta.sex ? (item.meta.sex.toString().trim().toLowerCase() in ['m', 'male', '1'] ? 1 : item.meta.sex.toString().trim().toLowerCase() in ['f', 'female', '2'] ? 2 : 1) : 1,
handedness: item.meta.handedness ? (item.meta.handedness?.toLowerCase().contains("r") ? 1 : item.meta.handedness?.toLowerCase().contains("l") ? 2 : 1) : 1,
disease: item.meta.disease ?: "HC",
site: item.meta.site],
t1w,
Expand Down Expand Up @@ -439,8 +439,8 @@ workflow PIPELINE_INITIALISATION {
readout: readout,
pe: pe,
age: item.meta.age,
sex: item.meta.sex ? (item.meta.sex?.toLowerCase().contains("f") ? 2 : item.meta.sex.toLowerCase().contains("m") ? 1 : 0) : 0,
handedness: item.meta.handedness ? (item.meta.handedness?.toLowerCase().contains("r") ? 1 : item.meta.handedness?.toLowerCase().contains("l") ? 2 : "NA") : "NA",
sex: item.meta.sex ? (item.meta.sex.toString().trim().toLowerCase() in ['m', 'male', '1'] ? 1 : item.meta.sex.toString().trim().toLowerCase() in ['f', 'female', '2'] ? 2 : 1) : 1,
handedness: item.meta.handedness ? (item.meta.handedness?.toLowerCase().contains("r") ? 1 : item.meta.handedness?.toLowerCase().contains("l") ? 2 : 1) : 1,
disease: item.meta.disease ?: "HC",
site: item.meta.site],
t1w,
Expand Down
36 changes: 35 additions & 1 deletion workflows/sf-tractomics.nf
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ workflow SF_TRACTOMICS {

ch_inputs = ch_inputs
.multiMap{ meta, t1, wmparc, aparcaseg, dwi_bval_bvec, rev_dwi_bval_bvec, b0, rev_b0, lesion ->
meta: meta
t1: [meta, t1]
wmparc: [meta, wmparc]
aparcaseg: [meta, aparcaseg]
Expand All @@ -48,6 +49,14 @@ workflow SF_TRACTOMICS {
lesion: [meta, lesion]
}

if ( params.harmonization_reference ) {
ch_inputs.meta
.collect()
.map { meta_list ->
validateMinimumParticipantsPerSite(meta_list)
}
}

ch_versions = channel.empty()
ch_sub_multiqc_files = channel.empty()
ch_global_multiqc_files = channel.empty()
Expand Down Expand Up @@ -267,7 +276,6 @@ workflow SF_TRACTOMICS {
// while keeping the header from the first
// file only and skipping it in the rest.
ch_collection_mean_input = ATLAS_ROIMETRICS.out.stats_tab_mean

ch_collection_mean_input = collectStatsFiles(ch_collection_mean_input, "space-native_atlas-iit_label-mean_desc-roi_stats.tsv", "${params.outdir}/metrics/")
ch_global_multiqc_files = ch_global_multiqc_files.mix(ch_collection_mean_input)

Expand Down Expand Up @@ -531,6 +539,32 @@ def collectStatsFiles(ch_stats_files, name, storeDir) {
}
}

def validateMinimumParticipantsPerSite(meta_list) {
def participants_per_site = [:].withDefault { [] as Set }

meta_list.each { meta ->
def meta_site = meta.get('site')
def participant = meta.get('id')
if (meta_site && participant) {
participants_per_site[meta_site.toString().trim()].add(participant.toString().trim())
}
}

def sites_with_too_few_participants = [:]
participants_per_site.each { entry ->
if (entry.value.size() < 5) {
sites_with_too_few_participants[entry.key] = entry.value
}
}
if (sites_with_too_few_participants) {
def site_errors = []
sites_with_too_few_participants.each { entry ->
site_errors << "Site '${entry.key}' has ${entry.value.size()} participant(s); at least 5 are required."
}
error "Harmonization cannot continue:\n${site_errors.join('\n')}"
}
}

/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
THE END
Expand Down
Loading