safety.viz release review 2026-10-03

What v1.9.0 adds, annotated

safety.viz opens its shared parts to a second chart library, and the demo app now carries that library’s four biomarker charts in a tab of their own, with R’s tests one press away. No existing chart, setting or API changes: what is new is the Biomarkers tab, R started on request, the chart list’s format version 2, and the kit those charts are built on.

17 of 17 charts ready on the pilot study R on request: 13.26 MB, once the kit: 36 parts, public from v1.9.0 single file: 1,165,774 bytes, no requests safety.viz dev at 096cc26

What to look at

  1. Open the Biomarkers tab: four charts, each ready, and the app counts 17 of 17 charts on the pilot study.
  2. Choose Alanine Aminotransferase in the group comparison before pressing anything: every visit’s line says statistics need R and what starting it costs, and nothing has been fetched.
  3. Press Start R. It reads Starting R…, then R started, and each visit prints R’s one-way ANOVA across the three arms: at Week 4, p = 0.005 for 75, 67 and 65 participants. Desktop R gives the same.
  4. Open the single-file build with the network off: the same tab draws, there is no Start R, and each line says why statistics are unavailable there.

Patch release v1.9.1

A patch on everything below. Nothing is removed, and no chart’s drawing changes except the histogram’s, which now draws its two deprecation notes.

  • The demo app’s footer says what happens to the data you load: files are read in the browser and never uploaded, and starting R downloads R from webr.r-wasm.org while your data stays in the browser. The single file says it loads nothing (safety.viz#196).
  • The histogram’s two JavaScript p-values, the normality screen and the group comparison, are deprecated. They still work, and the chart says so. v1.10.0 removes them, so remove test_normality and compare_distributions from your settings; nothing in safety.viz replaces them (safety.viz#188).
  • A library chart named data is refused, because the app keeps that name for its data view (safety.viz#197).
  • Each requirement ID now names one requirement, and every evidence page shows its own requirement text (safety.viz#195).
  • Evidence screenshots can be refreshed by name, and the obot app can start that refresh itself (safety.viz#204, safety.viz#207).
01 · the Biomarkers tab

The Biomarkers tab

bio.viz’s four charts sit beside Labs and vitals, ECG and Adverse events: the group comparison, the association scatter, the correlation matrix and the biomarker screen. They read the labs and vitals file as their results and the subject-level file as their participants, through the mapping already made, so a study mapped for the safety charts is mapped for these.

The demo app on the pilot study with the Biomarkers tab open, reading 4 of 4. Beneath the tabs, a Start R control with the hint About 13 MB, once, and the four biomarker charts; the group comparison overview shows Alanine Aminotransferase across the visits, by arm.

The Biomarkers tab on the pilot study. The tabs read 9 of 9, 1 of 1, 3 of 3 and 4 of 4, and the Data view says 17 of 17 charts ready. The group comparison opens on an overview of every measure at every visit, which prints no test: “12 of 28 biomarkers shown”.

What you should see

  • Biomarkers 4 of 4, each chart marked ready.
  • On the Data view: 17 of 17 charts ready.
  • The group comparison overview: 12 of 28 biomarkers on page 1 of 3.

Try it

Open the demo app
  1. Click the Biomarkers tab.
  2. Open each of the four charts from the row beneath the tabs.
  3. On the Data view, choose the renamed-column study: the one mapping readies both libraries’ charts.
02 · R on request

R on request

The biomarker charts print statistics only from R. Until you ask for R, every biomarker chart draws and its statistics line says what starting R costs, and the page fetches nothing. One press starts R in your browser, once, from webR’s public host with gsm.bio’s statistics functions, and every biomarker chart uses that one R from then on.

The group comparison with Alanine Aminotransferase chosen, before R is started: panels for Baseline, Unscheduled 1.1 and 1.2 with box plots by arm, and under each the line Statistics need R. Start R to compute them: it downloads about 13 MB, once, from webr.r-wasm.org, and the study’s data stays in this browser.

Alanine Aminotransferase chosen before the press. Under each visit: “Statistics need R. Start R to compute them: it downloads about 13 MB, once, from webr.r-wasm.org, and the study’s data stays in this browser.” No request had gone to R’s host at this point.

The app header just after the press: the control reads Starting R…

Just after the press: Starting R…

The app header once R has answered: the control reads R started.

1.5 seconds later, here: R started.

The same chart after R started: the Week 4 panel prints One-way analysis of variance, p = 0.005, Placebo n = 75, Xanomeline High Dose n = 67, Xanomeline Low Dose n = 65; Week 6 prints p = 0.037; Unscheduled 5.1 says there is no test because only one arm has values; Unscheduled 7.1 prints R’s reason for not computing, a minimum group size of 5.

After the press, the chart keeps what you chose and prints R’s test under each visit. Where a visit has too few participants, it prints R’s reason, not a number.

VisitOne-way ANOVA, across the three armsn: Placebo, High Dose, Low Dose
Baselinep = 0.51576, 66, 88
Week 2p = 0.12782, 70, 73
Week 4p = 0.00575, 67, 65
Week 6p = 0.03771, 55, 58
Week 8p = 0.01370, 52, 54
Week 12p = 0.38066, 42, 40
Week 16p = 0.17067, 33, 32
Week 20p = 0.05061, 29, 26
Week 24p = 0.51757, 28, 24
Week 26p = 0.25250, 24, 22

Alanine Aminotransferase by arm on the pilot study, as the app printed them, each labelled exploratory and unadjusted. Desktop R, running the same gsm.bio statistics file on the app’s own data files, gives the same p-value and counts at every visit. Unscheduled visits with fewer than five in a group print R’s reason instead.

The biomarker screen in the app after R started: Result at Baseline, Placebo against Xanomeline High Dose, twenty rows sorted by estimate, Platelet first at 0.3404 with p = 0.042 unadjusted and 0.295 after Benjamini-Hochberg.

Another biomarker chart, the screen, on the same R with no second download: Placebo against Xanomeline High Dose at Baseline across 28 biomarkers. Platelet is first at 0.3404 (0.01 to 0.6696), p = 0.042 before adjustment and 0.295 after. No row survives the adjustment.

The app at 390 pixels wide with the Biomarkers tab open: the Start R control with About 13 MB, once, beside the Group comparison chip, and the chart’s notes beneath.

At 390 px, before the press.

At 390 pixels wide after R started: the Baseline panel with its three boxes and R’s one-way ANOVA, p = 0.515.

At 390 px, after it: R’s test at Baseline. Neither page scrolls sideways.

What you should see

  • Before the press: no request to webr.r-wasm.org.
  • The press: 13.26 MB in 7 requests, all to webr.r-wasm.org, here in 1.5 seconds to R started. Opening the screen afterwards fetched nothing more.
  • Week 4: p = 0.005 (75, 67, 65).

Try it

Open the group comparison in the app
  1. Set Biomarker to Alanine Aminotransferase and read a visit’s line.
  2. Press Start R, at the left beneath the tabs.
  3. Switch Test to Kruskal-Wallis: each line waits for R and prints the new answer.
  4. Open the biomarker screen: it uses the R that is already running.

The single file, offline

The single-file build carries bio.viz’s charts inline and still loads nothing, so it cannot start R. It has no Start R control, and its biomarker charts say why statistics are unavailable.

The single-file build opened from disk with the pilot study’s four files dropped on it: the Biomarkers tab reads 4 of 4, and beneath the tabs the four biomarker charts with no Start R control.

The single file, opened from disk with the network off and the pilot study’s four files dropped on it: the Biomarkers tab, and no Start R.

The single file’s group comparison with Alanine Aminotransferase chosen: the same box plots, and under each visit the line Statistics are unavailable in this file: it loads nothing, so it cannot start R. The hosted demo app can start R in your browser.

“Statistics are unavailable in this file: it loads nothing, so it cannot start R. The hosted demo app can start R in your browser.” The file is 1,165,774 bytes and made no request.

03 · a second library joins

A second library joins the app

A page that mounts the demo app can hand it another chart library: its chart factories and its own chart list. The app lists those charts in a tab of their own, gives each a status, counts them, builds their settings and data from the loaded files and the mapping, and draws one at a time, as it does its own. To describe charts like these, the chart list’s format goes to version 2: an entry can name its library, the group it is listed under, and the named tables its chart takes. The thirteen safety charts’ entries mean what they meant.

The Domains page: the standard domain set of four tables, with a summary strip reading 17 charts read the standard set and the manifest described in format version 2, then the subject-level domain, whose list of charts that add it when supplied names the four biomarker charts.

The Domains page: 17 charts read the standard set, from a manifest in format version 2. The subject-level domain now lists the four biomarker charts among those that use it when it is supplied.

The Domains page’s Biomarkers, from bio.viz section: four charts from a second library, each with links to its live demo and API reference, the tables it takes and a table of its column settings with their defaults.

A section of its own, “Biomarkers, from bio.viz”: each chart with the tables it takes, its column settings and their defaults, and links to its demo and reference on bio.viz’s site.

Why it matters

Before this, the app knew only its own charts. Now any library that publishes a chart list in this format can join it, on the same files and mapping, without the app being rebuilt around it.

Try it

Open the Domains page
  1. Find “Biomarkers, from bio.viz” near the end.
  2. Follow a chart’s API reference link to bio.viz’s site.
04 · the kit

The kit

SafetyViz.kit hands out the parts every safety.viz chart is built from, so a library loaded beside it builds charts that look and behave the same, without a copy of that code drifting away: the control sidebar and its builders, the filter contract, the axis-limit helpers, the record listing, the participant rail, the box drawing, the measure list, the Kaplan–Meier estimator and the Chart.js the bundle already contains. Each member is the very function the charts call. bio.viz’s four charts are built on it.

The kit API reference on the dev site: 36 members from 8 shared modules and Chart.js, reached as SafetyViz.kit, drawing with Chart.js 4.5.1, public surface from v1.9.0, with a contents list of the member groups and a snippet loading safety.viz before another library.

The kit’s reference: 36 members from 8 shared modules and Chart.js 4.5.1, reached as SafetyViz.kit.

The one commitment in this release

From v1.9.0 the kit is public surface: a change to any member’s name, signature, return value, or the elements and class names it produces is a breaking change. Adding a member is not. The kit, explained in one page, and its API reference.

before you approve

What is not in this release

  • R in the single file: it loads nothing, so its biomarker charts say statistics are unavailable.
  • A library other than bio.viz in the app: the seam is general, and bio.viz is the only one using it.

Where to look further