create_missing_features: opt-in / configurable strictness for synthesized parent rows
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 129
- Forks
- 34
- PR merge metrics
- No merged PRs in 30d
Description
Observation
pyensembl calls gtfparse.create_missing_features to backfill transcript and gene rows that the GTF omits (legitimate when the upstream only emits exon / CDS). The synthesizer derives the parent feature from the child rows it sees, which is usually correct — but when the input GTF deviates in ways the synthesizer doesn't anticipate, downstream consumers have to clean up.
Two recent pyensembl issues are downstream of this:
- openvax/pyensembl#331 / v2.6.4 — older Ensembl releases (e.g. release 54) omit
exon_id.create_missing_featuressynthesizestranscriptrows that don't carryexon_ideither, and pyensembl'sTranscript.exonsthen crashed withsqlite3.OperationalError: no such column: exon_id. Workaround lives in pyensembl: acolumn_exists("exon", "exon_id")check attranscript.py:149. - openvax/pyensembl#252 / v2.6.4 — TAIR
chr_patch_hapl_scafffragments containCDSrows without matchingstart_codon/stop_codon. After feature synthesis the transcript row exists butcoding_sequencecouldn't compute its endpoints. Workaround in pyensembl:Transcript.coding_sequencereturnsNonerather than raising.
In both cases the inconsistency is structural to the input GTF rather than to gtfparse's logic, but a caller-side knob would help.
Proposal
Add a strict / policy kwarg to create_missing_features:
strict="raise"— when a child row lacks attributes the synthesizer would need to faithfully build the parent, raise.strict="warn"— log + skip the synthesized row.strict="best_effort"— current behavior; synthesize whatever we can, fill missing attrs with None.
Or more granularly: a required_attributes_per_feature: dict[str, set[str]] knob so callers can pin "if you're going to synthesize a transcript row, only do so when the child exon carries exon_id".
Why it'd help
The two issues above both look like "pyensembl handles partial GTFs" but the upstream signal that something's off (exon_id missing, start_codon missing) gets eaten by the synthesizer and lives later as a crash at query time.
Scope guard
- Existing default behavior should stay best-effort. This is purely additive.
- Bacteria/archaea GFFs with their own synthesis quirks are out of scope for this issue (separate parser ecosystem).
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at gtfparse.create_missing_features and review the downstream examples in pyensembl's transcript.py, including the column_exists("exon", "exon_id") check and Transcript.coding_sequence behavior. Compare the proposed strict/policy options and required_attributes_per_feature design, preserving best-effort behavior by default. Done means callers can opt into raising or warning/skipping when synthesized parent attributes are insufficient, with the existing default unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- bioinformatics
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100