TissuePlex User Manual
TissuePlex is a web-based viewer for spatial transcriptomics data. It layers cell positions, gene expression, cell-to-cell signaling, and custom analysis results on top of a tissue morphology image, running in a browser on your local machine.
No programming experience is required. This guide covers installation, data setup, and every control in the interface.
Six platforms are supported — Xenium, Visium, Visium HD, MERSCOPE, CosMx and seqFISH — and TissuePlex works out which one it is looking at from the files in the folder. The examples below use Xenium; everything transfers, and the platform-specific differences are called out where they matter.
By the end of this guide you will have: TissuePlex installed and running, your dataset loaded, cell-cell communication edges from NICHESv2 visible, and custom analysis results available as cell color overlays.
What You'll Need
A Mac or Windows computer
TissuePlex runs in the browser. No special graphics card is needed.
Your platform's output folder
Whatever your instrument or pipeline produced, unmodified. For Xenium that
is the folder containing experiment.xenium,
morphology.ome.tif and transcripts.parquet; for the
Visium platforms it is the contents of Space Ranger's outs/. See
the platform table in step 5. The image is optional: a dataset without its
morphology or DAPI still shows its cells, transcripts and edges, on a plain
frame.
An internet connection
Required for the initial download steps only. After setup, TissuePlex runs on your local machine.
About 30–45 minutes
For initial setup. Subsequent launches take seconds.
Getting TissuePlex Running
Install two programs (Git and Docker), download TissuePlex, and run it for the first time. These are one-time steps; after setup, launching TissuePlex takes a single command.
Install Git
Git downloads and manages software repositories. It lets you pull TissuePlex updates with a single command.
On a Mac
Open Terminal (Applications → Utilities, or
⌘ Space and type "Terminal") and run:
git --version
If you see git version 2.x.x, Git is already installed;
skip to Step 2. If a pop-up offers to install "Command Line Developer Tools"
or "Xcode Command Line Tools", click Install and follow the
prompts.
On Windows
Go to git-scm.com, download the Windows installer, and run it. Accept the default settings. When it finishes, you will have a program called Git Bash. Use Git Bash wherever this guide says "Terminal".
git --version in Terminal or Git Bash. A version number should
appear.
Install Docker Desktop
Docker runs TissuePlex in an isolated container that bundles all required software (Python, databases, web server). Install Docker once; no other dependencies are needed on your machine.
Go to docker.com/products/docker-desktop and download Docker Desktop for your operating system. Install it as you would any other application.
Recommended: increase Docker's memory limit
In Docker Desktop, go to Settings (gear icon) → Resources. If your machine has 16 GB of RAM or more, set the memory limit to at least 8 GB, then click Apply & Restart.
Download TissuePlex
Open Terminal (Mac) or Git Bash (Windows). Navigate to the folder where you want to keep TissuePlex, for example:
cd ~/Documents
Then clone the repository:
git clone https://github.com/RaredonLab/TissuePlex.git
cd TissuePlex
This creates a TissuePlex folder and downloads all the code
into it. The second command moves your terminal into that folder.
cd ~/Documents/TissuePlex), run
git pull, then docker compose up --build.
git pull,
Docker Desktop sometimes reuses a stale build cache and serves an outdated
version of the app, resulting in a black screen with an error about a wrong
MIME type in the browser console. If this happens, force a clean rebuild:
docker compose build --no-cache
docker compose up
First Launch
TissuePlex includes a small sample dataset for verifying the installation. With Docker Desktop running, run the following from inside the TissuePlex folder:
docker compose up --build
The first run downloads and builds all container images, which takes
5–15 minutes depending on internet speed. A large amount of
build output will scroll by. When you see messages containing
uvicorn running and nginx, TissuePlex is ready.
Open Chrome or Firefox and go to:
http://localhost:3000
The TissuePlex viewer should load with the sample dataset.
Stopping TissuePlex
Press Ctrl + C in the terminal to stop the process, then run:
docker compose down
docker compose up (without --build) is faster.
Add --build after a git pull to rebuild with
the latest changes.
Load Your Dataset
TissuePlex reads from a parent folder containing one or more dataset subfolders. The expected layout:
Set DATA_PATH to the parent folder. Multiple dataset folders
are supported; TissuePlex lists them all in the interface.
Mac or Linux
DATA_PATH="/Users/yourname/xenium-data" docker compose up --build
Windows (Git Bash)
DATA_PATH="C:/Users/yourname/xenium-data" docker compose up --build
/).
TissuePlex detects the platform from the files present in each subfolder:
| Platform | Required file in the dataset folder | Unit |
|---|---|---|
| Xenium (10x Genomics) | experiment.xenium | cell |
| Visium HD (10x Genomics) | binned_outputs/square_*um/ | bin |
| Visium (10x Genomics) | spatial/scalefactors_json.json plus a tissue_positions file | spot |
| MERSCOPE (Vizgen) | cell_by_gene.csv or cell_metadata.csv | cell |
| CosMx (Nanostring) | a file ending in _tx_file.csv | cell |
| seqFISH (Spatial Genomics) | a file matching *_CellCoordinates*.csv | cell |
Folders without a matching sentinel file are silently skipped.
outs/ directory — the folder that directly contains
spatial/ — not its parent.
The interface adapts to whichever platform is loaded. Panels are relabelled to match the unit — a Visium dataset says Spot Segments, Spot Filter and Spot Info where a Xenium one says Cell, and Visium HD says Bin. Layers a platform cannot serve are hidden entirely: the two Visium platforms measure counts per spot or bin rather than per molecule, so the Transcripts layer does not appear for them.
Enriching Your Data
TissuePlex can display enriched data alongside the standard Xenium output: cell-cell communication edges from the NICHESv2 R pipeline, and custom cell metadata such as clustering labels or pseudotime scores. Both are optional; the core viewer works without them.
The NICHESv2 Edge Layer
TissuePlex can render cell-cell communication as a spatial graph overlaid on the tissue. Each line represents a pair of neighboring cells; lines are colored and filtered by ligand-receptor mechanisms (LRMs): the molecular signals passing from one cell to another.
This data comes from NICHESv2, a Raredon Lab R pipeline that scores every spatially neighboring cell pair for every ligand-receptor interaction in the dataset.
The output TissuePlex reads is a single file, edges.parquet,
placed in the dataset folder alongside experiment.xenium. When
present, the edge layers appear in the Layer Panel. When absent, those layers
are hidden and all other features work as normal.
Install R and RStudio
R is a programming language widely used in biology and statistics. RStudio is a graphical interface for writing and running R code.
Install R
Go to cran.r-project.org and download the latest version of R for your operating system.
Install RStudio
Go to posit.co/download/rstudio-desktop and download the free RStudio Desktop version. Install it after R.
Install required R packages
Open RStudio. In the Console panel, paste the following and press Enter:
install.packages(c("Seurat", "arrow", "dplyr", "devtools"))
Installation may take several minutes. Then install the NICHESv2 package; ask a lab member for the current installation command.
Run NICHESv2 and Export Edge Data
The workflow has three steps: load your Xenium data into R, run NICHESv2 to score cell-cell communication, and export the result for TissuePlex.
library(Seurat)
library(NICHESv2)
# 1. Load your Xenium data into R
xenium_obj <- LoadXenium("/path/to/your/xenium-dataset")
# 2. Run NICHESv2 (ask a lab member for recommended parameters)
niches_result <- RunNICHES(xenium_obj, ...)
# 3. Export for TissuePlex (writes edges.parquet to the dataset folder)
export_to_TissuePlex(
niches_result,
output_dir = "/path/to/your/xenium-dataset"
)
export_to_TissuePlex() writes edges.parquet
to your dataset folder. The resulting structure:
RunNICHES() depend on your dataset and the current version of
NICHESv2. Ask a lab member for guidance on your first run.
This step can take significant time for large datasets.
Verify the result
Restart TissuePlex. The Tissue Graph and
Directed Edges sections should appear in the Layer
Panel. If they do not, confirm that edges.parquet is directly
inside the dataset folder at the same level as
experiment.xenium.
Add Custom Cell Metadata
TissuePlex can color cells by any metadata you generate: clustering labels,
cell type annotations, pseudotime scores, or gene module scores. Place a CSV
in a subfolder named cell-metadata inside the dataset directory.
Every column is automatically available in the color-by dropdown.
A typical R workflow
library(Seurat)
# Load your Xenium data
xenium_obj <- LoadXenium("/path/to/your/xenium-dataset")
# --- Run your analysis here ---
# For example, cluster the cells:
xenium_obj <- NormalizeData(xenium_obj)
xenium_obj <- FindVariableFeatures(xenium_obj)
xenium_obj <- ScaleData(xenium_obj)
xenium_obj <- RunPCA(xenium_obj)
xenium_obj <- FindNeighbors(xenium_obj)
xenium_obj <- FindClusters(xenium_obj, resolution = 0.5)
# Extract the columns you want to export
metadata_to_export <- xenium_obj@meta.data[, c("seurat_clusters")]
# Add as many columns as you like; they all appear in TissuePlex.
# Create the cell-metadata folder if it does not already exist
dir.create(
file.path("/path/to/your/xenium-dataset", "cell-metadata"),
showWarnings = FALSE
)
# Save the file (cell barcodes become the row names automatically)
write.csv(
metadata_to_export,
file.path("/path/to/your/xenium-dataset", "cell-metadata", "my_clusters.csv")
)
LoadXenium() ensures
the barcodes in xenium_obj@meta.data are already correct. Ask
a lab member for guidance on clustering parameters appropriate for your
dataset.
Resulting folder structure:
After adding the file, restart TissuePlex. Metadata columns appear automatically under Cell Segments → Color by → Cell metadata.
cell-metadata/. TissuePlex merges them on the barcode key;
each file can contain different columns.
Using TissuePlex
This section covers every control in the TissuePlex interface.
Interface Overview
TissuePlex has four main areas:
- The Viewer. The large central area showing the tissue image and all data layers. Pan by clicking and dragging; zoom with the scroll wheel or pinch gesture.
- The Layer Panel. The right-hand panel for controlling layer visibility, color mappings, gene filters, and LRM selections.
- The Annotation Toolbar. A compact bar at the top of the viewer with tools for drawing regions, measuring distances, toggling split-screen mode, and saving images.
- Info Panels. Floating panels that appear when you click on a cell or edge, showing metadata and scores for that object.
Dataset & Image Picker
At the top of the Layer Panel are two dropdowns:
- Dataset: lists all datasets found in your
DATA_PATHfolder. - Image: lists the available OME-TIFF files in the dataset. Most Xenium datasets have one.
Switching datasets reloads all layers automatically. The first time each image is viewed, TissuePlex builds a tile pyramid (10–30 seconds); if the canvas looks blank, wait and refresh.
In split-screen mode these dropdowns move into each panel's own header instead, because the two panels can show different datasets and an image or edge file only means something relative to one of them.
Changing a panel's dataset clears the settings that name a column, gene or mechanism — metadata filters, the color-by field, the gene selection, the mechanism checklist. It has to: those names come from the dataset you just left. Sliders, palettes and layer visibility are kept. While the panels are linked, this clears both; unlinked, only the panel you changed.
Morphology Image
The morphology image is the tissue photograph that forms the base of the viewer. In the Layer Panel, the Morphology row lets you toggle it on or off and adjust its opacity. Reducing opacity can help other data layers stand out more clearly on a dark background.
The image is streamed as a tile pyramid, so it renders sharply at every zoom level without loading the entire file into memory at once.
Cell Segments
The Cell Segments section controls how individual cells are drawn. Each detected cell is shown as a polygon matching its actual measured boundary.
Visibility and Opacity
Separate opacity sliders control the cell fill (solid interior) and outline (border line):
- Use the checkbox next to Cell Segments to show or hide boundaries entirely.
- The fill slider adjusts interior opacity.
- The outline slider adjusts the border line weight.
The sample slider controls what fraction of cell boundaries are loaded. At low zoom it adjusts automatically; raise it when zoomed in to load more cells.
Color By
The Color by dropdown colors each cell by a data value.
Off (default)
Cells shown in a neutral color. Use this to view cell positions without a data overlay.
Gene Set
Colors each cell by the combined expression of a selected set of genes. High-expressing cells appear at the hot end of the color scale; low-expressing cells at the cold end.
- The gene set is defined by the selection in the Transcripts gene filter.
- Choose a color palette: viridis (yellow→purple), plasma (yellow→magenta), magma (yellow→black), or inferno. Viridis is recommended for colorblind accessibility.
- A color legend shows the data range. Use the clamp sliders to restrict the color range to a specific window, useful when outliers at the high end compress the variation across the rest of the dataset.
- The fade to slider sets the fill opacity of the lowest-expressing cells; the fill slider stays the maximum. At the maximum nothing fades. Drag it down to let low-expressing cells recede so the high expressers stand out.
Cell Metadata
Colors each cell by any metadata column, including supplemental columns
added to the cell-metadata/ folder.
- Use the field dropdown to select the column.
- Continuous columns (pseudotime, module scores, etc.) use a gradient palette with clamp controls.
- Categorical columns (cluster labels, cell type names, etc.) are assigned distinct colors automatically, one per category, with a legend of editable color swatches.
Treat as Categorical
When you pick a numeric column, a treat as categorical checkbox appears beneath the dropdown. This is the control you want for integer-coded categories.
Cluster IDs are the usual case: fwrite on a Seurat
@meta.data writes seurat_clusters as plain integers,
so nothing in the file distinguishes "cluster 7" from a measurement. TissuePlex
guesses — an integer column with 30 or fewer distinct values is treated as
categorical — and the checkbox overrides that guess in either direction:
- Checked — one distinct, editable color per value, with the legend in numeric order, so cluster 10 comes after cluster 2 rather than between 1 and 2.
- Unchecked — a continuous gradient with clamp sliders. Useful for a coded column with few levels that you would rather read as a scale.
- An auto button returns the column to automatic detection.
The choice is remembered per column for the session. It applies to edge metadata too, in the Edge Data section.
Filtering by Metadata
The Cell Filter section restricts the whole view to a subset of your data — one sample, a few cell types, a range of values. Everything outside the subset is simply not drawn.
How to use it
- Pick a column from the dropdown. Any cell metadata column works, including supplemental ones.
- Categorical columns give you a checkbox per value. Tick the ones you want; all and none buttons are provided. With nothing ticked, everything is shown — an empty selection means "no restriction", not "hide everything".
- Continuous columns give you min and max boxes, both optional and both inclusive. The placeholder text shows the column's actual range.
- clear filter removes the restriction.
What the filter affects
- Cell segments — only matching cells are drawn, and only they can be clicked or captured by a region selection.
- Nothing else. The cell filter does not touch edges or the tissue graph — filtering cells and filtering edges are independent actions. To narrow the edges, use the sending and receiving filters described below.
- Transcripts are not filtered. Several platforms ship no transcript-to-cell assignment at all, so there is nothing to match on.
Filtering edges by sending and receiving cell
Edge Filter inside Edge Data has two dropdowns side by side — Sending cell and Receiving cell. Each offers any cell metadata column, the same list the cell filter uses, and each constrains one end of an edge.
- Set one and that end is constrained while the other is free — "everything sent from crypt cells, to anywhere".
- Set both and you get the intersection: senders in one group, receivers in the other. This is how you ask for fibroblast → endothelial signalling and nothing else.
These are independent of the Cell Filter above. Narrowing the cells you draw does not narrow the edges, and vice versa. An edge may therefore terminate on a cell that is not currently drawn — that is intended, so the graph structure can be read on its own terms.
Below the two dropdowns, a third filter works on columns of the
edge table itself, including annotations from an
edge-metadata/ folder — a curation call, a confidence score, a
review flag.
All of these are distinct from the LRM Mechanisms checklist. The checklist chooses which mechanisms are scored on every edge; the filters choose which cell pairs are drawn at all.
The order things happen in
Understanding this makes the controls predictable:
- every edge in view
- density — keeps a spatially random fraction
- the result is the Tissue Graph layer
- sending, then receiving, then the edge-table filter
- the result is the Edge Data layer
Because the edge data is filtered from the tissue graph, it can never appear where there is no graph edge beneath it. Both layers respond to the one sample slider and stay aligned as you move it.
Transcripts
The Transcripts layer renders individual detected RNA molecules as colored dots, each colored by gene identity.
Quality Filter (Xenium)
Each Xenium transcript has a Q-Score, the instrument's estimate of how reliably it was decoded. Like Xenium Explorer, TissuePlex hides transcripts with a Q-Score below 20 by default. On a typical run that is about one transcript in ten.
- Tick show low-quality (Q < 20) in gray under the Transcripts layer to show them. They are drawn gray whatever their gene, as in Xenium Explorer.
- The counter includes low-quality transcripts only while they are shown.
- The option appears only for datasets that record a Q-Score (Xenium). Other platforms are unaffected.
Gene Filter
By default, transcripts from all detected genes are shown, each in its own color. To restrict the display to specific genes:
- The current status reads either all N genes or M / N genes selected.
- Click select ▼ (or edit ▼ if a filter is active) to open the gene picker.
- Search by gene name and check or uncheck any gene.
- Click all to remove the filter, or none to start a fresh selection.
- Selected genes have an ✕ button for individual removal.
- Click clear to reset to all genes.
Importing a Gene List
To show a list of genes you already have, such as markers from a Seurat analysis, click import next to the gene count and choose a CSV file. The selection is replaced by the genes in the file. export saves the genes currently shown in the same format, so a selection can be saved and loaded again later.
gene,group
Epcam,epithelium
Lgr5,stem
Muc2,goblet
- The first row must contain a column named
gene, in any letter case. Other columns are ignored, so a Xenium Explorer gene-group file (gene,group) imports unchanged. - Gene names must match the dataset exactly, including
letter case:
EPCAMdoes not matchEpcam. Names that do not match are skipped. - If no name in the file matches, nothing changes and a red message
explains why. The same happens for a file with no
geneheader, and for an Excel workbook. Save those with File → Save As → CSV UTF-8.
Gene-color assignments can be imported and exported as CSV with the import palette / export palette buttons, useful for reproducing a color scheme across sessions.
Connectivity Layers
These layers require edges.parquet in the dataset folder (see
Step 8). They visualize cell-cell communication as a spatial graph overlaid
on the tissue.
Sample
The sample slider, at the top of the Edge Data section, controls what fraction of the available edges are drawn — for the Tissue Graph and the Directed Edges alike, so the two always line up. It works exactly like the sample slider under Cell Segments. The default is 10%.
- At a low sample (1–10%): a sparse graph useful for viewing overall connectivity patterns.
- At a high sample (50–100%): many more edges, revealing densely connected hubs. Rendering may slow for large datasets.
Tissue Graph
The Tissue Graph row, just below the sample slider, is a structural background layer showing which cells are spatial neighbors, independent of any LRM information. Each line indicates spatial adjacency between two cells. Use the checkbox to toggle it and the opacity slider to adjust its visual weight.
The tissue graph is ground truth: the total set of edges in view. No filter narrows it — it is shown or hidden, nothing else. Only the sample slider changes how many of its lines are drawn, and that applies equally to the Directed Edges on top, so the two always align.
Use opacity, not the sample, to make it recede behind the edge data. Lowering the sample removes lines from a layer whose whole purpose is to show the complete structure.
Directed Edges
The Directed Edges layer is the quantitative counterpart to the Tissue Graph. Each arrow represents a directed signal from a sending cell to a receiving cell, with appearance determined by the active ligand-receptor mechanisms (LRMs).
When two cells communicate in both directions (A → B and B → A), both arrows are offset from each other, keeping bidirectional signals visually distinct.
Style Controls
Directional
The Directional checkbox renders A → B and B → A as two offset parallel lines. On by default.
Arrowheads
The Arrowheads checkbox adds directional tips at the receiving end of each edge (available only when Directional is on). Two additional controls appear when arrowheads are active:
- arrow scale: adjusts arrowhead size.
- Full / Harpoon: solid triangle or single-sided chevron. Harpoon style mimics the chemistry ⇌ notation and is often cleaner for dense graphs.
Autocrine
The Autocrine checkbox draws autocrine signalling — a cell signalling to itself — as a ring around that cell. NICHESv2 emits one autocrine edge per cell, so on real output expect a ring on every cell that has any self-signal.
Autocrine rings behave exactly like directed edges in every other respect:
- They are colored by the same control and the same scale. Set edge color to LRM Set and the rings are shaded by signal strength alongside the lines; set it to a metadata column and they take that column's colors. One legend describes everything on screen.
- They obey the LRM Mechanisms checklist. Narrow to one mechanism and only the cells with autocrine signal through that mechanism keep their ring.
- They obey the cell and edge metadata filters, and the sample slider.
- Clicking a ring opens the same edge detail panel, listing the mechanisms scored for that self-edge.
Two sliders appear when the checkbox is on:
- ring r: ring radius, in image pixels. Increase it on large tissues where the default is small relative to the field of view.
- ring w: ring line width.
Width and Offset
- width: thickness of all edge lines.
- offset (visible when Directional is on): perpendicular separation between the A → B and B → A lines.
Minimum Strength Filter
The min strength slider hides edges below a total interaction score threshold. Raising it restricts the view to stronger interactions and reduces visual clutter.
Edge Color
The edge color dropdown has three modes:
- Default (uniform): all edges in a single neutral color.
- LRM Set (selected mechanisms): edges colored by total communication score across active LRMs. The color scale adapts to the current viewport. A palette picker, a fade to slider and clamp controls appear below. Fade to is the opacity of the weakest edge: leave it at the maximum and every edge draws at the Edges opacity; drag it down and weak edges become translucent while the strongest keep the full opacity.
- Metadata column: color edges by a metadata field such as sending or receiving cell type. Continuous fields use a gradient palette; categorical fields use distinct colors with a legend.
LRM Mechanisms Checklist
The LRM Mechanisms list shows every ligand-receptor
mechanism in your edges.parquet data. Toggle individual mechanisms
on or off to focus the visualization.
- A counter shows how many are active (e.g. 488 / 488 active).
- The all and none buttons select or deselect everything.
- Use the search box to filter by gene name (e.g. type "Tgfb" to find all TGF-β mechanisms).
- Hiding an LRM reduces each edge's visible score by that mechanism's contribution; edges whose score reaches zero are hidden.
Importing a Mechanism List
Click import in the checklist header and choose a CSV file. Only the mechanisms in the file stay active; every other mechanism is unchecked. export saves the active mechanisms in the same format. Either of two layouts is accepted:
lrm
Wnt5a|Fzd1
Notch1|Dll4
ligand,receptor
Wnt5a,Fzd1
Notch1,Dll4
- The first row must contain an
lrmcolumn, or both aligandand areceptorcolumn, in any letter case. If both layouts are present,lrmis used. - Names must match the edge file exactly, including
letter case and direction:
Fzd1|Wnt5ais a different mechanism fromWnt5a|Fzd1and will not match. - Receptors made of several subunits contain commas, so put them in
quotes:
Fn1,"Itgav,Itgb3". Excel adds the quotes itself when it saves a CSV. - If nothing in the file matches, or the header is missing, nothing changes and a red message explains why.
- The imported list belongs to one edge file. Switching the edge source or the dataset makes every mechanism active again; import the file again if you need it.
Clicking to Explore
Clicking on cells or edges opens floating info panels with detailed information.
Clicking on a Cell
Click inside a cell to open the Cell Info Panel, which shows the barcode ID, all metadata values for that cell, and the current color-by value highlighted. Click on empty canvas to dismiss.
The Local Neighbourhood
With a cell selected, show local neighbourhood at the bottom of the info panel reveals everything that cell is connected to in the tissue graph. The canvas marks the clicked cell in white, its connected neighbours in yellow, and draws a circle at the distance of the furthest one. The panel reports:
- neighbours and local edges — how many cells it touches, and how many directed edges that is;
- radius in µm, so the reach can be quoted without measuring it off the screen;
- composition — the neighbours broken down by whichever metadata column you are colouring cells by;
- mechanisms — the strongest LRMs across its edges.
The circle is a convenience, not the answer. Connectivity is not evenly spread — a cell at the edge of a tissue has neighbours on one side only — so the circle usually contains cells it is not connected to. The yellow marks are the neighbourhood; the circle only shows how far it reaches.
The summary is computed on the full data, so it is unaffected by the sample slider, by the sending and receiving filters, or by how far you are zoomed in. It describes the tissue, not the current view. Clicking another cell replaces it; hide highlight removes it.
Clicking on an Edge or Tissue Graph Line
Click on any line in the Tissue Graph or Directed Edges layer to open the Edge Info Panel, showing the sending and receiving cell barcodes and the top-scoring LRMs for that edge.
Split-Screen Mode
Split-screen mode divides the viewer into two side-by-side panels. Each has its own pan and zoom, and each can show a different dataset — so you can put two samples, two platforms, or two timepoints next to each other. Both panels can also show the same dataset rendered two different ways.
- Click ⊞ Split in the annotation toolbar to enter split-screen mode.
- Click □ Single to return to a single panel.
- In split mode each panel gets its own dataset, image and edge-source picker in its header, since those only mean something relative to one dataset.
Choosing Which Panel You Are Editing
The sidebar drives both panels. At the top of it, Panel 1 / Panel 2 tabs choose which one your edits apply to, and a checkbox below them controls whether they are linked:
- Linked (the default): every change — opacity, palette, color-by, filters, mechanism selection, edge geometry — applies to both panels at once. This is what makes a side-by-side comparison actually comparable.
- Unlinked: edits apply only to the tab you are on. Use this to show cluster coloring on one side and gene expression on the other, or two palettes, or two filters.
Switching the checkbox back on re-syncs both panels to the tab you are currently on. That is deliberate: a control labelled "linked" over two visibly different panels would not be telling you the truth. Pick the tab whose look you want to keep before you re-link.
Copying Settings From One Panel to the Other
While the panels are unlinked, a copy panel 1 → panel 2 button appears under the checkbox. It copies every display setting from the tab you are on to the other panel in one go, and then leaves the panels independent again — so you can establish a common baseline and diverge from it.
Settings that name something the other dataset does not have are dropped rather than copied: a metadata filter on a column it lacks, a gene allowlist with no genes in common, mechanisms absent from its edge file. Color range limits also reset when the two panels show different datasets, because a range measured in one dataset's units is meaningless in another's.
Matching Zoom Between Panels
The ⇔ Match button sets the other panel to your current panel's zoom while each panel stays centered on its own region.
Match works in microns, not pixels, so the same physical distance spans the same width on screen in both panels — exactly as a scale bar would. This matters when the panels hold different platforms: 20% of a 6.5 mm Visium capture area and 20% of a 55 µm seqFISH region differ by more than fifty-fold.
Color Scales Across Panels
The shared colour scale across panels checkbox, on by default, makes both panels map color through one range computed across both. Leave it on for any figure. Two panels that each auto-scaled to their own data look comparable and are not — one panel's yellow might be 40 counts and the other's 4,000. Turn it off only when one panel's range is so much narrower that sharing flattens it, and say so in the legend.
Annotation Tools
The annotation toolbar offers four interaction modes:
- Pan: the default mode. Click and drag to pan.
- ⬡ Region: draw a polygon on the tissue. Click to place vertices; double-click to close. Regions are colored and labeled, and remain visible on top of all data layers.
- ⟷ Measure: click two points to measure the distance between them in micrometers.
- ▭ Rectangle: drag a rectangle to frame an area for high-resolution figure export. See Saving Images.
⬡ Region and ▭ Rectangle do different things. A region selects cells, and its output is a CSV of barcodes. A rectangle frames an image, and its output is a PNG. Drawing a region does not affect what an export contains, and vice versa.
The Clear button removes the regions, measurements and export rectangle belonging to that panel — each panel has its own toolbar, so clearing one leaves the other's work alone.
In split-screen mode, regions and measurements belong to the panel they were drawn in and appear only there. They are stored in that dataset's coordinates, so a region drawn on one tissue would land somewhere meaningless if it were drawn on the other. Exported cell lists and measured distances likewise resolve against the panel that produced them.
Exporting Cells Within a Region
Each drawn region appears in the Layer Panel's Regions list. The export button saves a CSV of the barcodes of all enclosed cells, for downstream analysis in R.
Saving Images
There are two ways to save an image, for two different purposes.
Save PNG — a quick screenshot
Click Save PNG in the annotation toolbar. This
composites the morphology image and all visible data layers exactly as shown,
at your screen's resolution, and saves it as
tissueplex_[timestamp].png (or
tissueplex_panel1_[timestamp].png in split-screen mode). Good for
slides, notes and sharing a view. Its resolution is limited to the size of the
viewer on screen, so it is not usually enough for print.
Export… — a publication figure
Click Export… to render the data layers again at whatever resolution you ask for. Because the layers are geometry — lines, polygons and points — they are redrawn at the output size rather than enlarged, so they stay sharp at any resolution.
- Optionally choose ▭ Rectangle and drag to frame the area you want. Without a rectangle, the whole current view is used.
- Click Export….
- Set the output width in pixels and the DPI, then click Export PNG.
Resolution is pixels, not DPI. A PNG contains pixels; DPI only means something once you fix a print width. So decide the width in inches your figure will be printed at, multiply by the DPI you need, and use that as the pixel width:
- Single column, 3.5 in at 500 DPI → 1750 px
- Double column, 7 in at 500 DPI → 3500 px
- Double column, 7 in at 600 DPI → 4200 px
Buttons for these three are in the dialog. The DPI you enter is also written into the PNG's metadata, which is what journal submission systems read when they check a figure's resolution.
Options
- Background — black by default, matching the viewer. Transparent is useful for compositing in Illustrator or Photoshop; white suits a printed page. Some submission systems flatten transparency unpredictably, so choose a solid background if you are unsure.
- Scale bar — drawn in a margin band below the plot rather than over the tissue, at a rounded length (50 µm, 100 µm, 500 µm…) computed from the dataset's pixel size.
- Include annotations — off by default; turn it on to draw your regions and measurements into the figure.
The morphology image is not included in Export…. It is a photograph, so unlike the data layers it cannot be redrawn at a higher resolution than it was acquired at, and including it would cap the whole figure at the source image's detail. Use Save PNG if you need the tissue image in the picture, or export the data layers on a transparent background and composite them over the morphology yourself.
Points to watch
- Sampling is not changed for you. The figure shows exactly what the panel shows, including the edge sample and transcript sampling in effect. If you want the full edge set in a figure, raise the sample slider before exporting — and record the value you used in the legend.
- Keep the rectangle on screen. Data is loaded for the current view, so if you pan away from your rectangle the export would be missing whatever is off screen. The dialog warns you when this happens.
- Line weights are preserved, not re-tuned. Strokes are scaled so the export matches what you approved on screen. A weight that reads well on a monitor may still look heavy or thin in print — adjust edge width for the figure and export again.
- If you rotate after drawing the rectangle, the export keeps the orientation the rectangle was drawn at. Redraw it to use the new angle.
Troubleshooting
| Problem | What to do |
|---|---|
| Blank or grey canvas after the dataset loads | TissuePlex is still processing the morphology image. Wait 15–30 seconds and refresh the page. |
| Black screen after updating (especially on Windows) | Docker reused a stale build cache. Force a clean rebuild:docker compose build --no-cache && docker compose up |
| My dataset doesn't appear in the dropdown | Check that DATA_PATH points to the parent folder and that
the dataset folder contains the platform sentinel file (e.g.
experiment.xenium). |
| Tissue Graph and Directed Edges don't appear in the panel | edges.parquet is missing or in the wrong place. It must be
directly inside the dataset folder, alongside
experiment.xenium. |
| My metadata columns don't appear in the Color-by dropdown | Check that the CSV is in a folder named exactly
cell-metadata inside the dataset folder, with barcodes as
the first column. R's default write.csv() writes barcodes
there automatically. |
| Transcripts are not showing | Transcripts only appear when zoomed in close enough to see individual cells. Try zooming in more. Also confirm the Transcripts toggle is on in the Layer Panel. |
| TissuePlex is running slowly or edges lag | Reduce the sample slider to 5% or lower. Also check that Docker Desktop has at least 8 GB of memory allocated (Settings → Resources). |
| A red ⚠ … failed badge appears at the bottom of the canvas, or the viewer just stops updating | A data request to the backend failed; the layer it was for is left
empty rather than crashing the viewer. The badge disappears after a few
seconds. Every such failure, every slow request and every backend crash is
written to a log file that survives restarts:docker compose exec backend tail -n 300 /cache/logs/tissueplex.logIf the badge keeps reappearing, restart with docker compose
restart backend and send the log to whoever maintains your
deployment. Opening a very large edge file for the first time is slow for
a minute or two while an index is built in the background; that is
normal and happens once. |
| My dataset has no DAPI / morphology image, or the badge says the image could not be opened | Both are handled. Without an image the cells, transcripts and edges are drawn on a plain dark frame sized from the data, and there is no Morphology row. If an image exists but cannot be read, the viewer reports it (badge and log file) and draws the data on the same frame, so nothing else is lost. The log line names the file; re-exporting it as a standard OME-TIFF, or removing it, resolves the badge. |
| Error: port 3000 is already in use | Another application is using that port. Stop the other application, or
edit docker-compose.yml and change the host port (e.g.
3001:80), then restart. |
| Something else is wrong | Ask a lab member, or open an issue at github.com/RaredonLab/TissuePlex/issues. |