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 bringValues read fromUsually
H5ADX — not .raw, layers or obsmWhatever X holds: often log-normalized, sometimes raw counts
Xeniumcell_feature_matrix (.h5 or the folder), or cell_by_gene.csvRaw counts
MERSCOPEcell_by_gene.csvRaw counts
SpatialData store, or an AnnData table in ZarrThe table's X, or a CSC copy of it in layers/ (e.g. X_csc) when X is CSRWhatever X holds
A processed folder (Python scripts or server processing)The chunks written from one of the aboveUnchanged from the source
If your H5AD keeps raw counts somewhere other than 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).

  1. 1Your valuesExactly as stored, for the selected gene
  2. 2Counts or log?Whole numbers → counts; mostly fractions → log-normalized
  3. 3Raw / Log toggleStarts on the kind your data is; switch it under the scale bar
  4. 4ColoursScaled from 0 to the 95th percentile; drag the numbers to change it
Your data isShown as RawShown as Log
Raw countsAs storedlog1p(x) = ln(1 + x) — exact
Log-normalizedexpm1(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.

  1. 1Per-group summaryFor every gene and every group: the mean expression, and the fraction of cells where it is above 0
  2. 2Choose the comparisonGroup 1 against the rest (their means combined, weighted by cell count) or against group 2
  3. 3Back to linear unitsIf the data is log-normalized, both means go through expm1 first
  4. 4Fold changemean 1 ÷ mean 2, genes ranked from highest
In the panelWhat it is
mean1 / mean2Mean expression of group 1 and of group 2 (or the rest), in linear units
FCmean1 ÷ mean2 — 5.8× means almost six times higher in group 1. The list is sorted by it
Hover a rowThe share of each group's cells where the gene is above 0
Above the listHow 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.

This is a fold-change ranking, not a statistical test: there are no p-values or corrections for multiple testing. Use it to find candidate markers quickly, and confirm them with a proper test (for example scanpy.tl.rank_genes_groups) before reporting them.