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
?ninetails::launch_signal_browser| 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
?ninetails::launch_signal_browser_guppy| 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_nameorgroup - 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
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
shinyuser) - All data file paths in
config.ymlmust be readable by theshinyuser -
Dorado Signal Viewer:
PYTHON_PATHmust be set; the specified environment must havepod5installed (pip install pod5); theshinyuser must have execute permissions on the Python binary -
Guppy Signal Viewer: no Python dependency; the
shinyuser must have read access to the fast5 files and to the Nanopolish output
Restart Shiny Server after placing the files:
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.ymland 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 fromman/figures/logo.png) -
favicon.ico— browser tab icon (copy frompkgdown/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.
