Methods & help
How every number in this tool is computed, what files it reads, and where its limits are.
Workflow
- Instrument — pick your cytometer in the header. Signatures, similarity and spread are always computed for that detector layout.
- Panel — list markers with expected expression, priority and the cell populations where they are positive. Assign fluors (type to search; aliases such as “AF647” or “PE/Dazzle 594” work).
- Optimize — let the tool suggest a low-complexity fluor set from the library or your stock, and place markers on fluors.
- Library — import your own single-stain controls (FCS) or exported signatures (CSV). Measured signatures replace simulated ones and can calibrate the simulation for every other dye.
- Save the panel as a
.panelyzer.jsonfile (includes references, custom dyes and settings). Export CSVs or print a PDF report.
Simulated signatures
For a fluor with excitation spectrum ex(λ) and emission spectrum em(λ), the signal on detector d (laser L, band [lo, hi]) is
s_d = P_L · k_L · g_d · ex(λ_L) · ∫_lo^hi em(λ) · R(λ) dλwhere P_L is laser power, k_L the laser scale (Instrument tab), g_d an optional calibrated detector gain, and R(λ) an approximate detector response. The vector is normalized so its peak channel equals 1. Spectra are resampled to a 4 nm grid (300–940 nm).
Simulation ignores beam geometry, PMT/APD voltages, filter roll-off and autofluorescence, so real signatures (especially cross-laser ratios) can differ. Importing even a handful of reference controls and running Calibrate detector gains fits per-detector corrections g_d by weighted alternating least squares in log space (log m = log a_f + log g_d + log s_fd) and applies them to every simulated dye.
Similarity and complexity
similarity(i, j) = s_i · s_j / (‖s_i‖ ‖s_j‖) complexity index = σ_max(S) / σ_min(S)S is the detectors × fluors matrix of peak-normalized signatures, and σ its singular values (the 2-norm condition number). Values grow with panel size; compare alternatives for the same instrument rather than using a fixed cut-off. Similarity limits default to 0.98 (problem) and 0.90 (caution) and can be changed under the Optimize tab's similarity limit.
Unmixing and estimated spread
W = (SᵀS)⁻¹ Sᵀ (ordinary least squares) SS(j → k) = √( Σ_d W_kd² · s_jd ) ν_k = √( Σ_d W_kd² )A cell carrying abundance a of fluor j produces detector signals a·s_j whose variance scales with the signal (photon shot noise). After unmixing, the extra variance in fluor k is a·Σ_d W_kd² s_jd, so SS is the spread standard deviation per √intensity — the same quantity a measured spillover spreading matrix reports, up to an instrument-specific constant. Values are therefore relative: use them to rank problem pairs within a panel. ν is the factor by which unmixing amplifies uniform detector background into fluor k.
Marker assignment model
signal_n = E_n · B_f(n) var_n = (b · ν_f(n))² + Σ_m c(m,n) · SS(f(m) → f(n))² · signal_m R_n = signal_n / √var_n cost = Σ_n w_n / R_nE is expression (1 = low … 4 = very high), B fluor brightness (1–5, editable in the Library), b the background-noise setting, w the priority weight (critical 2, normal 1, low 0.5) and c(m,n) = 1 when two markers share a population tag, otherwise the “non-co-expressed” weight (default 0.15). The search is simulated annealing over swaps and moves (several restarts). “Pick from candidate pool” first chooses a fluor set, then tries swapping each marker's fluor for every compatible pool fluor and re-anneals.
Population tags: write the populations where a marker is positive and must be resolved, e.g. CD3 → “CD4 T, CD8 T”, CD4 → “CD4 T”, CD8 → “CD8 T”, CD19 → “B”. Spread matters most between markers on the same cells.
Autofluorescence
Autofluorescence (AF) profiles — from an unstained cell FCS (median of scatter-gated events), a CSV, or Honeychrome's AutoSpectral AF profiles — are unmixed as extra components. They enter the unmixing matrix, so they change noise amplification ν and the spreading matrix, and they add a spread source present on every cell (“Autofluorescence level” on the Optimize tab sets its intensity, 1–4 on the expression scale). Fluors with ≥ 0.90 similarity to an AF profile are flagged. The headline complexity index is computed for the fluors alone, as instrument software reports it; the value including AF is shown beneath it.
Working with Honeychrome
Measured library. For the Aurora 5L and ID7000 presets the tool bundles Honeychrome's measured reference library (Aurora: 93 fluors, ID7000: 65). Library spectra are used ahead of simulated ones (your own references still take priority), and simulated dyes are calibrated by default: per-detector gains are fitted to the library dyes that also have FPbase spectra (Instrument tab). In leave-one-out tests this raised agreement between simulated and measured spectra from a mean cosine of 0.94 to 0.96 on the Aurora and 0.83 to 0.92 on the ID7000. The ID7000 channel boundaries were themselves fitted to this library.
Import Honeychrome… on the Library tab reads an experiment file (.kit): the cleaned reference spectra in process.profiles (channel order from settings.raw.fluorescence_channel_ids), AutoSpectral af_profiles, and the label/antigen pairs of the spectral model. Each spectrum is compared with the measured library spectrum for its fluor (or the simulated one when the library lacks it); low agreement (< 0.80) usually points to a contaminated, mis-gated or mislabeled control. The same button reads a Panel Check export (.json), which adds measured stain indices, unmixing residuals and a spread calibration.
Panel Check plugin (panel_check_tab.py) runs inside Honeychrome: it unmixes each single-stain control and measures spread as √(rSD²pos − rSD²neg)/√ΔF (rSD = 84.13th percentile − median), stain index ΔF/(2·rSDneg), and residual signal left in other channels. Matching measured to predicted spread gives a scale c (median of log ratios); after import, this tool multiplies its spreading matrix by c for that instrument.
Export → Single-stain control checklist lists the controls a panel needs, with file names Honeychrome's label detection reads (“Marker Fluor (Cells).fcs”).
Honeychrome is © Cytkit contributors, LGPL-3.0 (github.com/Cytkit/honeychrome). Its reference library data are included here unmodified in encoded form.
Best fluors to add
For each candidate, the panel is re-unmixed with the candidate added (plus any enabled autofluorescence) while existing marker→fluor assignments stay fixed. The new marker (your expression, priority and populations) is placed on the candidate and scored with the assignment model: its predicted resolution R, and the change in Σ w/R over the markers already in the panel. Overall rank = wnew/Rnew + Δ(existing cost); the complexity index after adding and the closest panel fluor are shown alongside. Candidates above the similarity limit are hidden by default.
Fluor-set suggestion
Greedy forward selection (each step adds the candidate giving the lowest objective, never exceeding the similarity limit), followed by swap refinement until no single swap improves the objective. Objectives: complexity index, or trace((SᵀS)⁻¹) — the total noise amplification across all unmixed channels. “Prefer bright fluors” multiplies the objective by 1 + weight · mean(1/B). Thorough mode adds randomized restarts.
File formats
Reference signatures (CSV/TSV). Either orientation works. Detector names are matched case-insensitively with “-A/-H” suffixes ignored (Aurora: UV1…R8; ID7000: 405-1, 405nm CH1, …). Values are normalized to their peak.
Fluor,UV1,UV2,…,R8 BV421,0.012,0.020,…,0.001 (fluors in rows) Detector,BV421,PE,… UV1,0.012,0.000,… (detectors in rows)
Single-stain FCS (2.0/3.0/3.1, list mode). A broad FSC/SSC gate removes debris and doublet-rich extremes; the peak channel is the one with the largest 99.5th-percentile − median; positives are the top 2% (adjustable) of events in that channel excluding saturation; negatives come from an unstained file if you pick one, otherwise the dimmest 30% of the same file. Signature = median(positive) − median(negative) per channel.
Custom dye spectrum (CSV). Three columns: wavelength (nm), excitation, emission (any scale).
Instrument (JSON). Export any instrument to see the schema; lasers have wl, power, scale and detectors with name plus center/bw or lo/hi. Use this for Aurora 3L/4L, Northern Lights, FACSDiscover or any other layout.
Instrument presets
Cytek Aurora 5L: 64 detectors with the published 5-laser filter layout (UV 355 nm/20 mW, V 405/100, B 488/50, YG 561/50, R 640/80). Sony ID7000: per-laser channel counts follow published specifications (355: 35 ch, 405: 35, 488: 32, 561: 26, 637: 19; optional 320: 35 and 808: 2), with all lasers sharing one 35-position grid (488 nm starts at channel 4, 561 nm at channel 10, 637 nm at channel 17). Sony does not publish channel boundaries, so they were fitted to Honeychrome's measured ID7000 library (cross-validated agreement 0.93 on held-out dyes); treat ID7000 simulations as less certain than Aurora ones. If your configuration differs, duplicate the preset and edit it.
Spectra and their sources
Excitation/absorption and emission spectra for 271 dyes and fluorescent proteins were retrieved from FPbase (fpbase.org, CC BY-SA 4.0; see FPbase for the original vendor and literature sources). Dyes FPbase does not list are marked approx.: their spectra are built from a related FPbase dye (excitation of the donor/backbone, emission shape of a similar acceptor shifted to the published emission maximum, plus donor residual for PE/APC tandems). Treat approximated dyes as planning estimates and replace them with reference controls before relying on them. Brightness ratings are generic 1–5 estimates — edit them to match your reagents.
Privacy
Everything runs inside this single HTML file in your browser. It contains a Content-Security-Policy that blocks all network connections, so no panel, FCS file or reference ever leaves your computer. Work is not stored by the browser: use Save (the tool warns before closing with unsaved changes).
How Panelyzer was made
Panelyzer was developed by Cole Batty with substantial help from Claude (Anthropic), a generative AI model, which wrote most of the code, tests and documentation under his direction. The calculations are checked against NumPy and against measured spectra by scripts anyone can rerun; see the project's README and docs/VALIDATION.md.
Keyboard
Ctrl/⌘ S save · Ctrl/⌘ Shift S save as · Ctrl/⌘ O open · Ctrl/⌘ Z undo · Ctrl/⌘ Shift Z redo (outside text fields).
Panelyzer 0.9.0 · built 2026-10-21 · © Cole Batty and contributors · code LGPL-3.0-or-later; FPbase spectra CC BY-SA 4.0; Honeychrome library LGPL-3.0 · source and issues: https://github.com/colejbatty/panelyzer