Can the SafetyGraphics kidney-function renderer become a Chart.js module in safety.viz? Short answer: yes, and it is a natural next renderer — its core chart is a direct kidney analog of the already-shipped hep-explorer. The work splits cleanly into a straightforward core scatter and a heavier patient-profile drill-down, and the main open question is data, not architecture.
A KDIGO-staged nephrotoxicity explorer: a per-participant scatter over creatinine change, with click-through patient-profile line charts. Clinically the kidney twin of eDISH.
The current Shiny v1.0.0 (R/ggplot2/plotly) is the behavioral source of truth. The deprecated JS v0.9.0 (D3 + RhoInc webcharts) is the legacy stack we are replacing — reference only.
Canvas-first, not table-first. Reuses the proven hep-explorer / delta-delta module pattern — the KDIGO stage zones are a Chart.js background plugin.
Migrate nepExplorer as a canvas-first module on the hep-explorer/delta-delta pattern, in two phases: (1) the KDIGO creatinine scatter (small–medium, demoable on today's pharmaverseadam data) and (2) the patient-profile drill-down (medium–large, blocked on kidney-specific measures the demo data lacks). Settle the demo-data question first (decision D1 below) — it gates phase 2's scope, not phase 1.
1 · Clinical purpose
nepExplorer helps a safety reviewer spot acute declines in renal function in trial lab data. It is built around the KDIGO acute-kidney-injury (AKI) staging criteria, which classify severity from serum-creatinine change relative to baseline. The tool implements two of the KDIGO creatinine axes:
The main chart is a scatter, one point per participant, of each subject's maximum fold change (x) against maximum absolute change (y), laid over colored L-shaped KDIGO stage zones (white → yellow → orange → red for no-stage → 1 → 2 → 3). A companion summary table cross-tabulates the fold-change and absolute-change stage counts. It is the clinical sibling of hep-explorer's Hy's-Law eDISH quadrant plot — same "diagnostic scatter with clinical threshold zones + drill-down" shape, different organ.
Clicking a point opens a patient profile: a demographics panel plus small-multiple time-series line charts across five measure groups — serum creatinine & cystatin C, eGFR (creatinine- and cystatin-C–based), related electrolytes (BUN, sodium, potassium, bicarbonate, chloride, phosphate, calcium), blood pressure, and the urine albumin/creatinine ratio — with KDIGO reference lines, a measure picker, and a time-animation control on the main scatter.
The absolute-change staging in creatinine_data_fcn.R uses a case_when ordered >0.3 → >1.5 → >2.5. Because case_when returns the first match, every value above 0.3 is labeled "Stage 1" and the Stage 2/3 branches are unreachable. Migration should re-derive the staging from KDIGO intent (descending cut-points), not port the bug. Flag for the clinical owners.
2 · Two incarnations
The repo has lived twice. Jeremy's recollection is correct: it began as a JavaScript renderer and was rewritten as a Shiny app in 2025 (NEWS: "Migrated from Javascript to R"). Both are on GitHub.
ggplot2 + plotly scatter, gt summary table, plotly patient-profile line charts; a safetyGraphics module with a settings/mapping object. ~1,500 lines across ~13 R files. Actively the current product; carries the authoritative KDIGO logic, unit-conversion notes, and the richest feature set.
Use for: clinical logic, thresholds, feature scope, patient-profile design.
D3 + RhoInc webcharts, ~2,700 lines / 92 files, structured as kdigoScatterPlot + timeSeries with a settings-schema.json. This is exactly the legacy stack safety.viz exists to replace, and it predates the v1.0 feature set.
Use for: interaction/UX cues only. Do not port webcharts idioms.
3 · Architecture fit
safety.viz modules share a lifecycle (init / setData / setSettings / render / resize / destroy) and internal flow (checkInputs → configure → structureData → getScales/getPlugins → new Chart) over a shared control shell. nepExplorer is squarely canvas-first (a diagnostic scatter is the primary object), so it slots into the same pattern as the two closest precedents:
| nepExplorer element | safety.viz precedent | Mapping |
|---|---|---|
| KDIGO scatter | hep-explorer eDISH / delta-delta | Per-participant scatter of two derived measures; direct reuse of scale + point-selection machinery. |
| KDIGO stage zones | hep-explorer quadrantPlugin | Colored background regions + labels drawn by a Chart.js canvas plugin. Stage rectangles instead of Hy's-Law quadrant cut-lines — same technique. |
| value ÷ baseline, value − baseline | hep-explorer ×ULN/×Baseline; delta-delta change-from-baseline | structureData reduces to one point per participant. Simpler here (single measure, baseline only). |
| measure_values matching | hep-explorer ALT/AST/TB/ALP | Match CREAT (and profile measures) from the measure column via a measure_values mapping. |
| Summary stage table | delta-delta linked measure table | Listing area in the shell; a stage cross-tab instead of a per-measure table. |
| Patient-profile line charts | results-over-time / outlier-explorer | Time-series line rendering exists; a multi-panel per-participant profile is net-new wiring on top of it. |
The core scatter is well-trodden ground. The genuinely new surface is the patient-profile panel — five stacked small-multiple charts, a demographics table, a measure picker, and the scatter time-animation — which is richer than hep-explorer's participant-detail popover and has no one-to-one precedent yet.
4 · Data requirements
nepExplorer needs a tall labs domain (id, value, measure, study-day, visit, visit-number, unit, baseline flag) plus vitals (blood pressure) and demographics. The clinical logic depends on a set of measure values. Here is how those line up against safety.viz's current demo data — pharmaverseadam (CDISC Pilot 01), shipped in v1.1.0 as site/data/adbds.csv:
| Measure / feature | Used by | In pharmaverseadam? |
|---|---|---|
| Serum creatinine | Main KDIGO scatter, profile | PRESENT — core chart works today |
| Blood pressure (sys/dia) | BP profile sub-chart | PRESENT |
| BUN, Na, K, Cl, Ca, Phosphate | Related-electrolytes sub-chart | PRESENT (6 of 7) |
| Bicarbonate | Related-electrolytes sub-chart | ABSENT |
| eGFR (creatinine-based) | eGFR profile sub-chart | DERIVABLE — CKD-EPI from creatinine + age/sex |
| Cystatin C | Creatinine sub-chart alt, eGFRcys | ABSENT — not derivable |
| eGFRcys (cystatin-C-based) | eGFR profile sub-chart | ABSENT — needs cystatin C |
| Urine albumin/creatinine ratio | Urine ACR sub-chart | ABSENT — distinct urinalysis measure |
The takeaway: the core KDIGO scatter is fully demoable on today's data (creatinine is present), and two of the five profile sub-charts (BP, related electrolytes) largely work. But the kidney-specialized measures — cystatin C, eGFRcys, and the urine ACR — are genuinely absent from pharmaverseadam and cannot be derived. The RhoInc "renderer-specific" dataset that nepExplorer itself ships (and that was safety.viz's own demo data before the v1.1.0 pharmaverse migration) does carry all of them.
The fold-change axis (a ratio) is unit-independent and safe. But the absolute-change axis and the "≥ 4 mg/dL" rule are mg/dL-specific, and the demo creatinine is in µmol/L (≈88.4× larger). nepExplorer handles this with an explicit conversion step and warns that factors vary by sponsor. The Chart.js module must be unit-aware (convert to mg/dL for the absolute axis, or make thresholds unit-parameterized) — not hard, but a correctness trap if missed.
5 · Effort & phasing
The done-gate applies per phase: a module is not finished until the Pages site carries a gallery demo, an evidence page, and an API reference — factor that in beyond the code itself, as with every prior renderer.
6 · Risks
| Risk | Sev | Mitigation |
|---|---|---|
| Demo data lacks kidney-specialized measures (cystatin C, eGFRcys, urine ACR) | high | Decide D1: derive eGFR (CKD-EPI); retain RhoInc renderer-specific data as a nep-specific demo; or scope phase 2 to available measures. |
| Unit dependence of absolute KDIGO thresholds | med | Build the module unit-aware; convert to mg/dL for the absolute axis; parameterize thresholds. |
| Clinical-logic fidelity (incl. the DELTA_STAGE bug) | med | Re-derive KDIGO staging from intent; validate against clinical owners; don't blind-port R. |
| Patient-profile scope — richest surface, no exact precedent | med | Phase it; lean on results-over-time/outlier-explorer; treat time-animation as optional. |
| Scope creep — two features in one renderer | low | Ship phase 1 as a standalone renderer with its own done-gate before starting phase 2. |
7 · Recommendation & decisions
nepExplorer is a strong fit and a natural addition to the renderer set: it extends the eDISH-style diagnostic-scatter family from liver to kidney, reuses machinery that is already proven twice, and rounds out the organ-system coverage of the safety graphics suite. Filed as a standalone renderer requirement — hub #35 — sibling to hep-explorer (#30), beyond the v1.3 core set (#29), with features to mine from the upstream tracker under #33; migrating from the Shiny v1.0.0 as the behavioral spec, in the two phases above (framed as ~1–2 ultracode sessions).
Phase 2 needs cystatin C, eGFRcys, and urine ACR, which pharmaverseadam lacks. Options: (a) derive eGFR + retain the RhoInc renderer-specific dataset as a nep-specific demo; (b) augment pharmaverseadam with synthetic kidney measures; (c) scope phase 2 to available measures only.
Leaning: (a) — the RhoInc set was purpose-built for hep/nep and was safety.viz's own demo data pre-v1.1.0, so it is a known-good, self-consistent kidney demo without inventing data.
Phase 1 (KDIGO scatter) is demoable today and independently valuable. Phase 2 (profile) is the larger, data-gated lift.
Leaning: ship phase 1 as a standalone renderer with its own done-gate; start phase 2 once D1 is settled.
nepExplorer animates the scatter across visits (plotly frames). Chart.js can do this, but it is custom and non-core.
Leaning: defer to a follow-up; not required for a v1 of the renderer.
This is an initial assessment for direction-setting, not a committed plan. On a GO, the next step is a hub requirement (Business Requirement → Data Requirement → Design) that resolves D1–D3 and decomposes phase 1 into safety.viz sub-issues.
Sources