Skip to content

ADD cau igvf-export: the guide design in the IGVF per-guide format - #10

Merged
emattei merged 5 commits into
mainfrom
feat/igvf-export
Oct 13, 2026
Merged

emattei merged 5 commits into
mainfrom
feat/igvf-export

Conversation

@emattei

@emattei emattei commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator

The fourth step. Alignment, annotation and element mapping between them know
everything the IGVF per-guide metadata format asks for; this assembles it
into igvf/guide_metadata.tsv.

The format is Format_for_Per-Guide_Metadata.pdf, IGVF document
f6a915a9-a6b8-4015-8aeb-236764976979, which files with content_type
"guide RNA sequences" must follow. Its conventions are the ones this package
already uses, and it pins ENSEMBL ids to GENCODE v43.

What a guide targets is derived, not believed

A design's category for an element is a hypothesis; the annotation is
evidence. A validated enhancer keeps its label, since that an element
regulates a gene is experimental knowledge no annotation supplies. Everything
else follows the format's own wording: within 2 kb of a protein-coding TSS is
a promoter, then exon, then intron, then distal element.

This is not pedantry. In a real 43,778-guide screen the design labelled 344
elements promoter; the genome agreed with all 300 that have a measured
gene, but of the other 44, 39 contained no TSS of any biotype — checked
against all 62,757 genes of v43 — and one sat 109 kb from the nearest.

type has to agree with genomic_element: positive control means a known
measurable effect, so a row claiming it while the element is an exon
contradicts itself.

One row per guide

guide_id must be unique, so a guide inside two overlapping elements names
the element sharing the most bases with its protospacer, ties broken by id.
putative_target_genes keeps every gene of every element it hit.

Tests

123 new, 689 in total, on synthetic elements placed among the annotation
fixtures' genes, with the mapping built by the real map_to_elements so the
input format cannot drift.

They found three faults, all fixed here: three path options escaped the
command line as tracebacks; a guide with two sites took its class from one
row and its element from another; and a guide absent from the mapping came
out targeting FALSE with type targeting.

What it fixes in a real submission

The lab's released IGVFFI2289OJBA has 2,365 of 6,982 spacers at 19 nt
against 20 nt coordinates, pam as the literal string NGG on all 4,667
targeting rows, and genomic_element, intended_target_name and
putative_target_genes 0% filled. This export cannot produce any of those.

🤖 Generated with Claude Code

emattei and others added 5 commits October 13, 2026 19:12
The fourth step. The three before it know everything the format asks for;
this assembles it into igvf/guide_metadata.tsv.

What a guide targets is decided from the genome, not from the design's label
for the element: a validated enhancer stays one, then within 2 kb of a
protein-coding TSS is a promoter, then an exon, then an intron, then a distal
element. The 2 kb is the format's own definition of a distal element. A
validated enhancer is the exception, since that an element regulates a gene
is experimental knowledge no annotation supplies.

type has to agree with genomic_element: positive control means a guide
expected to produce a known effect, so a row claiming it while the element is
an exon contradicts itself.

A guide inside two overlapping elements still gets one row, since the format
requires guide_id to be unique: the element sharing the most bases with the
protospacer wins, and every associated gene goes in putative_target_genes, so
a bidirectional promoter keeps both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A one-base overlap is right for CRISPRi, where the dCas9-KRAB footprint
covers the whole protospacer, and wrong for a cutting screen, where the cut
site is the thing. About 4% of rows are partial overlaps, so the distinction
changes the counts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The guide page, the outputs reference it includes, the API page and the nav,
plus the README and skills tables. CLAUDE.md records why what a guide targets
is derived rather than believed, why type has to agree with genomic_element,
and that pam is the genome's bases rather than the pattern.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
123 tests on synthetic elements placed among the annotation fixtures' genes,
with the mapping built by the real map_to_elements so the input format
cannot drift. The GTF fixture now writes exon_id, without which the store's
column is all null and the exon case is untestable.

The faults:

- three of the five path options escaped the command line as tracebacks,
  because StoreError, ElementError and PromoterError are siblings of
  ExportError rather than subclasses and were not caught;
- a guide with two sites took its class and coordinates from one row and its
  element from another, so a safe-targeting control could name the element
  its other site falls in. One row of the mapping is now chosen per guide and
  everything comes from it;
- a guide in the alignment but absent from the mapping fell through every
  condition and came out targeting FALSE with type targeting. The two tables
  describing different libraries is now an error.

A docstring also claimed putative_target_genes keeps both genes of a
bidirectional promoter. Only a measured pair can name two; an inferred one
names the nearest TSS's gene alone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@emattei
emattei merged commit 44f34a4 into main Oct 13, 2026
9 checks passed
@emattei
emattei deleted the feat/igvf-export branch October 13, 2026 23:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant