This page is the repository's own document docs/dashboard.md, shown as it is, so that it never drifts from the product.
sapling sas dashboard makes a study dashboard from the products of a SAS run: plain HTML and JavaScript, no R, no
server, no network. A team that runs only SAS has the same pages that the R engine's Shiny dashboard
(sapling dashboard, which stays as it is) gives a team that runs R. The folder opens by double click (index.html):
the data are JavaScript files, so file:// works where fetch of a local JSON file does not.
Commands#
sapling sas dashboard [--no-subjects] [--out DIR] [--open] SAS DASHBOARD PASS: n pages, m numbers; the path and the size
sapling sas dashboard --check [--no-subjects] the gate: SAS DASHBOARD PASS / FAIL
sapling sas run --adam-export a SAS run that also brings the ADaM data sets back as .xpt
--open opens the built page in your default browser (open, xdg-open or start), only when you give it; no test
and no other command ever opens a window. --check --no-subjects builds out/sas/dashboard-no-subjects/ and gates
that (the full dashboard stays as it is).
It writes out/sas/dashboard/: index.html, app.js, subjects.js, app.css, data/*.js, figures/*.png and
export_adam.sas. Nothing in the build needs R or SAS.
What it reads#
| Source | For |
|---|---|
out/sas/ard/*.csv | every number of a table (the one results shape of all engines) |
out/sas/programs.json | the outputs, their analyses, the SAS program of each, the listings and figures |
out/sas/tlf/*.lst, out/sas/listings, out/sas/figures (.csv, .png) | the table as SAS printed it, listings, figures and their numbers |
out/sas/logs/*.log, out/sas/check.md | the verdicts of the run; check.md (SAS against R, "759 of 759") is optional: a SAS-only site has none and the page is complete without it |
out/tlf/spec/<study>_sap.json, out/sap/sap.json, sap.qmd, protocol/*.json, out/adam/spec | the trace: analysis, method, population, records, ADaM derivations, SAP block, protocol sentence |
the ADaM data sets as .xpt | the subject pages |
Which ADaM data the subject pages used is written on the Overview and in the build verdict:
out/sas/adam/data/*.xpt, SAS's own ADaM data sets, when they are there: "the ADaM data sets as SAS made them";- else
out/adam/data/*.xpt, the transport files the SAS table programs read insapling sas run: "the transport files the SAS table programs read" (the SAS programs ran on exactly these files).
sapling sas run --adam-export brings SAS's own ADaM data sets back: after the programs, DataStep Studio runs the
generated export_adam.sas (LIBNAME XPORT and PROC COPY: it reads <root>/adamsas, the data sets of
sapling sas adam run, or else <root>/adam, and writes <root>/adamout/*.xpt) and fetches the files into
out/sas/adam/data. The next sapling sas dashboard then reads them. The program is generated text in the house style;
the build also writes it to out/sas/dashboard/export_adam.sas to run by hand. Its text is unit-tested; it has not been
run on a SAS server yet, so that run is the proof of the export itself. --no-subjects builds without any
subject-level data.
The pages#
One page, a left navigation, deep links by hash (#/o/T14_2_1/12 is the trace of one number).
- Overview: the study, the arms, the numbers, SAS as engine, the verdicts of the run, the DRAFT banner (the plan is
not approved: results are not for decisions) and, for dummy data, the made-up-data banner from
sdtm/DUMMY.md. - Protocol and plan: each endpoint of the protocol, the SAP's decision (estimand) and the outputs that answer it; a gap is shown as a gap; the plan's status, populations, open decisions with their protocol sentence, waivers, changes, the views of the dashboard (the data cut and the subgroups, each with the protocol's own sentence about it or the gap), the outputs and their status, the protocol text.
- Outputs: every table, listing and figure. A table is drawn from its results (
n (%),Mean (SD),Min, Maxthe cells of the SAS.lstitself: row labels, indentation and values as SAS printed them, a listing with several blocks as several tables); each number in a cell is bound to the result it is (by arm, by the labels above the row, and its text), and opens the trace panel: result, analysis, method and operations, population, records, grouping, ADaM variables with their derivations, the SAP block (its sentence and source), the protocol sentence. A tab shows the.lsttext as SAS printed it. Whenout/sas/check.mdhas the output, its page says "Checked against R: 15 of 15 numbers the same". Print styles print a table in black on white. - AE explorer: subjects per body system and preferred term and arm, counted in the browser from ADAE and ADSL (safety population), with serious, intensity, related, treatment-emergent and text filters; a count lists its subjects, a subject its records and a subject page.
- Subjects and the subject page: demographics, treatment and dates, adverse events, the primary endpoint over the visits against the arm mean, values outside the reference range, time to event. Every subject id on a page (a chip, a count's subjects, an Insights finding) opens a drawer over the current page with the subject in short and a link to the full page; Esc closes it.
- Insights (fixed rules, no AI; labelled exploratory): serious events, deaths, discontinuations and reasons, signals by preferred term (Fisher exact test, Benjamini-Hochberg adjustment), baseline imbalance (standardized difference), data quality (missing and impossible dates), each with its subjects.
- Kaplan-Meier: curves, medians with 95% limits (log-log), subjects at risk, log-rank test, from the time-to-event data set; the SAP's own analyses on it are linked.
- Labs and measurements: mean change or value by visit and arm (with standard errors), outside-range counts with their subjects, shift from baseline, potential Hy's law cases, where the data have a range.
- Audit trail: a chained ledger (
out/sas/ledger.jsonl): the SAS run, its check against R and each build of the dashboard are entries; an entry's hash includes the hash of the entry before it, with the files it read and made and their SHA-256, and the commands' verdicts. The page recomputes the chain in the browser. The status pill (in the navigation of every page) says DRAFT, APPROVED, or "APPROVED · sealed" (approved and the chain intact), with the ledger entry and its hash, as the plan says.
The data cut and the subgroups (sex, age group, race, site) of the bar apply to the subject-level pages only. The tables are the SAS results of all the data and are never recomputed in the browser.
The gate (--check)#
- the data of the page equal the results files of SAS, read again;
- in a headless Chrome (the one Remotion ships in
video/node_modules, orCHROME_BIN; never a visible window) every number of every table is one element with its key; the text, none missing, none extra, none twice, equals the results file; 2b. the cells of every table page (header, row labels and values, in order, every block) equal the cells of the SAS.lstof that output, which the gate reads itself with its own reader (parseLstinsrc/sas_dash_data.ts; the page has its own inapp.js); a result that no cell of the.lstholds fails the gate; - the trace of every number reaches its analysis;
- every page draws;
- the AE explorer's counts of the unfiltered view equal the SAP's AE table (all treatment-emergent events, or serious only for the serious table);
- the Kaplan-Meier numbers of the page (subjects, events, median and its 95% limits per arm) equal a second calculation from the transport file;
- the log-rank p of the page equals the SAS result where the SAP has a log-rank analysis (otherwise it says so; the SAP's Cox models are shown beside the curves as clickable SAS numbers);
- the labs page's n, mean and SD by arm, parameter and visit equal the SAP's table of values by visit where one exists;
- a build without subject data (
--check --no-subjects): its five subject pages and the subject page say why they are empty, and no subject-level file is in the folder; - the ledger: the chain recomputed by the page and by the gate agrees with
out/sas/ledger.jsonl, and every file the build read still has its SHA-256 (a stale dashboard fails).
A number that differs by one character makes the gate FAIL (test/sas_dashboard.test.ts plants one in the page data,
one in the .lst, and one wrong log-rank p).
Data and privacy#
The folder holds subject-level data (ADaM records of every subject): handle it like the ADaM data, do not email or
publish it. --no-subjects leaves them out (the AE explorer, Subjects, Insights, Kaplan-Meier and Labs say why they are
empty). Numbers of the subject data are rounded to 5 decimals in the page data (the tables are not). Dummy data show
their made-up label.
What the R dashboard has that this one has not#
- Ask AI (left out on purpose).
- Live engines / recomputed tables: the R dashboard reruns its engines on a data cut or a subgroup; here the SAS tables are fixed and only the subject-level pages follow the view.
- QC against independent programs of the live views (R dashboard gate steps 3 and 4).
- The published reference of the Kaplan-Meier page (a CSR line): not in the SAS products.