ribo-seq/orf-detection/SKILL.md
Detect and quantify translated ORFs from Ribo-seq using 3-nucleotide periodicity, including uORFs, internal ORFs, dORFs, and novel ORFs. Use when finding actively translated regions beyond annotated CDS, classifying ORFs by the 2022 community standard, quantifying ORF-level translation, or choosing between periodicity-based callers.
npx skillsauth add GPTomics/bioSkills bio-ribo-seq-orf-detectionInstall 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.
Reference examples tested with: RiboCode 1.2+, ORFquant 1.0+, ORFik 1.22+, DESeq2 1.42+, pandas 2.2+
Before using code patterns, verify installed versions match. If versions differ:
pip show <package> then help(module.function) to check signaturespackageVersion('<pkg>') then ?function_name to verify parameters<tool> --version then <tool> --help to confirm flagsIf code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt the example to match the actual API rather than retrying.
"Detect translated ORFs from my Ribo-seq data" -> Identify actively translated open reading frames (uORFs, internal ORFs, dORFs, novel ORFs) using 3-nucleotide periodicity (not mere coverage) as the evidence of translation, then classify and quantify them.
RiboCode for periodicity-based de novo ORF callingORFquant for isoform-aware quantification; ORFik as the general toolkitThe discriminating signal is PERIODICITY: a translated ORF shows footprint P-sites in frame 0 (F0 >> F1, F2). Coverage alone is not evidence of translation. Every method needs a correct per-read-length P-site offset first (see ribosome-periodicity).
The GENCODE-led standard (Mudge et al 2022) defines the umbrella term "Ribo-seq ORF" and six positional categories. These are positional, not modification-based (N-terminal extensions are not part of the scheme).
| Category | Definition (transcript-relative) | |----------|----------------------------------| | uORF | Entirely within the 5' UTR, not overlapping the CDS | | uoORF | Upstream-overlapping: starts in 5' UTR, overlaps CDS start out-of-frame | | intORF | Internal/nested: within the CDS in a different frame | | dORF | Entirely within the 3' UTR, not overlapping the CDS | | doORF | Downstream-overlapping: overlaps the CDS stop into the 3' UTR | | lncRNA-ORF | ORF on a transcript annotated as long non-coding RNA |
Related terms: sORF/smORF (<100 codons, product = microprotein), annotated CDS, novel. Catalogs: sORFs.org, OpenProt.
Initiation occurs at AUG and at near-cognate codons differing from AUG by one base; the biologically used set is CUG, GUG, ACG, UUG, AUU, AUC, AUA (AAG/AGG also differ by one base but initiate negligibly). CUG is the dominant near-cognate start (~16% of mapped initiation sites; AUG remains >50%). uORFs ESPECIALLY use near-cognate starts, so an ATG-only scanner misses the majority of real uORFs. Periodicity-based callers can be configured with alternative starts (RiboCode -A); the manual finder below is ATG-only and is a teaching toy unless extended.
| Situation | Tool | Why | |-----------|------|-----| | De novo discovery (uORFs, novel ORFs), standard Ribo-seq | RiboCode | Periodicity-based, maintained, supports alternative starts | | Isoform-aware detection + per-ORF quantification | ORFquant | Resolves ORFs across overlapping isoforms; built on Ribo-seQC | | General R toolkit (uORF finding, P-site shift, TE, plots) | ORFik | Comprehensive; NOT a dedicated de novo caller | | Initiation-site / non-AUG mapping (needs harringtonine/LTM) | Ribo-TISH, PRICE | TI-seq-aware (see initiation-site-mapping) | | Assay-agnostic, no TI-seq, short + long ORFs | ribotricer | Phasing-only, species-calibrated cutoff | | Bacteria/prokaryotes | DeepRibo, smORFer | Prokaryote-trained (eukaryote periodicity tools fit poorly) | | Differential ORF translation | P-site counts per ORF then DESeq2 | Count-based DE on ORF-level counts |
ORFik and ORFquant are DISTINCT packages (different authors, repos, methods): ORFik (Tjeldnes 2021, general toolkit) is not the same as ORFquant (Calviello 2020, dedicated isoform-aware caller). Do not install ORFik expecting ORFquant.
Goal: Identify periodicity-significant ORFs, including uORFs at near-cognate starts.
Approach: Prepare transcript annotation, run metaplots to select periodic read lengths and their P-site offsets, then run RiboCode with optional alternative starts.
# Step 1: annotation
prepare_transcripts -g annotation.gtf -f genome.fa -o ribocode_annot
# Step 2: metaplots picks periodic read lengths + per-length P-site offsets -> config .txt
# (read lengths come from THIS step, NOT from a -l flag)
metaplots -a ribocode_annot -r transcriptome.bam -o metaplots_out
# Step 3: call ORFs. -A adds near-cognate starts; -l is the longest-ORF toggle (yes/no)
RiboCode -a ribocode_annot -c metaplots_out_pre_config.txt \
-A CTG,GTG -l no -p 0.05 -o ribocode_result
RiboCode works in transcript coordinates, so the -r input is the TRANSCRIPTOME-projected BAM (Aligned.toTranscriptome.out.bam), not the genome BAM; a genome BAM silently misbehaves. Its core test is a MODIFIED WILCOXON SIGNED-RANK test on the per-codon P-site frame distribution (a separate binomial file is a secondary output). The -l flag toggles longest-ORF selection; it is NOT a read-length list.
Goal: Split called ORFs by the standard categories.
Approach: Read the tabular result and group on the ORF_type column, whose RiboCode values are annotated, uORF, dORF, Overlap_uORF, Overlap_dORF, Internal, novel.
import pandas as pd
def load_ribocode_orfs(path):
'''Load the RiboCode result table (<output_name>.txt) and group by ORF_type.'''
df = pd.read_csv(path, sep='\t')
groups = {t: df[df['ORF_type'] == t] for t in df['ORF_type'].unique()}
return df, groups
RiboCode writes the result as <output_name>.txt (plus a <output_name>_collapsed.txt), e.g. ribocode_result.txt for -o ribocode_result; its columns include ORF_ID, ORF_type, transcript/genome start-stop, pval_combined, and adjusted_pval.
Goal: Quantify ORF-level translation while resolving footprints across overlapping isoforms.
Approach: Prepare annotation once, feed Ribo-seQC-prepared input, then run the master function.
library(ORFquant)
prepare_annotation_files(annotation_directory = "annot/",
twobit_file = "genome.2bit",
gtf_file = "annotation.gtf")
# Ribo-seQC writes a for_ORFquant object from the Ribo-seq BAM; pass it here
run_ORFquant(for_ORFquant_file = "sample_for_ORFquant",
annotation_file = "annot/annotation.gtf_Rannot",
n_cores = 4)
For uORF discovery in a general R workflow, ORFik provides findUORFs() and the true P-site shift is detectRibosomeShifts() then shiftFootprints() (there are no p_offsets/lengths arguments on fimport).
Goal: Illustrate ORF finding mechanics; not a substitute for a periodicity caller.
Approach: Scan three frames for start-to-stop pairs. This finds only ATG starts and uses coverage, not periodicity, so it misses near-cognate uORFs and cannot confirm active translation on its own.
def find_orfs(seq, min_codons=10):
'''Find ATG-to-stop ORFs in all three frames (ATG-only: a teaching toy).'''
seq = str(seq).upper()
stops = {'TAA', 'TAG', 'TGA'}
orfs = []
for frame in range(3):
i = frame
while i < len(seq) - 2:
if seq[i:i+3] == 'ATG':
for j in range(i + 3, len(seq) - 2, 3):
if seq[j:j+3] in stops:
if (j + 3 - i) >= min_codons * 3:
orfs.append({'start': i, 'end': j + 3, 'frame': frame})
i = j
break
i += 3
return orfs
Goal: Separate genuine translation from coverage artifacts.
Approach: Check the in-frame (frame-0) fraction within the ORF; compare the ORF's footprint read-length distribution to annotated CDS with FLOSS; use ORFscore for frame bias; add PhyloCSF/conservation or mass-spec peptide evidence for novel microproteins.
FLOSS (Ingolia 2014) is half the summed absolute difference between an ORF's footprint length-fraction histogram and the CDS reference; a high-coverage region whose length distribution is non-CDS-like is likely not genuine translation. A called ORF with no frame-0 enrichment, a non-ribosomal FLOSS, and no conservation/peptide support should be treated as a candidate, not a finding.
Goal: Compare ORF-level translation across conditions.
Approach: Count offset-corrected P-sites per ORF per sample into an integer matrix, then run DESeq2.
library(DESeq2)
dds <- DESeqDataSetFromMatrix(orf_psite_counts, coldata, ~ condition)
dds <- DESeq(dds)
res <- results(dds) # adjusted p-value is res$padj
Ribosome occupancy is not translation efficiency; a TE change needs an RNA-seq denominator (see translation-efficiency).
| Symptom | Cause | Fix |
|---------|-------|-----|
| RiboCode runs but uses wrong read lengths | -l 27,28,29,30 passed as read lengths | -l is the longest-ORF toggle; read lengths come from metaplots config |
| KeyError on ORF_type == 'noncoding' | Wrong category names | RiboCode emits Overlap_uORF/Overlap_dORF/Internal/novel, not noncoding |
| library(ORFik) cannot find ORFquant functions | ORFik and ORFquant conflated | They are different packages; install ORFquant from its own repo |
| fimport(p_offsets=, lengths=) errors | Those arguments do not exist | Use detectRibosomeShifts() then shiftFootprints() |
| RibORF.py -f -r -g -o not found | Fabricated single-command CLI | RibORF is a Perl multi-script pipeline (logistic regression) |
| Most uORFs missing | ATG-only scan | Use a periodicity caller with -A near-cognate starts |
| High-coverage "ORF" is not real | Coverage used as the translation signal | Require frame-0 enrichment + FLOSS/ORFscore validation |
tools
End-to-end CLIP-seq pipeline from FASTQ to ENCODE-compliant binding sites, single-nucleotide crosslink maps, annotation, motifs, and (optionally) differential binding. Use when running the full Yeo lab eCLIP / iCLIP / iCLIP2 / iCLIP3 / irCLIP / PAR-CLIP analysis with SMInput control, protocol-specific UMI extraction, ENCODE STAR parameters, CLIPper or Skipper peak calling with stringent log2 FC and -log10 p thresholds, IDR rescue and self-consistency QC, and downstream motif registration with mCross or PEKA.
development
Detect, date, and contextualize whole-genome duplication (WGD / paleopolyploidy) events using wgd v2 (Chen et al 2024), KsRates (Sensalari 2022 substitution-rate-corrected Ks dating), DupGen_finder (Qiao 2019), MAPS (Li 2018 phylogenomic), POInT (Conant 2008 ordered-block), SLEDGe (2024 ML-based), Whale.jl (Bayesian DL+WGD), and synteny-anchored paranome construction. Use when identifying ancient polyploidy from Ks distributions and synteny block analysis, positioning WGD events relative to speciation, distinguishing tandem from segmental from WGD duplications, dating the 2R/3R vertebrate / fish / salmonid WGDs, building paranome and Ks-age mixture models, applying KsRates substitution-rate correction across lineages, or testing alternative biased-fractionation / dosage-balance models post-WGD.
tools
Build whole-genome alignments using Progressive Cactus (Armstrong 2020 reference-free clade-level WGA), Minigraph-Cactus (Hickey 2024 pangenome-aware), LASTZ chain/net (UCSC pipeline), MUMmer4 (Marçais 2018 pairwise), minimap2 -x asm5/10/20 (Li 2018 fast pairwise), AnchorWave (Song 2022 WGD-aware), and Mauve / progressiveMauve (bacterial). Operates the HAL toolkit (Hickey 2013) for downstream extraction including halSynteny, halLiftover, halBranchMutations, and hal2maf. Use when constructing multi-species alignments for comparative-annotation projection (TOGA), synteny detection, conservation analyses (phyloP / PhastCons), or pangenome graph construction; selecting between reference-free (Cactus) and reference-anchored (LASTZ chains/nets) approaches; tuning sensitivity for closely vs distantly related genomes; or producing HAL files for genome-wide downstream tools.
development
Detect syntenic blocks and structural rearrangements between genomes using MCScanX (Wang 2012), JCVI/MCScan (Tang 2008 Python), GENESPACE (Lovell 2022) for orthology-anchored riparian visualization, SyRI for structural variation, AnchorWave for sequence-level synteny, i-ADHoRe 3.0 for highly diverged species, SynNet for synteny networks, and ntSynt for multi-genome macrosynteny. Use when identifying collinear gene blocks across species, distinguishing macrosynteny from microsynteny, detecting inversions/translocations/duplications, anchoring orthology in WGD lineages, producing publication riparian plots, computing synteny block age via Ks (cross-references whole-genome-duplication), or running synteny-aware ortholog inference in polyploids.