Louis Le Nézet
02/03/2026, 11:05 AMJim Downie
02/03/2026, 11:12 AM_), not overwrite or remove them. It should be the responsibility of the subworkflow user to stage the input metas appropriately for joining/grouping.Louis Le Nézet
02/03/2026, 11:13 AMtake:
ch_vcfs // channel: [ meta, vcf, tbi ]
ch_scatter_output // channel: [ meta, bed, gather_count ] => output from the scatter subworkflow, if you didn't use this subworkflow you can just use `[]` as bed since it isn't used
val_common_meta // string: The name of the meta field that should become the new id
val_sort // boolean: Whether or not the output file should be sorted !! Add the config when using sort !!
main:
ch_concat_input = ch_vcfs
.join(ch_scatter_output)
.map { meta, vcf, tbi, _bed, gather_count ->
meta = val_common_meta ? meta + [id: meta[val_common_meta]] : meta
[groupKey(meta, gather_count), vcf, tbi]
}
.groupTuple()
.map { meta, vcf, tbi -> [meta.target, vcf, tbi] }
BCFTOOLS_CONCAT(ch_concat_input)
and her is my proposition
take:
ch_vcfs // channel: [ meta, vcf, index, count ]
val_common_meta // string : The name of the meta field that should become the new id
val_sort // boolean: Whether or not the output file should be sorted !! Add the config when using sort !!
main:
ch_concat_input = ch_vcfs
.map { meta, vcf, index, count ->
newMeta = val_common_meta ? meta[val_common_meta] : meta
[groupKey(newMeta, count), meta, vcf, index]
}
.groupTuple()
.ifEmpty {
error("ERROR: grouping operation resulted in an empty channel.")
}
.map { key, meta, vcf, index ->
cleanedMetas = meta.collect { m ->
m.findAll { k, v -> k != val_common_meta }
}
newMeta = [(val_common_meta): key.target, metas: cleanedMetas]
[
newMeta, vcf, index, vcf.size()
]
} // Compute number of records
.branch{ it ->
one: it[3] == 1
more: it[3] > 1
}
// Concatenate vcf with more than one record
BCFTOOLS_CONCAT(ch_concat_input.more.map{ it -> it[0..2] } )Louis Le Nézet
02/03/2026, 11:15 AMIMO a subworkflow should only ever add keys to a meta map (and my preference is to prefix the keys with anI agree ! However in this particular workflow there is a grouping operation. Therefore my way of handling things would be to get the grouping key as the main key and register all the others into a 'metas' key to keep track of all file processed.), not overwrite or remove them. It should be the responsibility of the subworkflow user to stage the input metas appropriately for joining/grouping._
Louis Le Nézet
02/03/2026, 11:16 AM{
"sample": "test",
"metas": [
{
"id": "test_1",
"other": "annotated"
},
{
"id": "test_2",
"other": "not_annotated"
}
]
}Jim Downie
02/03/2026, 11:18 AMLouis Le Nézet
02/03/2026, 11:18 AMLouis Le Nézet
02/03/2026, 11:25 AMch_concat_input = ch_vcfs
.map { meta, vcf, index, count ->
newMeta = val_common_meta ?
val_common_meta.collectEntries { key -> [(key): meta[key]] } :
meta
[groupKey(newMeta, count), meta, vcf, index]
}
.view()
.groupTuple()
.ifEmpty {
error("ERROR: grouping operation resulted in an empty channel.")
}
.map { key, meta, vcf, index ->
cleanedMetas = meta.collect { m ->
m.findAll { k, v -> !(k in val_common_meta) }
}
newMeta = key.target + [metas: cleanedMetas]
[
newMeta, vcf, index, vcf.size()
]
} // Compute number of records
.branch{ it ->
one: it[3] == 1
more: it[3] > 1
}
// Concatenate vcf with more than one record
BCFTOOLS_CONCAT(ch_concat_input.more.map{ it -> it[0..2] } )
I obtain for a grouping array sample, key
{
"sample": "test",
"key": "1",
"metas": [
{
"id": "test_1",
"other": "annotated"
},
{
"id": "test_2",
"other": "not_annotated"
}
]
}Jim Downie
02/03/2026, 11:31 AM.map { key, meta, vcf, index ->
cleanedMetas = meta.collect { m ->
m.findAll { k, v -> !(k in val_common_meta) }
}
newMeta = key.target + [metas: cleanedMetas]
[
newMeta, vcf, index, vcf.size()
]
}
The idea is to store the unused meta components as a list of maps inside a new key?James Fellows Yates
02/03/2026, 12:13 PMbwa subworkflows that you could also look for inspirationNicolas Vannieuwkerke
02/03/2026, 12:16 PMLouis Le Nézet
02/03/2026, 12:18 PMThe idea is to store the unused meta components as a list of maps inside a new key?Yes, indeed!
Jim Downie
02/03/2026, 12:21 PMLouis Le Nézet
02/03/2026, 1:52 PM