Integrating WebR with the TLG Catalog

Enhancing Clinical Reporting Accessibility through Web-Based R Integration

Pawel Rucki

2024-10-30

About Me

Pawel Rucki

Project Tech Lead, NEST @ Roche

pawel-rucki

pawelru

TLG Catalog

Overview of the TLG Catalog

🌐 https://insightsengineering.github.io/tlg-catalog

The TLG Catalog serves as a comprehensive repository of Tables, Listings, and Graphs (TLGs) used in clinical reporting, created using R packages.

Key Features

  • A comprehensive, well-structured catalog containing 140 outputs, with numerous multi-variant options to support diverse clinical reporting needs
  • Based on dummy simulated data (random.cdisc.data package)
  • Reproducibility information (including .lock file)
  • WebAssembly integration
    • static output (via WebR)
    • interactive Shiny applications (via Shinylive)

Importance of the TLG Catalog

  • Serves as a reference guide for clinical trial programmers, offering extensive content.
  • Provides source code and reproducibility details to allow programmers to use it as a base for modifications.
  • Widely adopted at Roche and open-sourced for the benefit of the broader community.

WebR

Introduction to WebR

WebR is a framework that ports R to WebAssembly (WASM), allowing R code to run in web browsers without requiring local installations. This enhances accessibility, particularly in environments with centrally managed systems or limited access rights on local machines.

For more information, visit the official documentation: WebR Documentation and George Stagg’s presentations: Introduction to WebR, Shiny Without a Server.

How does it work

source: https://gws.quarto.pub/magic-with-wasm-and-webr

Shinylive

Powered by WebR, Shinylive enables Shiny applications to run directly in the browser. This allows for publishing Shiny apps without the need for a server.

source: https://gws.quarto.pub/webr-shinylive-overview

Quarto integration

Both WebR and Shinylive integrate directly with Quarto through extensions, enabling easy embedding of R code that runs in the browser. This allows for efficient creation of dynamic, reproducible documents.

For more details, visit: coatless/quarto-webr and quarto-ext/shinylive.

Example:

Example:

WebR REPL app

REPL - Read - Eval - Print - Loop

🌐 https://webr.r-wasm.org/latest/

Limitations

  • It might be slow and that’s (somewhat) expected.
  • Package availability - currently ~95% of CRAN coverage.
    • For non-CRAN packages, manual building of WASM binaries may be required.
    • Some packages requires specific WebR patches.
  • Still not stable. I have encountered a few issues but the maintainers were very responsive and helpful.

Integration of WebR with the TLG Catalog

Motivation

  • The integration of WebR into the TLG Catalog aims to make the catalog more interactive and accessible. No more requirement for local R installation.
  • Embedding interactive applications is far superior to static screenshots of it.
  • Enhances usability, making it suitable for training, experimentation, and iterative data analysis.

Live Demonstration

Implementation Challenges and Solutions

Static vs Dynamic

  • ⚠️ WebR code chunks are not executable during render process thus not testable.

  • ⚠️ We want to know whether the examples code does not throw errors (e.g. due to a new package version).

  • βœ… Solution: keep both

Good UX

  • ⚠️ If keep both, we need to assure a good User Experience
  • ⚠️ Embedding shinylive applications require a lot of page width
  • βœ… Solution:

Keep it DRY

  • ⚠️ We want to have a single code chunk for both static and dynamic outputs
  • βœ… Solution: 
    • reusing existing code chunks with knitr::knit_code$get()
    • results = "asis" to dynamically create WebR code chunks
    • Quarto Shortcodes

Keep it DRY - code

```{r setup}
library(dplyr)
(...)
```

```{r output}
tbl <- ...
tbl
```

```{r setup}
library(dplyr)
(...)
```

```{r output}
tbl <- ...
tbl
```

```{r webr-constructor, echo = FALSE, results = "asis"}
code_chunk_id <- c("setup", "output")
code_chunk_content <- lapply(code_chunk_id, knitr::knit_code$get)
final_code_chunk <- unlist(c(
  "```{webr-r}",
  code_chunk_content,
  "```"
))
cat(final_code_chunk, sep = "\n")
```

```{r webr-constructor, echo = FALSE, results = "asis"}
code_chunk_id <- c("setup", "output")
code_chunk_content <- lapply(code_chunk_id, knitr::knit_code$get)
final_code_chunk <- unlist(c(
  "```{webr-r}",
  code_chunk_content,
  "```"
))
cat(final_code_chunk, sep = "\n")
```

```{r webr-constructor, echo = FALSE, results = "asis"}
code_chunk_id <- c("setup", "output")
code_chunk_content <- lapply(code_chunk_id, knitr::knit_code$get)
final_code_chunk <- unlist(c(
  "```{webr-r}",
  code_chunk_content,
  "```"
))
cat(final_code_chunk, sep = "\n")
```

```{r webr-constructor, echo = FALSE, results = "asis"}
code_chunk_id <- c("setup", "output")
code_chunk_content <- lapply(code_chunk_id, knitr::knit_code$get)
final_code_chunk <- unlist(c(
  "```{webr-r}",
  code_chunk_content,
  "```"
))
cat(final_code_chunk, sep = "\n")
```

```{r webr-constructor, echo = FALSE, results = "asis"}
code_chunk_id <- c("setup", "output")
code_chunk_content <- lapply(code_chunk_id, knitr::knit_code$get)
final_code_chunk <- unlist(c(
  "```{webr-r}",
  code_chunk_content,
  "```"
))
cat(final_code_chunk, sep = "\n")
```

Outcome:

```{web-r}
library(dplyr)
...
tbl <- ...
tbl
```

Adding Shortcodes

File: my_article.qmd

```{r setup}
library(dplyr)
(...)
```

```{r output}
tbl <- ...
tbl
```

`r code_chunk_id <- c("setup", "output")`
{{< include /_utils/webr.qmd >}}

File: _utils/webr.qmd

```{r webr-constructor, echo = FALSE, results = "asis"}
code_chunk_content <- lapply(code_chunk_id, knitr::knit_code$get)
final_code_chunk <- unlist(c(
  "```{webr-r}",
  code_chunk_content,
  "```"
))
cat(final_code_chunk, sep = "\n")
```

Conclusions

WebR integration makes the TLG Catalog more accessible and encourages more user interaction.

The interactive nature of WebR enhances learning and usability, making it a powerful addition for training and experimentation in clinical reporting.

Future directions

πŸš€ CI enhancements

  • Auto-test whether WebR chunks are failing
  • Auto-update shinylive assets, extensions, etc.
  • Custom repos for shinylive allowing for dev version of packages.

πŸ’‘ Introduce WebR to the package documentation

WebR is a native web technology. It should be possible to to integrate into websites created via pkgdown. 🌐 r-lib/pkgdown#2348

πŸ’‘ Introduce Shinylive to the package documentation

roxy.shinylive

Embed Shinylive application(s) in the roxygen2 package documentation, vigniettes, README, etc.

Thank you πŸŽ‰