agentsclimarketplace

Bio applied taxonomic profiling

Skill Pavel-Kravchenko/Bioinformatics/Skills/bio-applied-taxonomic-profiling

Classify shotgun metagenome reads to species level with Kraken2, remove host reads with Bowtie2, and re-estimate abundance with Bracken. Use when doing metagenomics taxonomic profiling, Kraken2/Bracken, or host decontamination workflows.From its SKILL.md

Install
npx -y skills add Pavel-Kravchenko/Bioinformatics --skill bio-applied-taxonomic-profiling

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

6.8 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it

Taxonomic Profiling of Shotgun Metagenomes

When to Use

  • Classifying shotgun metagenomic shotgun reads to species/strain level (vs 16S amplicon genus-level resolution)
  • Removing host (human/animal) contamination from gut, skin, BAL, or blood metagenome samples before classification
  • Running Kraken2 → Bracken to correct LCA-inflated abundance estimates
  • Deciding between Kraken2+Bracken (sensitivity, speed) and MetaPhlAn4 (low RAM, marker-gene precision)
  • Computing alpha diversity (Shannon, Simpson, richness) from a Bracken/MetaPhlAn abundance table

Version Compatibility

Kraken2 ≥2.1.3, Bracken ≥2.9, Bowtie2 ≥2.5, MetaPhlAn ≥4.1, Python ≥3.10 with pandas ≥2.0, numpy ≥1.26, scipy ≥1.11.

Prerequisites

  • Kraken2 reference database downloaded locally (standard ~55 GB RAM footprint; PlusPF ~100 GB adds protozoa+fungi)
  • Bowtie2 host genome index (e.g. hg38) for decontamination
  • QC'd, adapter-trimmed paired-end FASTQ (see bio-read-qc-fastp-workflow)
  • Concepts: k-mer LCA classification, relative abundance vs read count

16S vs Shotgun

Feature16S ampliconShotgun
ResolutionGenus levelSpecies/strain level
Functional infoNoYes (gene/pathway content)
Host contaminationN/AMajor issue
Cost/sample~$30-80~$200-500

Goal: Remove host DNA before classification so it doesn't inflate counts or cause false bacterial assignments. Approach: Align reads to a host genome index with Bowtie2 and keep only the unmapped pairs (--un-conc-gz).

# Build once: bowtie2-build hg38.fa hg38_index/hg38
bowtie2 -x hg38_index/hg38 \
    -1 sample_R1.fastq.gz -2 sample_R2.fastq.gz \
    -p 8 --very-sensitive \
    --un-conc-gz decontam_%.fastq.gz \
    > /dev/null
# decontam_1.fastq.gz / decontam_2.fastq.gz = non-host read pairs

Typical host contamination: gut 1-10%, skin 10-30%, BAL 40-80%, blood/PBMC 60-95%.

import subprocess


def parse_bowtie2_contamination(bowtie2_stderr: str) -> float:
    """Extract the host-mapped read fraction from Bowtie2's stderr summary.

    Bowtie2 writes its alignment summary to stderr, e.g. a line like
    "93.42% overall alignment rate" — that rate IS the host contamination
    fraction when the index is a host genome.
    """
    for line in bowtie2_stderr.splitlines():
        if "overall alignment rate" in line:
            return float(line.strip().split("%")[0]) / 100.0
    raise ValueError("Could not find alignment rate in Bowtie2 output")

Kraken2 Classification

Goal: Assign each decontaminated read to the lowest common ancestor (LCA) of all reference genomes sharing its k-mers. Approach: Run Kraken2 against a prebuilt database with a confidence filter, then load the tab-delimited report into a DataFrame for downstream filtering.

kraken2 --db kraken2_db/ --paired --gzip-compressed --threads 16 \
    --confidence 0.1 --minimum-hit-groups 3 \
    --report kraken2_report.txt --output kraken2_output.txt \
    decontam_1.fastq.gz decontam_2.fastq.gz
  • --confidence 0.1: minimum fraction of k-mers classified to a node (reduces false assignments; default 0)
  • --minimum-hit-groups 3: minimum minimizer groups required before assignment
  • Database: standard (~55 GB RAM) vs PlusPF (~100 GB, adds protozoa+fungi)
import pandas as pd

KRAKEN2_COLUMNS = [
    "pct_clade", "reads_clade", "reads_direct", "rank_code", "taxid", "name",
]


def load_kraken2_report(path: str, min_pct: float = 1.0) -> pd.DataFrame:
    """Load a Kraken2 report.txt and keep clades above `min_pct` of reads.

    Report columns: % reads in clade, reads at exact taxon, reads in clade,
    rank code (S/G/F/O/C/P/K), NCBI taxid, indented scientific name.
    """
    df = pd.read_csv(path, sep="\t", header=None, names=KRAKEN2_COLUMNS)
    df["name"] = df["name"].str.strip()
    return df[df["pct_clade"] >= min_pct].reset_index(drop=True)

Bracken Abundance Re-estimation

Goal: Correct LCA inflation — reads pushed up to genus/family because they share k-mers across species — by redistributing them back to species level. Approach: Run Bracken on the Kraken2 report with the actual read length, then use fraction_total_reads for downstream analysis.

bracken -d kraken2_db/ -i kraken2_report.txt \
    -o bracken_species.txt -w bracken_species_report.txt \
    -r 150 -l S -t 10
ParameterMeaning
-r 150Read length (match your data)
-l SLevel: S=species, G=genus, F=family
-t 10Min reads threshold at species level

Alternative: MetaPhlAn4 aligns reads to clade-specific marker genes instead of k-mer LCA — ~3 GB RAM vs 55-100 GB, fewer false positives, direct compatibility with human-microbiome cohorts (HMP, curatedMetagenomicData), but lower sensitivity for organisms outside its marker set.

import numpy as np
import pandas as pd
from scipy.stats import entropy


def load_bracken_abundance(path: str) -> pd.DataFrame:
    """Load a bracken_species.txt file and return it indexed by species name."""
    df = pd.read_csv(path, sep="\t")
    return df.set_index("name")


def shannon_diversity(fractions: pd.Series) -> float:
    """Shannon index H = -sum(p_i * ln(p_i)) from a relative-abundance column
    (e.g. Bracken's fraction_total_reads or MetaPhlAn's relative_abundance/100).
    """
    p = fractions[fractions > 0].to_numpy()
    p = p / p.sum()
    return float(entropy(p))


def simpson_diversity(fractions: pd.Series) -> float:
    """Simpson's diversity 1 - D, where D = sum(p_i**2)."""
    p = fractions[fractions > 0].to_numpy()
    p = p / p.sum()
    return float(1.0 - np.sum(p ** 2))

Pitfalls

  • Database choice matters: organisms absent from the reference DB are missed or misclassified to a related taxon
  • LCA inflation without Bracken: reads sharing k-mers across species get pushed up to genus/family — always run Bracken before comparing species-level abundances
  • Host contamination: if not removed, host reads inflate library size and cause false-positive bacterial hits from human sequence similar to microbial regions
  • Read-length mismatch: Bracken's -r must match your actual sequencing read length, or redistribution weights will be wrong
  • Depth-sensitive diversity: Shannon/Simpson/richness all depend on sequencing depth — rarefy to equal depth before comparing samples

See Also

  • bio-metagenomics-kraken-classification
  • bio-metagenomics-abundance-estimation
  • bio-metagenomics-metaphlan-profiling
  • bio-microbiome-diversity-analysis

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Gives 0 of the 12 instructions most profiling optimisation skills give in ~1.8k tokens

Counted across 119 of the 180 authors here whose files we hold, read 2026-09-06

  • Capture snapshots at baseline, target, and final statesin 10 of 119, across 4 files
  • Determine whether the leak is browser-side or Node.js-sidein 10 of 119, across 4 files
  • Repeat the interactions ten times to amplify the leakin 10 of 119, across 4 files
  • Use memlab to identify leak traces from heapsnapshotsin 9 of 119, across 3 files
  • Revert the page and check whether memory is releasedin 9 of 119, across 3 files
  • Run the compare_snapshots fallback with Node.js when memlab is unavailablein 9 of 119, across 3 files
  • Ask the user before nulling detached DOM nodesin 8 of 119, across 3 files
  • Update profiles quarterlyin 6 of 119, across 3 files
  • Obtain ISAC approval before external sharingin 6 of 119, across 3 files
  • Qualify attribution confidence as low, medium, or highin 6 of 119, across 3 files
  • Identify the leak's root cause in the codein 6 of 119, across 2 files
  • Map group TTPs to ATT&CK using mitreattack-pythonin 6 of 119, across 3 files

Said here and by no other author read

  • Remove host DNA before classification
  • Keep only unmapped read pairs when decontaminating
  • Run Kraken2 with a confidence filter
  • Run Bracken on the Kraken2 report
  • Match Bracken's read length to the data
  • Use fraction_total_reads for downstream analysis

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.