Skip to contents

Overview

Ninetails includes an interactive Shiny dashboard for exploring analysis results. The dashboard provides six tabs for classification overview, residue composition, poly(A) length distribution, raw signal visualization, configurable report download, and package information.

Two launcher functions are available depending on the pipeline used:

Launcher Pipeline Signal input
launch_signal_browser() Dorado DRS POD5 files
launch_signal_browser_guppy() Guppy legacy fast5 files

Both launchers support the same two usage modes:

  • Single-sample mode — provide file paths directly; all tabs are available when classification and residue data are supplied.
  • Multi-sample mode — provide a YAML configuration file pointing to multiple samples; enables comparative analysis across samples and experimental groups.

Requirements

The dashboard requires several optional packages. Install them before first use:

install.packages(c("shiny", "plotly", "htmltools", "DT", "base64enc"))

# For multi-sample mode (YAML config):
install.packages("yaml")

# For rug density plots (position distribution):
install.packages("cowplot")

The Signal Viewer tab of launch_signal_browser() additionally requires a working Python environment with the pod5 package, accessible via reticulate. See the installation guide for details. launch_signal_browser_guppy() does not require Python.


Dorado DRS dashboard

Quick start

Single-sample mode

ninetails::launch_signal_browser(
  summary_file = "/path/to/dorado_summary.txt",
  pod5_dir     = "/path/to/pod5/",
  class_file   = "/path/to/read_classes.txt",
  residue_file = "/path/to/nonadenosine_residues.txt"
)

All four arguments are optional. When class_file and residue_file are provided, the Classification, Residues, and Poly(A) length tabs become active. When summary_file and pod5_dir are provided, the Signal Viewer tab enables raw signal visualization.

If only signal data paths are provided (no class_file), only the Signal Viewer tab is functional:

ninetails::launch_signal_browser(
  summary_file = "/path/to/dorado_summary.txt",
  pod5_dir     = "/path/to/pod5/"
)

Multi-sample mode

ninetails::launch_signal_browser(
  config = "/path/to/config.yml"
)

YAML configuration file

samples:
  KO_rep1:
    sample_name: KO_rep1
    group: KO
    class_path: /path/to/KO_rep1/read_classes.txt
    residue_path: /path/to/KO_rep1/nonadenosine_residues.txt
    dorado_summary: /path/to/KO_rep1/dorado_summary.txt   # optional
    pod5_dir: /path/to/KO_rep1/pod5/                      # optional

  WT_rep1:
    sample_name: WT_rep1
    group: WT
    class_path: /path/to/WT_rep1/read_classes.txt
    residue_path: /path/to/WT_rep1/nonadenosine_residues.txt
    dorado_summary: /path/to/WT_rep1/dorado_summary.txt
    pod5_dir: /path/to/WT_rep1/pod5/
Field Required Description
sample_name Yes Display name used in plots and legends
group Yes Experimental condition for grouping
class_path Yes Path to read_classes.txt from ninetails
residue_path Yes Path to nonadenosine_residues.txt from ninetails
dorado_summary No Path to Dorado summary file (for Signal Viewer)
pod5_dir No Path to POD5 file directory (for Signal Viewer)

Launcher reference

Argument Type Description
config character Path to YAML config (multi-sample mode)
summary_file character Path to Dorado summary file
pod5_dir character Path to POD5 directory
class_file character Path to read_classes.txt
residue_file character Path to nonadenosine_residues.txt
... Additional arguments passed to shiny::runApp()

Guppy legacy dashboard

Quick start

Single-sample mode

ninetails::launch_signal_browser_guppy(
  nanopolish_file         = "/path/to/nanopolish_output.tsv",
  sequencing_summary_file = "/path/to/sequencing_summary.txt",
  workspace               = "/path/to/fast5/",
  class_file              = "/path/to/read_classes.txt",
  residue_file            = "/path/to/nonadenosine_residues.txt"
)

nanopolish_file, sequencing_summary_file, and workspace are needed for the Signal Viewer tab. class_file and residue_file activate all other analysis tabs. All arguments are optional.

Multi-sample mode

ninetails::launch_signal_browser_guppy(
  config = "/path/to/config_guppy.yml"
)

YAML configuration file

samples:
  KO_rep1:
    sample_name: KO_rep1
    group: KO
    class_path: /path/to/KO_rep1/read_classes.txt
    residue_path: /path/to/KO_rep1/nonadenosine_residues.txt
    polya_path: /path/to/KO_rep1/nanopolish_output.tsv   # optional
    seq_summary: /path/to/KO_rep1/sequencing_summary.txt # optional
    workspace: /path/to/KO_rep1/fast5/                   # optional

  WT_rep1:
    sample_name: WT_rep1
    group: WT
    class_path: /path/to/WT_rep1/read_classes.txt
    residue_path: /path/to/WT_rep1/nonadenosine_residues.txt
Field Required Description
sample_name Yes Display name used in plots and legends
group Yes Experimental condition for grouping
class_path Yes Path to read_classes.txt from ninetails
residue_path Yes Path to nonadenosine_residues.txt from ninetails
polya_path No Path to Nanopolish polya output (for Signal Viewer)
seq_summary No Path to Guppy sequencing summary (for Signal Viewer)
workspace No Path to multi-fast5 directory (for Signal Viewer)

Guppy-specific dashboard features

The Guppy dashboard provides the same six tabs as the Dorado version, with two additions:

Nanopolish QC (Classification tab) — an additional plot showing the distribution of Nanopolish QC tags (PASS, ADAPTER, NOREGION, SUFFCLIP, etc.) produced by plot_nanopolish_qc().

Fast5 Signal Viewer — uses plot_squiggle_fast5() and plot_tail_range_fast5() instead of POD5-based functions. Includes a Moves toggle to show or hide basecaller move transitions in the signal background. No Python dependency is required.

Launcher reference

Argument Type Description
config character Path to YAML config (multi-sample mode)
nanopolish_file character Path to Nanopolish polya output
sequencing_summary_file character Path to Guppy sequencing summary
workspace character Path to multi-fast5 directory
class_file character Path to read_classes.txt
residue_file character Path to nonadenosine_residues.txt
basecall_group character Fast5 hierarchy level (default: "Basecall_1D_000")
... Additional arguments passed to shiny::runApp()

Dashboard tabs

All tabs described below are available in both launchers unless noted otherwise.

Classification

The first tab provides an overview of the analysis results.

Value boxes at the top display five metrics: number of samples analyzed, number of transcripts found, total read count, number of blank reads, and number of decorated reads.

Read Classification plot shows the distribution of read categories (decorated, blank, unclassified). Three views are available via the “Classification view” dropdown:

  • Summary (N) — simplified view with main categories
  • Detailed (R) — expanded view with all comment codes (YAY, MPU, MAU, IRL, BAC, UNM)
  • Decorated (A) — decorated reads only

Non-A Abundance plot shows the frequency of reads containing one, two, or three or more separate non-adenosine residues per read (plot_nonA_abundance()).

Nanopolish QC plot (Guppy dashboard only) — shows the distribution of Nanopolish QC tags (plot_nanopolish_qc()).

Sidebar controls:

  • Grouping variable — choose between sample_name or group
  • Filter by transcript — server-side searchable dropdown
  • Show as frequency — toggle between raw counts and proportions
  • Show descriptions — toggle explanatory text below each plot

Residues

The Residues tab provides three views of non-adenosine residue composition.

Residue Counts plot shows the distribution of C, G, and U residues (plot_residue_counts()).

Non-A Position Distribution displays rug density plots showing where non-adenosine residues are located along the poly(A) tail relative to tail length (plot_rug_density()). Each residue type is subsampled to a maximum of 1,000 points per sample.

Summary Table (when merged data is available) provides per-transcript statistics (summarize_nonA()).

Poly(A) length

Shows poly(A) tail length distributions across samples or groups (plot_tail_distribution()). Controls include grouping, transcript filter, condition selection, central tendency overlay, x-axis limit, normalization, and color palette.

Signal Viewer

Provides interactive visualization of raw nanopore signals.

Dorado dashboard — reads signals from POD5 files. Requires summary_file and pod5_dir.

Guppy dashboard — reads signals from multi-fast5 files. Requires nanopolish_file, sequencing_summary_file, and workspace. Includes a Moves toggle to show basecaller move transitions.

Both versions provide:

  • Static Viewer — two ggplot2 plots (entire signal and poly(A) region with non-A modification overlays)
  • Dynamic Explorer — interactive Plotly chart with zoom, pan, and hover

Download

Configurable report generator producing a self-contained HTML file with all plots embedded as base64-encoded PNG images.

About

Displays the ninetails logo, citation, links to GitHub, Wiki, pkgdown, and Zenodo, and institute information.


Annotated data

When the input data has been annotated with annotate_with_biomart() (adding symbol and Ensembl transcript ID columns), the dashboard automatically uses symbol as the transcript label in all “Filter by transcript” dropdowns.

class_data_annotated <- ninetails::annotate_with_biomart(
  class_data,
  species = "mmusculus"
)

residue_data_annotated <- ninetails::annotate_with_biomart(
  residue_data,
  species = "mmusculus"
)

Running on a server

Custom port and host

Pass port and host through ... to make the app accessible on your network:

# Dorado
ninetails::launch_signal_browser(
  config = "config.yml",
  port   = 8080,
  host   = "0.0.0.0"
)

# Guppy
ninetails::launch_signal_browser_guppy(
  config = "config_guppy.yml",
  port   = 8080,
  host   = "0.0.0.0"
)

Sourcing the app directly

The app can also be sourced directly from the installed package without using the launcher function. This is useful for embedding in scripts or for Shiny Server deployments where shinyOptions must be set manually:

library(ninetails)
library(shiny)

# Set data via shinyOptions before sourcing
shiny::shinyOptions(
  ninetails.class_data    = class_data,
  ninetails.residue_data  = residue_data,
  ninetails.merged_data   = merged_data,
  ninetails.signal_config = list(),
  ninetails.summary_file  = "/path/to/dorado_summary.txt",
  ninetails.pod5_dir      = "/path/to/pod5/"
)

# Source the app into an isolated environment
app_dir <- system.file("app", package = "ninetails")       # Dorado
# app_dir <- system.file("app_guppy", package = "ninetails")  # Guppy

app_env <- new.env(parent = globalenv())
source(file.path(app_dir, "app.R"), local = app_env)

shiny::shinyApp(ui = app_env$ui, server = app_env$server)

Deploying to Shiny Server

A unified deployment wrapper is included in the package at inst/deployment/app.R. It auto-detects the pipeline (Dorado or Guppy) from the YAML configuration and sources the correct app at runtime.

Setup

# 1. Create the app directory on the server
deploy_dir <- "/srv/shiny-server/ninetails"
dir.create(deploy_dir, recursive = TRUE, showWarnings = FALSE)

# 2. Copy the deployment wrapper
file.copy(
  system.file("deployment", "app.R", package = "ninetails"),
  file.path(deploy_dir, "app.R"),
  overwrite = TRUE
)

# 3. Copy your YAML configuration
file.copy("config.yml", file.path(deploy_dir, "config.yml"))

# 4. Copy or symlink static assets
# For Dorado app:
file.symlink(
  system.file("app", "www", package = "ninetails"),
  file.path(deploy_dir, "www")
)
# For Guppy app (if config describes Guppy data):
# file.symlink(
#   system.file("app_guppy", "www", package = "ninetails"),
#   file.path(deploy_dir, "www")
# )

Configuring the deployment wrapper

Edit the top section of the deployed app.R to set three variables:

# In /srv/shiny-server/ninetails/app.R:

# Path to the YAML config (relative to app.R)
config_path <- file.path(getwd(), "config.yml")

# Python binary with 'pod5' installed (Dorado Signal Viewer only)
# Set to NULL if signal visualization is not needed
PYTHON_PATH <- "/home/user/miniconda3/envs/r-reticulate/bin/python"

# Fast5 basecall group (Guppy Signal Viewer only)
BASECALL_GROUP <- "Basecall_1D_000"

The wrapper auto-detects the pipeline from the YAML: if the first sample contains pod5_dir or dorado_summary fields, the Dorado app is used; if it contains workspace or polya_path, the Guppy app is used.

Common Python path examples:

Environment Typical path
System Python /usr/bin/python3
Conda env /home/user/miniconda3/envs/r-reticulate/bin/python
virtualenv /home/user/.virtualenvs/ninetails/bin/python
pyenv /home/user/.pyenv/versions/3.11.0/bin/python

Run which python in the environment where pod5 is installed to find the correct path.

Directory structure

/srv/shiny-server/ninetails/
├── app.R          # deployment wrapper (from inst/deployment/)
├── config.yml     # your YAML configuration
└── www/           # symlink to inst/app/www/ or inst/app_guppy/www/
    ├── logo.png
    ├── favicon.ico
    └── IIMCB_logo.png

Requirements

  • ninetails and all Suggests dependencies must be installed system-wide (accessible to the shiny user)
  • All data file paths in config.yml must be readable by the shiny user
  • Dorado Signal Viewer: PYTHON_PATH must be set; the specified environment must have pod5 installed (pip install pod5); the shiny user must have execute permissions on the Python binary
  • Guppy Signal Viewer: no Python dependency; the shiny user must have read access to the fast5 files and to the Nanopolish output

Restart Shiny Server after placing the files:

sudo systemctl restart shiny-server

The dashboard will be accessible at http://your-server:3838/ninetails/.

Note: When you update the ninetails package, the deployed app picks up changes automatically (it sources from the installed package at runtime). To change the dataset, edit config.yml and restart Shiny Server.


Static assets

The dashboard expects three image files in inst/app/www/ (Dorado) or inst/app_guppy/www/ (Guppy):

  • logo.png — ninetails logo (copy from man/figures/logo.png)
  • favicon.ico — browser tab icon (copy from pkgdown/favicon/)
  • IIMCB_logo.png — IIMCB institute logo (displayed in the About tab)

Troubleshooting

Rug density plots are empty or show an error plot_rug_density() requires the cowplot package. Install it with install.packages("cowplot").

Download button produces an error The report generation requires base64enc. Install with install.packages("base64enc").

Signal Viewer shows “No POD5 file found” (Dorado) Ensure pod5_dir points to the directory containing .pod5 files. The app searches recursively within that directory.

Signal Viewer shows “Extraction failed” (Dorado) The Python pod5 package must be installed and accessible via reticulate. Check with:

reticulate::py_module_available("pod5")

Signal Viewer shows no signal (Guppy) Ensure nanopolish_file, sequencing_summary_file, and workspace all point to valid paths accessible to the R session. The read ID selected must exist in the Nanopolish output.

Classification or Residue plots are blank In single-sample mode, class_file and/or residue_file must be provided. Without them, the corresponding tabs show placeholder messages.

“Column more doesn’t exist” in Non-A Abundance plot This occurs when no reads have 3 or more non-A residues. Update plot_nonA_abundance() to the latest version which handles missing columns after pivot.

Y-axis shows scientific notation The dashboard disables scientific notation globally with options(scipen = 999) at startup. If you still see scientific notation, ensure you are running the latest version of the app.