SACGF / SACGF/variantgrid

Reclassification analytics: scored backlog (stale-and-contradicted queue, VUS stock and flow, and more)

Open
#1,772 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
30
Forks
3
Avg merge
9h 28m
Merged PRs (30d)
42

Description

🤖 Written by Claude

Parking the un-built ideas from the reclassification analytics plans (#1523) before those plan files are deleted. The page itself is built - this is the backlog that was scored alongside it.

Scoring convention: **V** = value to a curator, **F** = feasibility on today's schema, **Σ = V × F**.

| # | Idea | V | F | Σ |
|--:|---|--:|--:|--:|
| B1 | **Stale-and-contradicted work queue.** Their Σ 100 "lone voice" finding: a lab alone in calling something P/LP, unrevisited for years, contradicted since by benign calls. Ours is sharper — they infer contradiction from gene symbols, we have `ClinicalContext` and `DiscordanceReport` naming who disagrees. Rank on stale × contradicted × lone-voice; render as a CSV-exportable queue. `OverlapsCalculator` already assembles the cross-lab picture. | 10 | 8 | 80 |
| B2 | **VUS stock and flow.** Waterfall per year: opening stock, plus new records classified VUS at step 1, minus resolved (split by direction), minus withdrawn, equals closing stock. Answers whether the pile grows from creation or from slow resolution. Companion line: share of *initial* classifications that are VUS, by year. | 8 | 9 | 72 |
| B3 | **Curation-date trustworthiness per lab.** Their entropy detector (Σ 56) separated 164 trustworthy submitters from 2,110 batch-stamped ones and became a required gate before any lag analysis. Per lab: distinct curation dates, normalised entropy, top-5 date share. Resolves the original plan's open item on synced records. The signature is already in our probe data — 344 events on 2025-06-18, 322 on 2026-08-05. | 7 | 9 | 63 |
| B4 | **Discordance lifecycle.** `DiscordanceReport` carries start, completion and resolution, so time-to-concordance is directly measurable where ClinVar had to infer it (L_CONFLICT, Σ 56: 69% of conflicts unresolved after 6.5 years). Per year opened/closed/ongoing, a censored survival curve, and — joining to events inside the report window — which lab moved. | 8 | 8 | 64 |
| B5 | **Serial reclassification and oscillation.** The `step` column already answers it: distribution of final step, share with ≥2 reclassifications, and round-trip cases (VUS → LP → VUS) listed individually. Their equivalent came in *below* a Poisson baseline — calls settle after one move. | 6 | 9 | 54 |
| B6 | **Points-to-boundary near-miss queue.** No ClinVar analogue exists; they cannot see criteria. Rank VUSes by ACMG points distance to the nearest bucket boundary — a record at +5 needs one PP to reach likely pathogenic. Pair each with the criterion that moved comparable records. Depends on the points total from item 5. | 8 | 7 | 56 |
| B7 | **gnomAD BA1/BS1 candidates.** Their `missed_reclassifications.py` (Σ 30). Ours goes further: compare the `gnomad_af` evidence value captured *at curation* against current annotation, so records overtaken by gnomAD v4 form an explainable cohort. Frame as candidates — BS1 is gene-specific in practice. | 8 | 6 | 48 |
| B8 | **Gene resolution speed.** The existing "VUS Burden by Gene" shows stock; adding flow makes it actionable. Per gene: share resolved in window, median time to resolution, events per record. Large *and* slow is where a curation sprint pays off. Their per-gene spread ran MECP2 46.7% resolved to NOTCH2 0%. | 6 | 8 | 48 |
| B9 | **ClinVar corroboration cross-check.** `annotation.models.ClinVar` holds ClinVar's aggregate per variant, so each active record can be compared to the outside view — both as drift (we differ, ranked by staleness) and as an early signal (ClinVar moved since we curated). Collapse their aggregate to our five tiers and report conflicting states separately. The natural bridge back to the sibling repo. | 7 | 6 | 42 |
| B10 | **Follow-on movement between labs.** Their PP5/BP6 herding hypothesis, which returned a **null** once coordinated submitters were excluded. Shariant is the right place to retest it, since labs actually see each other's calls. Hazard of lab B moving within 90/180/365d of lab A on the same `ClinicalContext`, against that lab's baseline rate. Wants B3 first — batch-stamped dates put every pair in the short-lag bucket by artefact, which is what made the raw ClinVar signal look 3.6× stronger than it was. | 7 | 5 | 35 |

## Method conventions worth importing

- **Fixed origin cohort with censoring** for anything time-to-event, so the number describes the whole
catalogue rather than the records that happened to move.
- **Denominators that could have had the event** — a lab or record that appeared mid-window is
measured from when it appeared.
- **Gate lag analyses on date trustworthiness** (B3) before reading anything into short intervals.
- **State what is excluded on the chart itself** — top-N caps, records without a resolved gene,
withdrawn records. Their rule is that a silent truncation reads as full coverage.
- **Report nulls.** Several of the most useful findings there were negative results.

## Open items from the original plan

- **Per-lab access** stays superuser-only until the Shariant team has used it. When a lab view arrives, scope it to classifications the lab *owns* so unpublished movement elsewhere stays private.
- **Curation date for synced records** - `sync/` may carry the originating lab's timestamp in the payload; if it does, storing it alongside `reclassified_date` lets synced labs join the time-series charts. The provenance filter covers the page until then. B3 above is the proper measurement.
- **Deferred to their own issues:** lab follow-on convergence (covered by B10) and a stale-VUS list of records unreviewed in over N years (covered by B1).

Counting by classification grouping is tracked separately in #1771.

Contributor guide

No contributing guide indexed for this repository

Research direction

Choose one backlog item rather than treating this issue as a single change, then read the named OverlapsCalculator and DiscordanceReport components and the existing analytics page from #1523. Check sync/ and annotation.models.ClinVar where the selected item requires provenance or corroboration. Done means one defined metric or queue is implemented with its stated denominator, censoring, exclusions, and export or chart output.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
analytics
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.