Expression & DEGs
Where the expression values of your cells come from, how the viewer shows raw counts and log values, and how the DEG panel ranks genes.
Where the expression comes from
MERFISHEYES never normalizes, scales or log-transforms your expression. Each cell's values are read from your data as they are, and stay that way when a dataset is processed on our servers or saved. What you see depends on what you brought:
| You bring | Values read from | Usually |
|---|---|---|
| H5AD | X — not .raw, layers or obsm | Whatever X holds: often log-normalized, sometimes raw counts |
| Xenium | cell_feature_matrix (.h5 or the folder), or cell_by_gene.csv | Raw counts |
| MERSCOPE | cell_by_gene.csv | Raw counts |
| SpatialData store, or an AnnData table in Zarr | The table's X, or a CSC copy of it in layers/ (e.g. X_csc) when X is CSR | Whatever X holds |
| A processed folder (Python scripts or server processing) | The chunks written from one of the above | Unchanged from the source |
X and you want to see counts, put them in X before uploading. The cell type CSV you bring yourself (e.g. from MapMyCells) adds columns; it doesn't change expression.Raw counts or log values?
When you select a gene, the viewer looks at its values to tell which kind they are: raw counts are whole numbers, normalized or log values are mostly fractions. If more than 5% of the nonzero values it samples (up to 5,000) are fractions, the data is treated as log-normalized; otherwise as counts. The scale bar shows what it decided (data: counts or data: log-norm).
- 1Your valuesExactly as stored, for the selected gene
- 2Counts or log?Whole numbers → counts; mostly fractions → log-normalized
- 3Raw / Log toggleStarts on the kind your data is; switch it under the scale bar
- 4ColoursScaled from 0 to the 95th percentile; drag the numbers to change it
| Your data is | Shown as Raw | Shown as Log |
|---|---|---|
| Raw counts | As stored | log1p(x) = ln(1 + x) — exact |
| Log-normalized | expm1(x) = eˣ − 1 — back toward counts, but not the true integers (normalization can't be undone) | As stored |
The toggle changes only how values are shown — the colours, the scale bar and the plots — never the data. The log is the natural log, matching what scanpy.pp.log1p writes.
How DEGs are calculated
The DEG panel compares one group of cells (a cell type, a cluster, or any value of a column shown with one colour per value) against either all other cells or one other group you pick.
- 1Per-group summaryFor every gene and every group: the mean expression, and the fraction of cells where it is above 0
- 2Choose the comparisonGroup 1 against the rest (their means combined, weighted by cell count) or against group 2
- 3Back to linear unitsIf the data is log-normalized, both means go through expm1 first
- 4Fold changemean 1 ÷ mean 2, genes ranked from highest
| In the panel | What it is |
|---|---|
| mean1 / mean2 | Mean expression of group 1 and of group 2 (or the rest), in linear units |
| FC | mean1 ÷ mean2 — 5.8× means almost six times higher in group 1. The list is sorted by it |
| Hover a row | The share of each group's cells where the gene is above 0 |
| Above the list | How many cells are in each group, e.g. 24,317 in target · 123,085 in rest |
Counts or log, for DEGs. The panel decides from the per-group means: if the largest is above 30 it treats the data as raw counts, otherwise as log-normalized (log1p of size-normalized counts rarely goes above about 15). Its Expression menu shows the guess and lets you override it. The setting only affects the means and fold changes shown.
Means of log data. For log-normalized data the mean is taken on the log values and then turned back with expm1, so mean1 and mean2 are closer to a typical cell's count than to the arithmetic average of counts. Fold changes between groups compare like with like.
Where the summaries come from. For data opened in your browser they are computed there when you choose a column. For datasets processed on our servers (or with the Python scripts) they were computed once, from the same values, for every column with categories; SpatialData stores read them from an annotations/ folder beside the store. (The Leiden clusters that scripts/spatialdata_cluster.py adds to a store are the one exception to "as stored": their summaries are taken from a log-normalized copy of the table.) Copy CSV downloads the table, with a note of which mode was used.
scanpy.tl.rank_genes_groups) before reporting them.