Report Viewer
The Pixel Patrol viewer is a browser-based interactive dashboard for exploring .parquet reports. It is built with DuckDB and Plotly and runs in two modes:
- Static - the viewer runs entirely using DuckDB WASM with no server. Used when opening the hosted viewer or a static HTML file built with
pixel-patrol build-viewer-html. - Python-served -
pixel-patrol viewstarts a local HTTP server backed by native DuckDB. SQL queries run server-side, making it significantly faster for large files.
Opening a report
From the command line:
Starts a local HTTP server backed by native DuckDB and opens the viewer in your browser. Recommended for large files - SQL queries run server-side rather than in the browser.
From the hosted viewer:
Open ida-mdc.github.io/pixel-patrol/viewer and drag and drop your .parquet file, or use the file picker.
From a built static viewer:
Build a self-contained viewer file and open it alongside your parquet:
Open viewer.html in any browser and load your parquet from there. To share with someone, send them both files.
Hosted on a static server:
Deploy a viewer site folder and load a remote parquet via URL parameter:
pixel-patrol build-viewer-html -o my-site/
# deploy my-site/ to any static host, then open:
# https://your-host.com/my-site/?data=https://your-host.com/report.parquet
Via URL parameter (hosted viewer):
Warning
The static viewer may not be able to load very large parquet files (e.g. 5 GB+). Use pixel-patrol view for large reports.
The interface
The report shows the project name and description at the top (if provided when processing). The sidebar on the left contains all controls and widgets:
- Group by - choose any column to split the data into groups. Each distinct value becomes a group with its own color across all plots. Defaults to the
pathcolumn (the conditions from-p). - Filter - restrict the data to rows matching a column/operator/value combination.
- Dimension selectors - for multi-dimensional data (Z, T, C, S), select which slice to display across widgets.
- Show significance - toggle statistical significance brackets on violin plots (Mann-Whitney U test, Bonferroni corrected).
- Save - export the current data as a
.parquetor.csvfile. - Widget list - all available widgets. Click a widget to expand it. Widgets that require columns not present in the report hide themselves automatically.
Available widgets
| ID | Widget | Description |
|---|---|---|
summary |
File Data Summary | Dataset-wide KPIs (file/image counts, total size, file extensions, common base path) plus a per-group breakdown table when grouped. Quick overview of dataset composition. |
image-table |
Image Table | Sortable, searchable table of full-image statistics - one row per image file, no per-slice or per-channel rows. |
file-stats |
File Statistics | File count and total size by extension, file size distribution, and modification timeline. Properties with no variance across files are shown as a summary table instead of a chart. |
sunburst |
File Structure Sunburst | Interactive sunburst chart of the file and folder hierarchy, sized by file count or total file size. Click to zoom in; click the center to zoom out. |
metadata |
Metadata | Distribution of pixel data types (dtype) and dimension orderings (dim_order) per group. Also lists properties shared by all files and available dimension ranges. Requires loader metadata. |
dim-size |
Dimension Size Distribution | Distributions of image dimension sizes (X, Y, Z, T, C, ...) across the dataset. X/Y scatter plot plus per-dimension strip plots. Useful for spotting size mismatches between groups. |
histogram |
Pixel Value Histograms | Mean pixel intensity histogram per group, computed per image and normalised to sum to 1. Supports fixed 0-255 bins or native pixel range. Reveals bit-depth issues, clipping, or exposure differences. |
mosaic |
Image Mosaic | Thumbnail grid, one image per file. Sortable by any metric (e.g. mean_intensity, laplacian_variance) to surface visual outliers. Border colors indicate group membership. |
violin-basic |
Pixel Value Statistics | Violin and box plots comparing pixel statistics (mean_intensity, std_intensity, min_intensity, max_intensity) across groups. By default each point is one image; use the Slice by toggles to switch to one point per (image × dimension slice) instead. Plots over 5,000 points show a SQL-aggregate box summary instead of a full violin. |
violin-quality |
Image Quality Metrics | Violin and box plots comparing image quality metrics across groups. Requires pixel-patrol-image. Supports the same Slice by toggles and box-summary fallback as Pixel Value Statistics. Metrics: Michelson contrast (global contrast ratio; higher = greater dynamic range), MSCN variance (Mean Subtracted Contrast Normalized variance; sensitive to noise and blur), Texture heterogeneity (coefficient of variation of local standard deviations; captures spatial non-uniformity of texture), Laplacian variance (variance of discrete Laplacian; higher = sharper image; scale-dependent), Blocking index (strength of blocky compression artifacts), Ringing index (edge oscillation artifacts from compression). |
stats-across-dims-basic |
Basic Statistics Across Dimensions | How pixel statistics (mean, std, min, max) change across Z, T, C, or S slices. Useful for detecting drift or unexpected variation within a dimension. A dashed line shows the percentage of images that still have a slice at each position, for spotting datasets where images don't all have the same number of slices. |
stats-across-dims-quality |
Quality Metrics Across Dimensions | How image quality metrics change across dimension slices. Useful for detecting focus drift over time (T), channel-specific artifacts (C), or depth-dependent quality changes (Z). Requires pixel-patrol-image. A dashed line shows the percentage of images that still have a slice at each position, for spotting datasets where images don't all have the same number of slices. |
custom-plot |
Custom Plot | Build your own scatter, violin, bar, count, or heatmap plot from any columns in the report, with grouping, coloring, and palette controls. Each plot has its own Slice by toggles and per-image/per-slice badge. Add multiple plots, and export any of them as a standalone viewer plugin file. |
Widget data resolution
Each widget card shows a small badge indicating what one datapoint in that widget represents:
- 📄 per file - each datapoint is a file (e.g. File Structure Sunburst).
- 🖼️ per image - each datapoint is an image. A file containing multiple images (a stack or container) contributes one datapoint per image (e.g. Image Table, Image Mosaic, Pixel Value Statistics).
- 🧩 per slice - each datapoint is a slice within an image, such as a channel, Z-plane, or timepoint (e.g. Statistics Across Dimensions).
Pixel Value Statistics, Image Quality Metrics, and Custom Plot can switch between per image and per slice via their Slice by toggles - their badge updates accordingly. File Data Summary spans multiple resolutions (files, images, slices) and shows no badge.
This helps you reason about what's actually being aggregated or plotted, especially for multi-dimensional or multi-image files.
How it works
In static mode, the viewer loads the parquet file into DuckDB WASM - a full SQL engine running in a browser Web Worker. All queries run directly against the parquet data in the browser; no data is sent to any server.
In Python-served mode (pixel-patrol view), the viewer connects to a local Python HTTP server that runs native DuckDB server-side. This is significantly faster for large files since native DuckDB can handle queries that would exhaust browser memory.
Widgets subscribe to the current filter, group, and dimension state and re-query DuckDB whenever any of those change. The DuckDB table is always named pp_data.
Extensibility
The viewer is designed to be extended. Widgets are JavaScript ES modules loaded from extension.json manifests at runtime - no viewer rebuild required to add a custom widget.
See Extensions for how to write and load your own plugins.