-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.nf
More file actions
440 lines (373 loc) · 15.5 KB
/
Copy pathmain.nf
File metadata and controls
440 lines (373 loc) · 15.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
#!/usr/bin/env nextflow
/*
========================================================================================
Comprehensive Metagenomic Analysis Pipeline
========================================================================================
Author: Based on workflows by Ashok K. Sharma
Description: Complete pipeline for metagenomic data analysis from raw reads to
functional/taxonomic annotation and growth rate calculation
Version: 1.0.0
========================================================================================
*/
nextflow.enable.dsl=2
// Print pipeline header
def helpMessage() {
log.info"""
================================================================
Comprehensive Metagenomic Analysis Pipeline v${workflow.manifest.version}
================================================================
Usage:
nextflow run main.nf --input samplesheet.csv --outdir results [options]
Mandatory arguments:
--input Path to comma-separated file containing sample info
--outdir Output directory for results
Reference Databases (at least one required):
--host_genome Path to host genome for decontamination (optional)
--metaphlan_db Path to MetaPhlAn database
--humann_protein_db Path to HUMAnN protein database
--humann_nucleotide_db Path to HUMAnN nucleotide database
--checkm_db Path to CheckM database directory
--kegg_db Path to KEGG database for BLAST
--cazy_db Path to CAZy database for annotation
Pipeline Options:
--skip_qc Skip quality control with FastQC [false]
--skip_kneaddata Skip KneadData (assumes clean reads) [false]
--skip_assembly Skip assembly step [false]
--skip_binning Skip MAG binning [false]
--skip_growth_rates Skip growth rate calculation [false]
--skip_functional Skip functional annotation [false]
--skip_taxonomic Skip taxonomic profiling [false]
Assembly Options:
--assembler Assembly tool: 'megahit' or 'spades' [megahit]
--coassembly Perform co-assembly of all samples [false]
--min_contig_length Minimum contig length [1000]
Binning Options:
--binning_tools Comma-separated list: metabat2,maxbin2,concoct [metabat2,maxbin2]
--min_bin_completeness Minimum bin completeness [50]
--max_bin_contamination Maximum bin contamination [10]
Computational Resources:
--max_cpus Maximum CPUs per process [16]
--max_memory Maximum memory per process [128.GB]
--max_time Maximum time per process [240.h]
Profile Options:
-profile Configuration profile: docker, singularity, conda, awsbatch, slurm
Other:
--help Display this help message
""".stripIndent()
}
// Show help message
if (params.help) {
helpMessage()
exit 0
}
// Validate mandatory parameters
if (!params.input) {
exit 1, "ERROR: Please provide --input samplesheet.csv"
}
if (!params.outdir) {
exit 1, "ERROR: Please provide --outdir for results"
}
/*
========================================================================================
PARAMETER DEFAULTS
========================================================================================
*/
params.input = null
params.outdir = './results'
params.help = false
// Reference databases
params.host_genome = null
params.metaphlan_db = null
params.humann_protein_db = null
params.humann_nucleotide_db = null
params.checkm_db = null
params.kegg_db = null
params.cazy_db = null
params.ardb_db = null
// Pipeline control
params.skip_qc = false
params.skip_kneaddata = false
params.skip_assembly = false
params.skip_binning = false
params.skip_growth_rates = false
params.skip_functional = false
params.skip_taxonomic = false
// Assembly parameters
params.assembler = 'megahit'
params.coassembly = false
params.min_contig_length = 1000
// Binning parameters
params.binning_tools = 'metabat2,maxbin2'
params.min_bin_completeness = 50
params.max_bin_contamination = 10
// Resource limits
params.max_cpus = 16
params.max_memory = 128.GB
params.max_time = 240.h
/*
========================================================================================
IMPORT MODULES
========================================================================================
*/
include { FASTQC } from './modules/qc/fastqc'
include { MULTIQC } from './modules/qc/multiqc'
include { KNEADDATA } from './modules/preprocessing/kneaddata'
include { METAPHLAN } from './modules/taxonomy/metaphlan'
include { HUMANN } from './modules/functional/humann'
include { MEGAHIT } from './modules/assembly/megahit'
include { MEGAHIT_COASSEMBLY } from './modules/assembly/megahit'
include { SPADES } from './modules/assembly/spades'
include { FILTER_CONTIGS } from './modules/assembly/filter_contigs'
include { PRODIGAL } from './modules/annotation/prodigal'
include { BWA_INDEX; BWA_MEM } from './modules/mapping/bwa'
include { SAMTOOLS_SORT; SAMTOOLS_INDEX } from './modules/mapping/samtools'
include { BOWTIE2_BUILD; BOWTIE2_ALIGN } from './modules/mapping/bowtie2'
include { METABAT2 } from './modules/binning/metabat2'
include { MAXBIN2 } from './modules/binning/maxbin2'
include { CONCOCT } from './modules/binning/concoct'
include { DASTOOL } from './modules/binning/dastool'
include { CHECKM } from './modules/binning/checkm'
include { CDHIT } from './modules/clustering/cdhit'
include { KEGG_ANNOTATION } from './modules/annotation/kegg'
include { CAZY_ANNOTATION } from './modules/annotation/cazy'
include { DEMIC } from './modules/growth/demic'
/*
========================================================================================
MAIN WORKFLOW
========================================================================================
*/
workflow {
// Parse input samplesheet
ch_input = Channel
.fromPath(params.input, checkIfExists: true)
.splitCsv(header: true)
.map { row ->
def sample_id = row.sample
def fastq_1 = file(row.fastq_1, checkIfExists: true)
def fastq_2 = file(row.fastq_2, checkIfExists: true)
return tuple(sample_id, fastq_1, fastq_2)
}
/*
================================================================================
STEP 1: QUALITY CONTROL
================================================================================
*/
if (!params.skip_qc) {
FASTQC(ch_input)
ch_fastqc_results = FASTQC.out.zip.collect()
}
/*
================================================================================
STEP 2: READ PREPROCESSING (KneadData)
================================================================================
*/
if (!params.skip_kneaddata && params.host_genome) {
KNEADDATA(ch_input, params.host_genome)
ch_clean_reads = KNEADDATA.out.reads
ch_kneaddata_logs = KNEADDATA.out.log
} else {
ch_clean_reads = ch_input
}
/*
================================================================================
STEP 3: TAXONOMIC PROFILING (MetaPhlAn)
================================================================================
*/
if (!params.skip_taxonomic && params.metaphlan_db) {
METAPHLAN(ch_clean_reads, params.metaphlan_db)
ch_metaphlan_profiles = METAPHLAN.out.profile
}
/*
================================================================================
STEP 4: FUNCTIONAL PROFILING (HUMAnN)
================================================================================
*/
if (!params.skip_functional && params.humann_protein_db) {
HUMANN(
ch_clean_reads,
params.humann_nucleotide_db,
params.humann_protein_db
)
ch_humann_genefamilies = HUMANN.out.genefamilies
ch_humann_pathabundance = HUMANN.out.pathabundance
ch_humann_pathcoverage = HUMANN.out.pathcoverage
}
/*
================================================================================
STEP 5: METAGENOMIC ASSEMBLY
================================================================================
*/
if (!params.skip_assembly) {
if (params.coassembly) {
// Co-assembly: combine all samples
ch_all_reads = ch_clean_reads
.map { sample, r1, r2 -> [r1, r2] }
.collect()
if (params.assembler == 'megahit') {
MEGAHIT_COASSEMBLY(ch_all_reads)
ch_assembly = MEGAHIT_COASSEMBLY.out.contigs
.map { contigs -> tuple('coassembly', contigs) }
}
} else {
// Individual assembly per sample
if (params.assembler == 'megahit') {
MEGAHIT(ch_clean_reads)
ch_assembly = MEGAHIT.out.contigs
} else if (params.assembler == 'spades') {
SPADES(ch_clean_reads)
ch_assembly = SPADES.out.contigs
}
}
// Filter contigs by length
FILTER_CONTIGS(ch_assembly, params.min_contig_length)
ch_filtered_contigs = FILTER_CONTIGS.out.contigs
} else {
ch_filtered_contigs = Channel.empty()
}
/*
================================================================================
STEP 6: GENE PREDICTION AND QUANTIFICATION
================================================================================
*/
if (!params.skip_assembly) {
// Gene prediction with Prodigal
PRODIGAL(ch_filtered_contigs)
ch_genes_fna = PRODIGAL.out.genes_fna
ch_genes_faa = PRODIGAL.out.genes_faa
// Map reads back to genes for quantification
BWA_INDEX(ch_genes_fna)
// Combine clean reads with indexed genes
ch_mapping_input = ch_clean_reads
.map { sample, r1, r2 -> tuple(sample, r1, r2) }
.combine(BWA_INDEX.out.index.map { sample, idx -> tuple(sample, idx) }, by: 0)
BWA_MEM(ch_mapping_input)
SAMTOOLS_SORT(BWA_MEM.out.bam)
SAMTOOLS_INDEX(SAMTOOLS_SORT.out.bam)
// Create non-redundant gene set
ch_all_genes = ch_genes_fna.map { sample, fna -> fna }.collect()
CDHIT(ch_all_genes)
ch_nr_genes = CDHIT.out.clustered
}
/*
================================================================================
STEP 7: FUNCTIONAL ANNOTATION OF GENES
================================================================================
*/
if (!params.skip_assembly && !params.skip_functional) {
if (params.kegg_db) {
KEGG_ANNOTATION(ch_genes_faa, params.kegg_db)
}
if (params.cazy_db) {
CAZY_ANNOTATION(ch_genes_faa, params.cazy_db)
}
}
/*
================================================================================
STEP 8: CONTIG MAPPING FOR BINNING AND GROWTH RATES
================================================================================
*/
if (!params.skip_assembly && (!params.skip_binning || !params.skip_growth_rates)) {
// Build index for contigs
BOWTIE2_BUILD(ch_filtered_contigs)
// Map reads to contigs
ch_bowtie_input = ch_clean_reads
.map { sample, r1, r2 -> tuple(sample, r1, r2) }
.combine(BOWTIE2_BUILD.out.index.map { sample, idx -> tuple(sample, idx) }, by: 0)
BOWTIE2_ALIGN(ch_bowtie_input)
ch_contig_bams = BOWTIE2_ALIGN.out.bam
// Sort and index BAM files
SAMTOOLS_SORT(ch_contig_bams)
SAMTOOLS_INDEX(SAMTOOLS_SORT.out.bam)
ch_sorted_bams = SAMTOOLS_SORT.out.bam
}
/*
================================================================================
STEP 9: GENOME BINNING
================================================================================
*/
if (!params.skip_assembly && !params.skip_binning) {
// Collect all BAMs for each assembly
ch_binning_input = ch_filtered_contigs
.combine(ch_sorted_bams.groupTuple())
def binning_tools = params.binning_tools.split(',')
ch_all_bins = Channel.empty()
// Run selected binning tools
if ('metabat2' in binning_tools) {
METABAT2(ch_binning_input)
ch_all_bins = ch_all_bins.mix(METABAT2.out.bins)
}
if ('maxbin2' in binning_tools) {
MAXBIN2(ch_binning_input)
ch_all_bins = ch_all_bins.mix(MAXBIN2.out.bins)
}
if ('concoct' in binning_tools) {
CONCOCT(ch_binning_input)
ch_all_bins = ch_all_bins.mix(CONCOCT.out.bins)
}
// Integrate bins with DAS_Tool
if (binning_tools.size() > 1) {
ch_dastool_input = ch_all_bins
.groupTuple()
.combine(ch_filtered_contigs, by: 0)
DASTOOL(ch_dastool_input)
ch_final_bins = DASTOOL.out.bins
} else {
ch_final_bins = ch_all_bins
}
// Assess bin quality with CheckM
if (params.checkm_db) {
CHECKM(ch_final_bins, params.checkm_db)
ch_checkm_results = CHECKM.out.results
}
}
/*
================================================================================
STEP 10: GROWTH RATE CALCULATION
================================================================================
*/
if (!params.skip_assembly && !params.skip_growth_rates && !params.skip_binning) {
// Prepare input for DEMIC (needs sorted SAM files)
ch_demic_input = ch_sorted_bams
.groupTuple()
.combine(ch_final_bins, by: 0)
DEMIC(ch_demic_input)
ch_growth_rates = DEMIC.out.growth_rates
}
/*
================================================================================
STEP 11: MULTIQC REPORT
================================================================================
*/
if (!params.skip_qc) {
ch_multiqc_files = Channel.empty()
if (!params.skip_qc) {
ch_multiqc_files = ch_multiqc_files.mix(ch_fastqc_results)
}
if (!params.skip_kneaddata) {
ch_multiqc_files = ch_multiqc_files.mix(ch_kneaddata_logs.collect())
}
MULTIQC(ch_multiqc_files.collect())
}
}
/*
========================================================================================
WORKFLOW COMPLETION
========================================================================================
*/
workflow.onComplete {
log.info """
================================================================
Pipeline Completion Summary
================================================================
Completed at : ${workflow.complete}
Duration : ${workflow.duration}
Success : ${workflow.success}
Work Dir : ${workflow.workDir}
Exit status : ${workflow.exitStatus}
Error report : ${workflow.errorReport ?: 'None'}
================================================================
""".stripIndent()
}
workflow.onError {
log.error "Pipeline failed. See error report: ${workflow.errorReport}"
}