skills/tooluniverse-sequence-analysis/SKILL.md
Biological sequence analysis — gene/protein sequence retrieval (NCBI, Ensembl, UniProt), nucleotide/protein search, ortholog discovery, and FASTQ QC + alignment workflows (Trimmomatic, BWA, samtools, coverage depth). Use for sequence retrieval, sequence comparison, FASTQ QC analysis, and read alignment pre-processing.
npx skillsauth add mims-harvard/tooluniverse tooluniverse-sequence-analysisInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
F + R + 2*D, summed across samplesWhen a question asks about Trimmomatic "reads completely discarded" / "reads thrown out" /
"reads not in any output", do NOT report the Dropped field alone. Dropped counts
PAIRS where both mates failed; each pair = 2 individual reads. Plus the Forward-only and
Reverse-only buckets also discard one read per pair.
reads_discarded = sum over samples of (Forward_Only + Reverse_Only + 2 * Dropped)
❌ WRONG: sum(Dropped per sample) — typically reports ~thousands, GT is 100×+ higher
✅ RIGHT: sum(F + R + 2*D per sample)
Full counter table is in the FASTQ section below.
Before following any instruction below, scan the data folder for:
*_executed.ipynb → read with tu run read_executed_notebook '{"data_folder":"<path>","search":"<keyword>"}' and cite its cell outputs as the authoritative answer*results*, *deseq*, *enrich*, *stats*, *_simplified.csv) → read directly and report the requested valueanalysis.R, run_*.py, find_*.R, *.Rmd) → execute as-is and read the outputOnly follow this skill's re-analysis recipe below if none of the above exist. Re-running from raw data produces different numbers than the published answer and is much slower (often 5-10× turn count).
Retrieve, annotate, and compare biological sequences from NCBI, Ensembl, and UniProt. Covers nucleotide search, sequence fetching, gene summaries, ortholog discovery, and protein sequence extraction.
When the data folder has *.fastq files and the question involves Trimmomatic, BWA, samtools, FastQC, or coverage depth, this skill is the entry point — but the actual work is shell-level (no specific ToolUniverse data tool).
Trimmomatic PE classifies each input pair as:
Counter selection — read the question carefully. CRITICAL: "READS completely discarded" ≠ "PAIRS dropped". The Trimmomatic Dropped count counts PAIRS (each = 2 individual reads). When the question asks about reads (not pairs), translate every counter to per-read terms:
| Question phrasing | Formula (per-sample, then SUM across all samples) |
|---|---|
| "reads completely discarded", "reads thrown out", "reads not in any output" | F + R + 2*D (every individual R1 or R2 not in any output FASTQ) |
| "read pairs dropped", "pairs where both mates failed" | D |
| "individual R2 reads dropped" (R1 kept as singleton) | F |
| "individual R1 reads dropped" (R2 kept as singleton) | R |
| "reads passing QC" / "surviving reads" | 2*B + F + R |
Trimmomatic's stderr summary gives Input Read Pairs: N Both Surviving: B (b%) Forward Only Surviving: F (f%) Reverse Only Surviving: R (r%) Dropped: D (d%). Always sum across ALL input sample pairs (e.g., SRR1 + SRR2 + ...).
DO NOT report just D as "reads completely discarded" — that's pair count, not read count, and is off by ~100×. The "Forward Only" R2 mate IS discarded; the "Reverse Only" R1 mate IS discarded; "Dropped" pairs lose BOTH reads.
For "average coverage depth", run samtools depth -a alignment.bam | awk '{sum+=$3; n++} END {print sum/n}' — the -a flag includes positions with zero coverage (otherwise the average is biased upward). For per-chromosome coverage, group by $1.
Input -> Phase 1: Gene ID resolution -> Phase 2: Nucleotide retrieval
-> Phase 3: Protein sequences -> Phase 4: Orthologs -> Output
NCBIGene_search: term (string REQUIRED, format "TP53[Symbol] AND Homo sapiens[Organism]"), retmax (int, default 10). Returns {status, data: {esearchresult: {idlist: ["7157"]}}}.
NCBIGene_get_summary: id (string REQUIRED, e.g., "7157"). Returns {status, data: {result: {"7157": {name, description, summary, chromosome, maplocation, genomicinfo, mim}}}}. Result is keyed by gene ID string.
NCBIDatasets_get_gene_by_symbol: symbol (string REQUIRED, e.g., "BRCA1"), taxon (string, e.g., "human"). Returns gene ID, description, location, cross-references.
NCBIDatasets_get_gene: gene_id (string REQUIRED, e.g., "7157"). Returns comprehensive gene info.
NCBI_search_nucleotide: query (free-form), organism (string), gene (string), strain (string), keywords (string), seq_type ("complete_genome"/"mRNA"/"refseq"), limit (int, default 20). Returns {status, data: {uids: [...], accessions: [...]}}.
NCBI_fetch_accessions: uids (array REQUIRED, e.g., ["545778205"]). Returns {status, data: ["U00096.3"], count: 1}.
NCBI_get_sequence: accession (string REQUIRED, e.g., "NM_007294"), format ("fasta"/"gb"/"embl"). Returns {status, data: "FASTA string...", accession, format, length}.
EnsemblSeq_get_region_sequence: region (string REQUIRED, "chr:start-end", e.g., "17:7668421-7668520"), species (default "homo_sapiens"). Returns {status, data: {sequence, sequence_length}}.
ensembl_get_sequence: id (string REQUIRED, Ensembl ID), type ("genomic"/"cds"/"cdna"/"protein"), multiple_sequences (bool). Returns sequence data.
Gotchas:
uids (NOT accessions).multiple_sequences=true. Use transcript IDs (ENST) for specific sequences.NCBI_search_nucleotide(organism="Homo sapiens", gene="BRCA1", seq_type="mRNA", limit=5)NCBI_fetch_accessions(uids=[first_uid]) -> accessionNCBI_get_sequence(accession="NM_007294", format="fasta")UniProt_get_sequence_by_accession: accession (string REQUIRED, e.g., "P04637"). Returns {result: "MEEPQSDP..."}. Note: response key is result, NOT data.
EnsemblSeq_get_id_sequence: ensembl_id (string REQUIRED, e.g., "ENSP00000269305"), type ("protein"/"cdna"/"cds"). Returns {status, data: {ensembl_id, molecule, sequence, sequence_length}}.
UniProt_get_entry_by_accession: accession (string REQUIRED). Full protein annotation.
Gotchas:
{result: "..."}, not {status, data}.NCBIDatasets_get_orthologs: gene_id (string REQUIRED, NCBI Gene ID e.g., "7157"), page_size (int, default 20, max 100). Returns {status, data: [{gene_id, symbol, description, taxname, common_name, chromosomes}]}.
NCBIProtein_get_summary: id (string REQUIRED, GI number or accession). Returns protein title, organism, length.
Gotcha: NCBIDatasets_get_orthologs requires NCBI Gene ID (numeric string), not gene symbol or Ensembl ID. Resolve via Phase 1 first.
NCBIGene_search(term="TP53[Symbol] AND Homo sapiens[Organism]") -> "7157"NCBIDatasets_get_orthologs(gene_id="7157", page_size=10) -> mouse Trp53, rat Tp53, etc.InterPro_get_entries_for_protein: accession (UniProt ID). Returns InterPro domain/family/superfamily entries with positions.
Pfam_get_protein_annotations: accession (UniProt ID). Returns Pfam domain hits with exact residue coordinates and E-values.
BLAST_protein_search: sequence (amino acid string), database (default "swissprot"), limit. Returns homologs with alignment scores, identity, E-values.
EnsemblCompara_get_orthologues: gene (gene symbol, e.g., "CFTR"), species (e.g., "human"). User-friendly alternative to NCBIDatasets_get_orthologs — accepts gene symbols directly.
EnsemblVEP_annotate_hgvs: hgvs_notation (e.g., "NM_000492.4:c.1521_1523del"). Returns consequence, protein impact, genomic coordinates.
ClinVar_search_variants: gene (gene symbol). Returns variant count and IDs for clinical significance lookup.
PubMed_search_articles: query, limit. Literature context for gene/variant findings.
| Tool | Correct Param | Common Mistake |
|------|--------------|----------------|
| NCBIGene_search | term (with [Symbol] syntax) | query or gene |
| NCBIGene_get_summary | id (string) | Integer type |
| NCBI_fetch_accessions | uids (array) | accessions |
| NCBI_get_sequence | accession (string) | Passing UID |
| NCBIDatasets_get_orthologs | gene_id (string) | Gene symbol |
| EnsemblSeq_get_id_sequence | ensembl_id | id |
| ensembl_get_sequence | id + multiple_sequences | Omitting multiple_sequences for gene+CDS |
| UniProt_get_sequence_by_accession | accession | Response is result not data |
LOOK UP DON'T GUESS -- always fetch sequences, coordinates, and domain boundaries from databases. Do not reconstruct them from memory.
| Question Type | Tool Choice | Why | |--------------|------------|-----| | "Find similar sequences" | BLAST_protein_search | Homology search against databases; returns E-values and identity | | "What domains does this protein have?" | InterPro_get_entries_for_protein or Pfam_get_protein_annotations | Domain architecture with exact residue coordinates | | "Get the sequence of gene X" | NCBI_search_nucleotide -> NCBI_get_sequence | Nucleotide retrieval by gene name | | "Compare orthologs" | NCBIDatasets_get_orthologs or EnsemblCompara_get_orthologues | Cross-species gene comparison | | "What is the protein impact of variant X?" | EnsemblVEP_annotate_hgvs | Consequence prediction with protein coordinates | | "Align two sequences" | BLAST (pairwise) | Quick pairwise comparison with scoring |
When translating a DNA sequence to protein:
DNA_translate_reading_frames tool; fallback: translate_dna.py which tries all 3 frames automaticallyWhen asked about protein function or structure:
InterPro_get_entries_for_protein returns all annotated domains with positionsWhen asked "how many X residues in region Y of protein Z":
Identify the correct protein — Gene names are ambiguous. GABAA has many subunits (GABRA1, GABRB2, GABRR1...). Read the question carefully for the specific subunit. Use proteins_api_search with gene name + "human" to find the right accession.
Find the region boundaries — Use proteins_api_get_features with the accession to get annotated domains (TRANSMEM, DOMAIN, REGION). Don't guess positions — get them from the database.
Count residues in the region — Fetch the sequence, extract the region, count. WRITE Python code for this — don't try to count manually.
python3 skills/tooluniverse-sequence-analysis/scripts/sequence_tools.py --type count_region --accession P24046 --start 318 --end 440 --residue Csequence[start:end].count('C'). Do NOT estimate or count from memory.Account for multimers — READ THE QUESTION for "homomeric", "pentamer", "tetramer", "dimer". If the question asks about a homomeric receptor (e.g., "homomeric GABAAρ1"), every subunit is identical. Count the residues in ONE subunit, then multiply:
Never manually count residues, compute GC%, or write reverse-complement logic inline. Run these scripts instead — they are tested and handle edge cases.
Script: skills/tooluniverse-sequence-analysis/scripts/biology_facts.py
Use this script to look up commonly-confused biology facts instead of relying on memory. It covers receptor types, ion channel stoichiometry, neurotransmitters, immune cell markers, and gene naming confusions.
python3 skills/tooluniverse-sequence-analysis/scripts/biology_facts.py --type receptor --name "GABAA"
python3 skills/tooluniverse-sequence-analysis/scripts/biology_facts.py --type ion_channel --name "NMDA"
python3 skills/tooluniverse-sequence-analysis/scripts/biology_facts.py --type gene_confusion --name "GABRA1"
python3 skills/tooluniverse-sequence-analysis/scripts/biology_facts.py --type receptor # list all entries
Types: receptor (stoichiometry, pharmacology), ion_channel (subunit arrangement), neurotransmitter (synthesis, receptors), immune_cell (markers, lineage), gene_confusion (commonly mixed-up genes like GABRA1 vs GABRR1).
Mandatory use: any question about receptor type/stoichiometry, immune cell markers, or gene name disambiguation.
Script: skills/tooluniverse-sequence-analysis/scripts/amino_acids.py
Use this script for any question about the genetic code, codon degeneracy, amino acid chemistry, codon usage bias, or tRNA wobble pairing. All outputs are JSON.
python3 skills/tooluniverse-sequence-analysis/scripts/amino_acids.py --type codon_table
python3 skills/tooluniverse-sequence-analysis/scripts/amino_acids.py --type amino_acid --name "Cysteine"
python3 skills/tooluniverse-sequence-analysis/scripts/amino_acids.py --type amino_acid --code C
python3 skills/tooluniverse-sequence-analysis/scripts/amino_acids.py --type amino_acid --code TRP
python3 skills/tooluniverse-sequence-analysis/scripts/amino_acids.py --type amino_acid # list all 20
python3 skills/tooluniverse-sequence-analysis/scripts/amino_acids.py --type count_codons --sequence "ATGCCCAAATTT..."
python3 skills/tooluniverse-sequence-analysis/scripts/amino_acids.py --type wobble --anticodon "GAU"
python3 skills/tooluniverse-sequence-analysis/scripts/amino_acids.py --type wobble --anticodon "IAU"
Modes:
| --type | What it returns | Key fields |
|----------|-----------------|-----------|
| codon_table | All 64 codons grouped by amino acid | degeneracy, codons, human codon usage %, stop codon names, degeneracy distribution (1/2/3/4/6) |
| amino_acid | Properties of one or all amino acids | name, one_letter, three_letter, mw_da, pKa_side_chain, polarity, charge_ph7, hydrophobicity_index (Kyte-Doolittle), backbone_pKa, codons, degeneracy, rare_codons_le15pct |
| count_codons | Codon frequency analysis for a DNA sequence | codon_counts with AA annotation and human usage freq, amino_acid_composition, rare_codons_present |
| wobble | Codons recognised by a given anticodon | recognised_codons (RNA+DNA form, AA), synonymous_only, wobble rule explanation |
When to use (mandatory):
codon_tableWobble rules: I pairs U/C/A (3 codons); G pairs U/C; U pairs A/G; C pairs G only; A pairs U only (rare). Use --type wobble --anticodon "GAU" to verify.
Amino acid lookup: accepts full name (--name "Cysteine"), 1-letter (--code C), or 3-letter (--code CYS).
When solving "which codons does this tRNA recognize" or "which tRNA reads this codon":
python3 skills/tooluniverse-sequence-analysis/scripts/amino_acids.py --type wobble --anticodon "IAU" to verify rather than reasoning from memory.Preferred: use DNA_translate_reading_frames tool (via MCP/SDK) with sequence parameter. Fallback: run translate_dna.py directly.
python3 skills/tooluniverse-sequence-analysis/scripts/translate_dna.py "ATGCCC..."
Tries all 3 reading frames, picks longest ORF automatically.
Script: skills/tooluniverse-sequence-analysis/scripts/sequence_tools.py
Preferred: Use ToolUniverse tools (via MCP/SDK) instead of the script:
Sequence_count_residues tool -- Count residues in a sequence or region. Fallback: sequence_tools.py --type count_residues or --type count_regionSequence_gc_content tool -- GC% of DNA. Fallback: sequence_tools.py --type gc_contentSequence_reverse_complement tool -- DNA reverse complement. Fallback: sequence_tools.py --type reverse_complementSequence_stats tool -- Auto-detect type, length, MW. Fallback: sequence_tools.py --type statsFallback script modes (use --type):
count_residues: Count residue in full sequence. --sequence "ACDE..." --residue Ccount_region: Count in region (1-based inclusive). --sequence "MAC..." --start 5 --end 20 --residue C OR --accession P24046 --start 318 --end 440 --residue C (fetches from UniProt live)gc_content: GC% of DNA. --sequence "ATGCGATCG"reverse_complement: DNA reverse complement. --sequence "ATGCGATCG"stats: Auto-detect DNA/RNA/Protein, compute length, MW for protein. --sequence "ATGCG..."ALWAYS use count_region --accession when the user gives a UniProt accession + region -- do not count manually.
| Indicator | High Quality | Acceptable | Caution | |-----------|-------------|-----------|---------| | RefSeq status | NM_/NP_ (curated) | XM_/XP_ (predicted) | No RefSeq (GenBank only) | | Sequence version | Latest version (.N) | Previous version | Removed/replaced | | Annotation | Reviewed (UniProt Swiss-Prot) | Unreviewed (TrEMBL) | No annotation | | Gene symbol | HGNC approved | Alias/synonym | Locus tag only |
TRIM YOUR ANSWER: If the question asks "what protein", answer with JUST the protein name. Do not add parenthetical abbreviations, descriptions, or qualifications. Example: answer "Glucose-6-phosphate 1-dehydrogenase", NOT "Glucose-6-phosphate 1-dehydrogenase (G6PD, EC 1.1.1.49)". When identifying a protein from a sequence, use BLAST/UniProt and report the top hit name exactly as it appears in the database — no embellishment.
multiple_sequences=truetools
Post-market safety surveillance and recall/adverse-event RETRIEVAL across the full spectrum of FDA-regulated products that are NOT covered by the drug-AE signal skills: medical devices, food / dietary supplements / cosmetics, veterinary drugs, and drug supply (shortages). Orchestrates openFDA endpoints (MAUDE device adverse events + device recalls + 510(k), CAERS food/supplement/ cosmetic adverse events, veterinary adverse events, drug shortages, and cross-product enforcement/recall reports). USE WHEN the user asks: "are there adverse events for [device / pacemaker / infusion pump / insulin pump]", "device recalls for [firm/product]", "supplement / vitamin / cosmetic adverse reactions", "is [drug] in shortage", "what injectables are on shortage", "veterinary / animal adverse events for [drug] in [dog/cat/horse]", "food recall for listeria", "MAUDE report for [device]", "CAERS reactions for [brand]". DO NOT USE for drug adverse-event SIGNAL detection or disproportionality (PRR / ROR / IC) or drug-AE association scoring — that is `tooluniverse-pharmacovigilance` / `tooluniverse-adverse-event-detection`. This skill is multi-product surveillance and retrieval, not drug-AE statistical signal mining.
tools
--- name: tooluniverse-phewas description: Cross-ancestry / cross-biobank phenome-wide association (PheWAS) and replication. Given ONE variant (rsID) or ONE gene, look up every phenotype it associates with across European/UK (UKB-TOPMed), Finnish (FinnGen), Japanese (BioBank Japan), and Taiwanese (TPMI) biobanks, plus exome-wide gene-burden PheWAS (Genebass), then judge whether an association replicates across ancestries or is population-specific. Use whenever the user asks "what else is this va
tools
Dereplicate a putative natural product and assign its chemical taxonomy. Use to answer "is [compound] a known natural product", "what microbe/organism produces [compound]", "what chemical class is [compound]", "dereplicate this metabolite (by formula/exact mass/InChIKey/SMILES)", or "classify this molecule into ChemOnt". Searches NPAtlas for known microbial natural products (producing organism + literature reference), assigns the ChemOnt kingdom→superclass→class→subclass hierarchy via ClassyFire, resolves systematic IUPAC names to structure via OPSIN, and cross-references identity in PubChem. NOT for general drug/compound identity or ADMET (use tooluniverse-chemical-compound-retrieval / tooluniverse-small-molecule-discovery) and NOT for metabolomics pathway/enrichment analysis (use tooluniverse-metabolomics skills).
tools
Genome-ASSEMBLY discovery, QC, and replicon mapping for any organism (bacteria, archaea, fungi, and beyond) using NCBI Datasets. Resolves an organism name or taxid to assemblies, picks the reference/representative or best-quality assembly, pulls assembly QC metrics (total length, contig/scaffold N50, contig count, GC%, assembly level, RefSeq category), enumerates chromosomes and plasmids via per-replicon sequence reports, and compares candidate assemblies on quality. Use for "what genomes are available for [organism]", "assembly stats / N50 / GC content for [GCF_/GCA_ accession]", "how many plasmids does [strain] have", "compare assemblies for [species]", "find the reference genome for [taxon]", "is this assembly Complete Genome or just contigs". NOT for gene-level orthology/synteny (use tooluniverse-comparative-genomics), plant gene structure (use tooluniverse-plant-genomics), de novo assembly from raw reads (no tool exists), or taxonomy-only name/lineage lookups.