End-to-end eDNA metabarcoding from raw amplicons to community ecology. Covers QC, primer removal, denoising with OBITools3 or DADA2, contamination filtering, taxonomy assignment, Hill number diversity, and constrained ordination. Use when processing environmental DNA samples for biodiversity assessment or ecological surveys.
End-to-end eDNA metabarcoding from raw amplicons to community ecology. Covers QC, primer removal, denoising with OBITools3 or DADA2, contamination filtering, taxonomy assignment, Hill number diversity, and constrained ordination. Use when processing environmental DNA samples for biodiversity assessment or ecological surveys.
# Gate 1: Chimera rate <20%if(chimera_rate >0.20) message('WARNING: High chimera rate. Check primer removal and PCR conditions.')# Gate 2: ASV count reasonable for marker
n_asvs <- ncol(seqtab_nochim)
message(sprintf('ASVs after denoising: %d', n_asvs))# Typical ranges: COI 500-5000, 12S 50-500, ITS 200-3000
Step 4: Contamination Filtering
R (decontam)
library(decontam)
library(phyloseq)
ps <- phyloseq(otu_table(seqtab_nochim, taxa_are_rows =FALSE),
sample_data(meta))# Identify negative controls
sample_data(ps)$is_neg <- sample_data(ps)$sample_type =='negative_control'# prevalence method: standard for eDNA; threshold 0.5 identifies contaminants# present more in negative controls than real samples
contam <- isContaminant(ps, method ='prevalence', neg ='is_neg', threshold =0.5)
message(sprintf('Contaminant ASVs: %d',sum(contam$contaminant)))
ps_clean <- prune_taxa(!contam$contaminant, ps)# Remove negative control samples
ps_clean <- subset_samples(ps_clean, sample_type !='negative_control')
Tag-jumping removal
# Tag-jumping: cross-contamination from index hopping during sequencing# Remove ASVs with <0.1% of max abundance in a sample (likely tag-jump artifacts)
otu <- as(otu_table(ps_clean),'matrix')
max_per_asv <- apply(otu,2,max)
otu_filtered <- otu
for(j in1:ncol(otu)){# 0.1% of max: standard tag-jump threshold
threshold <- max_per_asv[j]*0.001
otu_filtered[otu[, j]< threshold, j]<-0}
otu_table(ps_clean)<- otu_table(otu_filtered, taxa_are_rows =FALSE)
QC Checkpoint: Decontamination
# Gate: verify contaminant ASVs were removed from real samples
n_before <- ntaxa(ps)
n_after <- ntaxa(ps_clean)
message(sprintf('ASVs removed as contaminants: %d (%.1f%%)',
n_before - n_after,(n_before - n_after)/ n_before *100))if((n_before - n_after)/ n_before >0.5){
message('WARNING: >50% ASVs flagged as contaminants. Review decontam threshold.')}
Step 5: Taxonomy Assignment
OBITools3 (ecotag)
# ecotag assigns taxonomy using LCA algorithm against reference database# Reference databases: EMBL, BOLD, MIDORI2, UNITE (marker-dependent)
obi ecotag -R reads/refdb --taxonomy reads/taxonomy reads/cleaned reads/assigned
# Filter by assignment quality (species-level for COI)
obi grep -p 'sequence["best_identity"] >= 0.97' reads/assigned reads/filtered_assigned
obi export --tab-output reads/filtered_assigned > taxonomy_results.tsv
DADA2 (assignTaxonomy)
# SILVA for 16S/18S, UNITE for ITS, custom for COI/12S# Reference databases must be formatted for DADA2# minBoot 50: minimum bootstrap confidence; 80 for more conservative assignments
taxa <- assignTaxonomy(seqtab_nochim,'reference_db.fa.gz', multithread =TRUE, minBoot =50)
taxa <- addSpecies(taxa,'species_db.fa.gz')