-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add snpclustering subworkflow #11879
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 51 commits
6bf6638
87af5c5
0ba608f
07dfd41
3b48d11
8bbe838
e1862fc
57599ea
fc8ef72
6dd867d
1196416
508e2d0
22e4b02
5b65525
de75749
bb78b22
33cc677
e4f13a1
2cf394d
a84585e
4e37881
a204ef2
6400b7b
4851ff7
1fba4a3
81c77db
1f98f39
5d6180d
b556f73
6a7677f
e29c966
59e09ba
cc0a052
ddc238f
44bb942
44baf0f
6017365
90425b6
94751cc
0709ded
408df10
da041de
2e0c680
78122f0
2d428b2
da18b2f
f788b1a
7c590bd
1cc6dbf
50fe64c
a066a9e
0298138
bbaa6d4
bd4bd3c
2897267
a4a6d49
1e7ac0f
d3e3c51
ba0d57c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| BEGIN { | ||
| FS = OFS = "\t" | ||
| } | ||
|
|
||
| NR == 1 { | ||
| sub(/^#/, "") | ||
| $0 = $0 | ||
| for (i = 1; i <= NF; i++) { | ||
| if ($i == "IID") { | ||
| $i = "sample_id" | ||
| } | ||
| } | ||
| next | ||
| } | ||
|
|
||
| { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| include { BEAGLE5_BEAGLE } from '../../../modules/nf-core/beagle5/beagle' | ||
| include { PLINK2_VCF } from '../../../modules/nf-core/plink2/vcf' | ||
| include { PLINK2_PCA } from '../../../modules/nf-core/plink2/pca' | ||
| include { GAWK as GAWK_EIGENVEC_TO_TSV } from '../../../modules/nf-core/gawk' | ||
| include { CUSTOM_PCACLUSTERING } from '../../../modules/nf-core/custom/pcaclustering' | ||
| include { CUSTOM_CLUSTERMETRICS } from '../../../modules/nf-core/custom/clustermetrics' | ||
| include { CUSTOM_CLUSTERVISUALIZATION } from '../../../modules/nf-core/custom/clustervisualization' | ||
|
|
||
| workflow SNPCLUSTERING { | ||
| take: | ||
| vcf_ch | ||
| refpanel_ch | ||
| genmap_ch | ||
| region | ||
| npcs | ||
| use_approx | ||
| algorithm | ||
| n_clusters | ||
| dbscan_eps | ||
| dbscan_min_samples | ||
|
|
||
| main: | ||
| // Bundled awk program (see ./awk/eigenvec_to_tsv.awk); shipped alongside | ||
| // the subworkflow and passed to GAWK_EIGENVEC_TO_TSV as `program_file` so | ||
| // the awk source stays readable as awk rather than as an escaped Groovy | ||
| // string. | ||
| ch_eigenvec_to_tsv_awk = file("${moduleDir}/awk/eigenvec_to_tsv.awk", checkIfExists: true) | ||
|
|
||
| /* | ||
| * Build BEAGLE input tuple: | ||
| * tuple val(meta), path(vcf), path(vcf_index), path(refpanel), path(refpanel_index), | ||
| * path(genmap), path(exclsamples), path(exclmarkers), val(region) | ||
| */ | ||
| ch_beagle_input = vcf_ch.map { meta, vcf, vcf_index -> | ||
| tuple( | ||
| meta, | ||
| vcf, | ||
| vcf_index, | ||
| [], | ||
| [], | ||
| [], | ||
| [], | ||
| [], | ||
| region | ||
| ) | ||
| } | ||
|
|
||
| BEAGLE5_BEAGLE(ch_beagle_input) | ||
|
|
||
| /* | ||
| * Convert imputed VCF to PLINK2 pfiles | ||
| */ | ||
| PLINK2_VCF(BEAGLE5_BEAGLE.out.vcf) | ||
|
|
||
| /* | ||
| * PLINK2_PCA expects: | ||
| * tuple val(meta), val(npcs), val(use_approx), path(pgen), path(psam), path(pvar) | ||
| */ | ||
| ch_plink_pca_input = PLINK2_VCF.out.pgen | ||
| .join(PLINK2_VCF.out.pvar) | ||
| .join(PLINK2_VCF.out.psam) | ||
| .map { meta, pgen, pvar, psam -> | ||
| tuple(meta, npcs, use_approx, pgen, psam, pvar) | ||
|
dbaku42 marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| PLINK2_PCA(ch_plink_pca_input) | ||
|
|
||
| /* | ||
| * Convert .eigenvec to a tab-separated file for downstream clustering | ||
| * modules: strips the leading '#' from the header and renames the IID | ||
| * column to sample_id. Output keeps its default naming (<meta.id>.eigenvec) | ||
| * — only the tab-separated content matters downstream, not the extension. | ||
| */ | ||
| GAWK_EIGENVEC_TO_TSV( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Personally, I wonder if having a dedicated process to remove
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair question. I left it as a dedicated step so custom/pcaclustering stays generic (any TSV of sample × features) and does not absorb PLINK-specific quirks (# header, IID/FID). The rename to sample_id also matches what clustermetrics / clustervisualization already expect. I’d rather keep that adapter at the subworkflow boundary than special-case PLINK inside the clustering module.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be better to special-case PLINK format in your clustering module, since it seems to commonly consume files that were generated in PLINK format. Which in my view would actually make the module more generic? I understand that this is a custom module, but to me it would facilitate wider adoption if this module was tailored to the inputs, and it is a very simple operation (e.g. My main concern here is that I assume spawning all of these jobs creates some overhead, and the jobs do very little. Since @famosab has been involved more than I am, maybe there are considerations here that I am not aware of. |
||
| PLINK2_PCA.out.evecfile, | ||
| ch_eigenvec_to_tsv_awk, | ||
| false | ||
| ) | ||
|
|
||
| /* | ||
| * PCA clustering | ||
| * CUSTOM_PCACLUSTERING(tsv, algorithm, n_clusters, dbscan_eps, dbscan_min_samples) | ||
| */ | ||
| CUSTOM_PCACLUSTERING( | ||
| GAWK_EIGENVEC_TO_TSV.out.output, | ||
| algorithm, | ||
| n_clusters, | ||
| dbscan_eps, | ||
| dbscan_min_samples | ||
| ) | ||
|
|
||
| /* | ||
| * Metrics and visualization both expect one tuple input channel | ||
| * built from: meta + tsv + cluster assignments | ||
| */ | ||
| ch_cluster_analysis_input = GAWK_EIGENVEC_TO_TSV.out.output | ||
| .join(CUSTOM_PCACLUSTERING.out.clusters) | ||
| .map { meta, tsv, clusters -> | ||
| tuple(meta, tsv, clusters) | ||
| } | ||
|
|
||
| CUSTOM_CLUSTERMETRICS(ch_cluster_analysis_input) | ||
| CUSTOM_CLUSTERVISUALIZATION(ch_cluster_analysis_input) | ||
|
|
||
| emit: | ||
| imputed_vcf = BEAGLE5_BEAGLE.out.vcf | ||
| beagle_log = BEAGLE5_BEAGLE.out.log | ||
| pgen = PLINK2_VCF.out.pgen | ||
| pvar = PLINK2_VCF.out.pvar | ||
| psam = PLINK2_VCF.out.psam | ||
| evecfile = PLINK2_PCA.out.evecfile | ||
| evfile = PLINK2_PCA.out.evfile | ||
| pca_log = PLINK2_PCA.out.logfile | ||
| tsv = GAWK_EIGENVEC_TO_TSV.out.output | ||
| clusters = CUSTOM_PCACLUSTERING.out.clusters | ||
| cluster_info = CUSTOM_PCACLUSTERING.out.info | ||
| metrics = CUSTOM_CLUSTERMETRICS.out.metrics | ||
| k_sweep = CUSTOM_CLUSTERMETRICS.out.k_sweep | ||
| selected = CUSTOM_CLUSTERMETRICS.out.selected | ||
| metric_plots = CUSTOM_CLUSTERMETRICS.out.plots | ||
| umap_tsv = CUSTOM_CLUSTERVISUALIZATION.out.umap_tsv | ||
| tsne_tsv = CUSTOM_CLUSTERVISUALIZATION.out.tsne_tsv | ||
| umap_png = CUSTOM_CLUSTERVISUALIZATION.out.umap_png | ||
| tsne_png = CUSTOM_CLUSTERVISUALIZATION.out.tsne_png | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.