FCS (Flow Cytometry Standard)
FCS is the open file format that flow cytometers and their software write. OpenReadout returns each data set as a table of events with one column per parameter, plus the keywords and instrument metadata; compensation, transforms and gates are applied on request.
Derived from the public ISAC specification “Data File Standard for Flow Cytometry, Version FCS 3.1 — Normative Reference” (2009, CC BY-SA 3.0) and checked against public corpus files (FCS 2.0, 3.0, 3.1 from many instrument families). FlowIO (BSD-3-Clause) and fcsparser (MIT) were read as prior art and are used as reference readers. See docs/provenance/fcs.md.
FCS is an open standard, so unlike the microscopy formats most of this page restates a specification; the corpus notes record where real files depart from it. Section numbers (§) refer to the FCS 3.1 normative reference.
A file is one or more data sets. Each data set has a HEADER, a primary TEXT segment of keyword-value pairs, a DATA segment of events, and optionally a supplemental TEXT, an ANALYSIS segment and implementor-defined OTHER segments. $NEXTDATA links data sets. OpenReadout exposes each data set as one table: one row per event, one column per parameter.
FCS 3.2
FCS3.2 data sets (Spidlen et al. 2021) are read like 3.1 with these differences: $PnDATATYPE gives a measurement its own data type (I, F or D) when it differs from $DATATYPE, and widths, decoding, dtype and bit masks follow it per column; $MODE may be absent (list mode); $BEGINSTEXT/$ENDSTEXT/$BEGINANALYSIS/$ENDANALYSIS may be absent; $BEGINDATETIME/$ENDDATETIME (ISO 8601, with a zone) become acquisition_start/acquisition_end in place of $DATE/$BTIM/$ETIM; $CARRIERID, $CARRIERTYPE, $LOCATIONID, $FLOWRATE, $UNSTAINEDCENTERS, $UNSTAINEDINFO are copied to carrier_id, carrier_type, location_id, flow_rate, unstained_centers, unstained_info. Corpus: zenodo19221995-facsdiscover-zam36 (BD FACSDiscover S8, 440 measurements, delimiter CR).
HEADER (§3.1)
All offsets are ASCII decimal, right-justified in 8 bytes, relative to the first byte of the data set, and inclusive (the end offset is the last byte of the segment).
| bytes | our name | content |
|---|---|---|
| 0–5 | version |
FCS2.0, FCS3.0, FCS3.1 or FCS3.2 |
| 6–9 | – | spaces |
| 10–17 / 18–25 | text |
primary TEXT begin / end |
| 26–33 / 34–41 | data |
DATA begin / end |
| 42–49 / 50–57 | analysis |
ANALYSIS begin / end (zeros or blanks when absent) |
| 58… | other |
optional OTHER segment begin/end pairs, 16 bytes each, until the first segment starts |
When a segment lies (partly) beyond byte 99,999,999 its HEADER offsets are 0 and the real offsets are only in TEXT ($BEGINDATA/$ENDDATA, $BEGINANALYSIS/$ENDANALYSIS, $BEGINSTEXT/$ENDSTEXT). Blank fields (all spaces) are read as 0 and reported as blank_header_offset (seen in fcsparser-fake-large, flowio-coulter-lmd). HEADER_LEN = 58; header_len is 58 plus 16 per OTHER pair actually present (74 in fcsparser-cyflow-cube-8).
TEXT (§3.2)
- The first byte of the primary TEXT is the delimiter (ASCII 1–126). Seen in the corpus:
/,\,|, form feed0x0C(BD FACSDiva, Cytek SpectroFlo), record separator0x1E(Beckman Coulter Navios). - Pairs are
keyword DELIM value DELIM. A delimiter inside a keyword or value is doubled. Keywords and values may not be empty, so a doubled delimiter is always an escape — except as the last two bytes of a segment, where it can only be a terminator plus an empty final value (flowio-data1ends…Analysis Doc.\\). - Keywords are case-insensitive (
getignores case); FCS-defined keywords start with$. Values are UTF-8 in 3.1; values that are not valid UTF-8 (older Mac writers, e.g.CellQuest Pro\xAA) are read byte-for-byte as Latin-1 and reported asnon_utf8_value. - Numeric values must not be padded (§3.2.17) but often are (
$TOT/83411 /in FACSDiva exports,$BEGINDATA/ 3446/in Guava) or carry leading zeros ($BEGINDATA/0000000000004161/). We trim;checkreports padding aspadded_numeric_value(info). - Trailing spaces or NULs after the final delimiter are ignored (Miltenyi supplemental TEXT ends with one space).
Supplemental TEXT and ANALYSIS
$BEGINSTEXT/$ENDSTEXT locate the supplemental TEXT; it uses the primary delimiter and may or may not start with it (Miltenyi: starts with /; flowio-m0-wm278-s1-zero-gain: starts directly with SORTSTATS|, and sits after DATA). Seen oddities: the range equals the primary TEXT (flowio-b01-kc-a-w-91-us, not re-parsed), and a ZIP archive instead of keywords (fcsparser-cyflow-cube-8, signature PK\x03\x04; the same file’s TEXT says P$CFGTYPE/ZIP/). ANALYSIS (§3.4) has the TEXT syntax; its location comes from $BEGINANALYSIS/$ENDANALYSIS, else the HEADER. Keyword lookups for normalized fields search the primary TEXT, then the supplemental TEXT.
Required keywords (§3.2.18) and how we use them
| keyword | our field | use |
|---|---|---|
$BYTEORD |
byte_order |
1,2,3,4 → LittleEndian, 4,3,2,1 → BigEndian; two-byte 1,2 / 2,1 appear in Beckman Coulter FCS 2.0 files; any other permutation → Mixed (reported, not decoded) |
$DATATYPE |
data_type |
I Integer, F Float, D Double, A Ascii |
$MODE |
mode |
L List (decoded); C Correlated, U Uncorrelated histograms (deprecated; described, reads exit 6) |
$PAR |
parameters |
number of $Pn* sets read |
$TOT |
event_count |
rows |
$PnB |
width |
Fixed(n): bits for I/F/D, characters for A; FreeFormat for * |
$PnN |
short_name |
column name |
$PnR |
range, range_text |
column range; the I bit mask |
$PnE |
amplification |
[decades, offset] in column extra.amplification |
$BEGINDATA, $ENDDATA |
data_range |
DATA location (see below) |
$BEGINSTEXT, $ENDSTEXT |
supplemental |
supplemental TEXT location |
$BEGINANALYSIS, $ENDANALYSIS |
analysis |
ANALYSIS location |
$NEXTDATA |
next_data |
offset of the next data set relative to the start of this one; 0 = last |
Optional parameter keywords copied into column extra: $PnS → label; $PnG → gain; $PnV → detector_voltage (volts); $PnL → excitation_wavelength_nm (list; 3.1 allows several); $PnO → excitation_power_mw; $PnF → filter; $PnT → detector_type; $PnP → percent_emitted; $PnD → display_scale (verbatim); $PnCALIBRATION → calibration (verbatim). Column extra.bits is $PnB, extra.range_keyword is $PnR as written, and extra.bit_mask appears for I data when the mask is narrower than the field.
Data-set keywords copied into table extra: $CYT/$CYTSN → instrument.model/serial_number; $SYS → system; $DATE → acquisition_date; $DATE+$BTIM/$ETIM → acquisition_start/acquisition_end; $FIL → file_name (also the table name); $SRC → source; $EXP → experimenter; $OP → operator; $INST → institution; $SMNO → specimen; $CELLS → cells; $PROJ → project; $COM → comment; $PLATEID/$PLATENAME/$WELLID → plate_id/plate_name/well_id; $ORIGINALITY; $LAST_MODIFIER; $LAST_MODIFIED → last_modified; $VOL → volume_nl; $TIMESTEP → timestep_s; $TR → trigger {parameter, threshold}; $LOST → events_lost; $ABRT → events_aborted. Also fcs_version, data_set_offset, datatype, byte_order, mode, event_width_bytes, supplemental_text, analysis_segment, spillover, software, vendor_keywords.
Dates and times
$DATE:dd-mmm-yyyy(spec). Also seen:dd-Mmm-yy(22-Sep-13, FCS 2.0 CellQuest; two-digit years < 70 → 20yy, else 19yy — inferred),yyyy-Mmm-dd(Miltenyi MACSQuantify), mixed-case months, trailing spaces.$BTIM/$ETIM:hh:mm:ss.cc(3.1, hundredths),hh:mm:ss:tt(2.0/3.0, sixtieths per 3.1 Appendix B, converted to hundredths:17:29:39:51→17:29:39.85),hh:mm:ss. A fourth field with three digits (09:42:05:509, CyFlow) is not a sixtieth; it is dropped rather than guessed.- Output is ISO-8601 without a time zone (FCS records none);
infoadds a note saying so (book/src/guides/metadata.md).acquisition_endrolls to the next day when$ETIM<$BTIM.
Spillover (spillover)
$SPILLOVER (3.1, §3.2.20): n,name1,…,namen,s11,s12,…,snn, row-major, sij = spillover from parameter i into j; names are $PnN. $SPILL (FlowKit’s compensation example) and SPILL (BD FACSDiva and others; not FCS keywords) have the same layout; they are used only when every name in them is a $PnN of the same data set (true for the DiVa files; false for the Stratedigm files, whose SPILL names were redacted). $COMP (FCS 3.0) is exposed as a matrix with parameters empty when the value lists no names; no claim is made about whether it is a spillover or a compensation matrix, and it is never applied. info reports the matrix; table --compensate and analyze gate apply it (docs/formats/flowjo-wsp.md).
Scale values, compensation, transforms, gates
read_table and export return raw DATA values. openreadout table FILE --compensate [--transform …] [--workspace W.wsp|--gatingml G.xml --population PATH] and openreadout analyze gate first convert them to scale values (FCS 3.1 §3.2.19–20): $PnE f1,f2 with f1 > 0 gives 10^(f1·x/$PnR)·f2 (f2 = 0 read as 1); a $PnG other than 0 or 1 divides; the Time parameter is multiplied by $TIMESTEP and never divided by a gain (as FlowIO does). Then compensation, transforms and gates as described in docs/formats/flowjo-wsp.md; table records every step in processing.
Instrument families (platform) and parameter roles
tables[].extra.platform names the family that wrote the data set, recognised from keywords the file carries (provenance: Source::Inferred), and adds what that family’s keywords mean:
family |
recognised by | corpus files | extra fields |
|---|---|---|---|
bd-spectral |
CREATOR starts BD FACSChorus, or BDSPECTRAL UNMIXED present |
zenodo19221995-facsdiscover-zam36 |
unmixing {stored, parameters (from BDSPECTRAL UNMIXED), method (BDSPECTRAL UNMIXING METHOD), applied (BDSPECTRAL APPLY)}, detector_count (the SPILL detectors), imaging_features ($PnFEATURE values other than Area/Height/Width), cytometer_configuration, lasers; columns: unmixed_fluorescence, imaging_feature, spectral_detector |
bd-facsdiva |
CREATOR starts BD FACSDiva |
fcsparser-facs-diva, -fortessa-a01, -hts-lsr-ii-d06, flowio-100715 |
lasers (LASERnNAME, LASERnDELAY → delay, LASERnASF → area_scaling_factor), experiment (EXPERIMENT NAME), tube (TUBE NAME), cytometer_configuration, cst_setup_status, compensation_applied_in_acquisition (APPLY COMPENSATION) |
cytek-spectral |
CREATOR starts SpectroFlo, or $CYT Aurora / Northern Lights / NL-… |
zenodo17457137-aurora-beads, fcsparser-cytek-nl-2000-header |
lasers, detector_count, detectors_by_laser (full-spectrum detectors <laser><n>-A with laser prefixes UV, V, B, YG, R named by the file’s LASERnNAME), unmixing (stored: false when $PnTYPE says Raw_Fluorescence or $SPILLOVER is the identity; true when no detector-named parameters are present), user_setting, group, tube |
beckman-cytoflex |
CYTEXPERTFIL present, or $CYT starts CytoFLEX |
zenodo18439538-cytoflex |
software CytExpert, tube (TBNM), group (CGNM), plate_number (PLTNO), compensation_channels (COMPCHH) |
sony-spectral |
$CYT SA3800, ID7000, SP6800 |
zenodo7971252-sony-sa3800 |
log_display_parameters ($PnD/Logarithmic,…/) |
sony-sorter |
$CYT SH800, MA900 |
– | – |
mass-cytometry |
$CYT containing the word CYTOF, DVSSCIENCES, FLUIDIGM or HELIOS, or three or more metal-tag channels |
zenodo10510047-cytof-mouse |
mass_channel_count, isotopes (142Nd), markers_by_isotope (from $PnS 142Nd_CD19 → CD19), note |
Every platform also has vendor, technology (conventional, spectral, mass), model ($CYT) and software (CREATOR). Per column, extra.channel_kind is time, scatter (FSC…, SSC…), fluorescence, spectral_detector (Cytek detectors, with laser), mass (<Element><mass>Di/Dd, element checked against the periodic table, mass 75–209; with metal_tag {element, mass, isotope} and marker), background (BCKG…), event_length (Event_length), gaussian_parameter (Center, Offset, Width, Residual) or other; extra.measure is area/height/width from the -A/-H/-W suffix; extra.parameter_type is $PnTYPE (FCS 3.2; Raw_Fluorescence, Time, … in the Aurora file), and the other FCS 3.2 measurement keywords are copied as detector ($PnDET), feature ($PnFEATURE), dye ($PnTAG), analyte ($PnANALYTE) and datatype ($PnDATATYPE, when given). info --view explain describes spectral and mass-cytometry files in these terms and the experiment model carries cytometry_technology, spectral_detectors and mass_channels method parameters and the vendor as instrument manufacturer.
DATA (§3.3)
Locating DATA
- Candidates: the TEXT pair (
$BEGINDATA,$ENDDATA, unless both 0) and the HEADER pair (unless both 0). FCS 3.x tries TEXT first; FCS 2.0 tries the HEADER first. - The first candidate whose length (
end − begin + 1) equals$TOT × event width, or is one byte longer, wins; otherwise the first candidate. - Differing pairs →
offset_discrepancy(warning). Inflowio-data-start-offset-discrepancythe HEADER says 5555–6188 (634 bytes) and TEXT 6081–6188 (108 bytes = 2 events × 54 bytes): TEXT wins. In-stop-the HEADER end lies past the end of the file. - Length one byte longer than needed →
data_end_off_by_one(warning; Miltenyi, Coulter). Shorter →data_length_mismatch(error). Past end of file →truncated(error, exit 4).
Decoding (list mode)
Events are stored one after another; within an event, parameters in order 1…$PAR, each $PnB wide.
- I — unsigned integers of
$PnB / 8bytes (any whole number of bytes up to 8; 8, 16, 24, 32 seen), in$BYTEORDorder, then masked:mask = next_power_of_two(ceil($PnR)) − 1when that is narrower than the field, else all ones (§3.3;$PnR/1024/→ 1023;$PnR/11209599/on 32 bits → 2²⁴−1;$PnR/4294967296/on 32 bits → no mask).$PnBnot a multiple of 8 (bit-packed) → unsupported (exit 6). - F — IEEE-754 binary32 (
$PnBmust be 32); D — binary64 ($PnB64). No mask; values may be negative or exceed$PnR. - A — fixed width:
$PnBcharacters per value, parsed as a decimal number (blank field → 0). Free format ($PnB/*/): values separated by space, tab, comma, CR or LF, runs of separators counting as one. Deprecated in 3.1; no corpus file uses it (unit tests only).
read_table returns values as f64 (lossless for every width ≤ 32 bits and for F/D), raw: not compensated and not scaled by $PnE, $PnG or $TIMESTEP. Storage dtype per column: I → uint8/uint16/uint32/uint64 (smallest that holds $PnB bits; 24-bit → uint32), F → float32, D and A → float64.
Oracle hash (corpus tests)
xxh3 in corpus/oracle/<id>.json → tables[] = xxh3-128 over every value of the data set as little-endian f64, column-major (all events of parameter 1, then parameter 2, …). oracle/gen.py computes it from FlowIO (as_array(preprocess=False)) or, for data sets FlowIO cannot decode (24-bit integers, blank HEADER offsets), from fcsparser; the corpus test computes it from read_table. FlowIO 1.4 ignores FCS 3.2’s $PnDATATYPE, so for FCS 3.2 files with mixed types the oracle re-reads the DATA segment with a NumPy record type built from each measurement’s type (fcsparser, which also ignores it, is kept as a disagreeing second opinion).
CRC (§3.5)
Eight ASCII bytes right after the last segment of a data set. CRC-16 with the CCITT polynomial, each input byte bit-reversed and initial value 0 (processed LSB-first: reflected polynomial 0x8408; check value of 123456789 is 0x2189). 00000000 means “not computed” (DiVa, Miltenyi 3.0, Navios). No corpus file stores a computed CRC, so a mismatch is a warning, not corruption; byte-swapped equality is accepted.
Multiple data sets
$NEXTDATA is relative to the current data set’s first byte (FCS 2.0 wording, followed by FlowIO; fcsparser treats it as absolute, which only works for the second data set). Guava Muse writes four data sets; Beckman Coulter .lmd files hold an FCS 2.0 data set followed by an FCS 3.0 copy with 32-bit values whose TEXT comes after its DATA. The walk stops at 0, at an offset past the end of the file (truncated), or at an offset already visited (bad_next_data).
check finding codes
truncated, data_length_mismatch, missing_data_offsets, missing_keyword, bad_keyword, unsupported_width, bad_offset, bad_next_data, bad_data_set (errors); offset_discrepancy, data_end_off_by_one, duplicate_keyword, duplicate_parameter_name, text_unterminated, dangling_keyword, empty_value, nonprintable_keyword, bad_delimiter, mixed_byte_order, histogram_mode, crc_mismatch, non_keyword_segment, no_events (warnings); padded_numeric_value, blank_header_offset, non_utf8_value, log_zero_offset, crc_ok, crc_not_computed (info).
Instrument-specific keywords (vendor_keywords)
Every keyword not starting with $ (primary and supplemental TEXT) is copied verbatim into table extra.vendor_keywords, grouped by a mechanical prefix (keyword_prefix): a namespace before an inner $ (FJ$ACQSTATE → FJ, GTI$SAMPLEID → GTI, P$CFGTYPE → P), a leading symbol (@SAMPLEID1 → @, &10PATIENT ID → &, #… → #), per-parameter keywords Pn… → Pn, letters followed by a number (LASER1NAME → LASERn), else the first word (CST SETUP STATUS → CST, ANALOG_COMP → ANALOG). Values over 1024 bytes are shortened in info; info --view full has them in full. No meaning is assigned except where stated above (CREATOR → software, SPILL → spillover).
| writer (from the file) | corpus files | keywords seen |
|---|---|---|
BD FACSDiva 6.2 (CREATOR) |
fcsparser-facs-diva, -fortessa-a01, -fake-large, -hts-lsr-ii-d06, flowio-100715 |
CREATOR, TUBE NAME, EXPERIMENT NAME, GUID, SPILL, APPLY COMPENSATION, THRESHOLD, WINDOW EXTENSION, FSC ASF, AUTOBS, EXPORT USER NAME, EXPORT TIME, CST SETUP STATUS, CST BEADS LOT ID, CST SETUP DATE, CST BASELINE DATE, CYTOMETER CONFIG NAME, CYTOMETER CONFIG CREATE DATE, CYTNUM, LASERnNAME, LASERnDELAY, LASERnASF, PLATE NAME, PLATE ID, WELL ID, SAMPLE ID, PnDISPLAY, PnBS, PnMS |
Cytek SpectroFlo 2.2.0 (CREATOR, $CYT/Aurora/) |
fcsparser-cytek-nl-2000-header |
CREATOR, LASERnNAME, LASERnDELAY, LASERnASF, FSC ASF, WINDOW EXTENSION, THRESHOLD, APPLY COMPENSATION, USERSETTINGNAME, TUBENAME, GROUPNAME, CHARSET, PnDISPLAY |
| FlowJo Collectors’ Edition 7.5 on a Cytek xP5 | fcsparser-cytek-xp5 |
CREATOR, ANALOG_COMP, FJ$ACQSTATE, FJ_$P1R, LASERnNAME, SAMPLEID |
Observed corpus values
| file | version | delimiter | $DATATYPE / $PnB |
$BYTEORD |
data sets | notes |
|---|---|---|---|---|---|---|
fcsparser-facs-diva |
3.0 | 0x0C | F / 32 | 4,3,2,1 | 1 | 83411 events, SPILL 8×8 |
fcsparser-cytek-xp5 |
3.0 | \ |
I / 24 | 4,3,2,1 | 1 | 8 × 3 bytes × 23126 = DATA length |
fcsparser-cyflow-cube-8 |
3.0 | / |
I / 8,16,32 | 1,2,3,4 | 1 | OTHER segment = STEXT = ZIP |
fcsparser-guava-muse |
3.0 | / |
F / 32 | 1,2,3,4 | 4 | relative $NEXTDATA |
flowio-coulter-lmd |
2.0 + 3.0 | \ |
I / 16, then I / 32 | 1,2 then 1,2,3,4 | 2 | second TEXT after its DATA |
flowio-m0-wm278-s1-zero-gain |
3.1 | | |
I / 32 | 1,2,3,4 | 1 | $PnR/4294967296/, STEXT after DATA |
fcsparser-miltenyi-fcs31 |
3.1 | / |
F / 32 | 1,2,3,4 | 1 | STEXT 2722–127220, DATA end off by one |
zenodo17457137-aurora-beads |
3.1 | 0x0C | F / 32 | 1,2,3,4 | 1 | 71 parameters: 64 full-spectrum detectors, $PnTYPE, 64×64 identity $SPILLOVER |
zenodo18439538-cytoflex |
3.0 | 0x0C | F / 32 | 4,3,2,1 | 1 | zero-padded $BEGINDATA, 8×8 $SPILLOVER over H and A detectors |
zenodo7971252-sony-sa3800 |
3.1 | \ |
F / 32 | 1,2,3,4 | 1 | $BEGINSTEXT at 64 (inside the primary TEXT), $PnD/Logarithmic,6,1/ |
zenodo10510047-cytof-mouse |
3.0 | | |
F / 32 | 1,2,3,4 | 1 | 51 metal channels; keyword $CYTSN_$DATE (an empty $CYTSN value merged with $DATE) |
flowkit-gml-events |
2.0 | \ |
I / 16 | 4,3,2,1 | 1 | $P1G/3.67/, $P2G/8/ and $PnE/4,0/ on four channels: scale values differ from raw |
Vocabulary (every public identifier in openreadout-fcs must appear here)
| identifier | meaning |
|---|---|
FcsReader, FcsDataset, FcsFile, FORMAT_ID |
reader entry points: format reader, opened file (core Dataset), parsed data-set chain, the id fcs |
open, path, file_len, data_sets, chain_findings, read_at |
opening a file; its path and size; the data sets found; findings about the $NEXTDATA chain; bounded read helper |
DataSet, index, offset, header, delimiter, text_range, text, supplemental, analysis, data_type, byte_order, mode, event_count, parameters, data_range, data_source, next_data, findings |
one data set and its parts (absolute offsets) |
keyword, event_width, expected_data_len, is_free_format, last_segment_end |
data-set helpers: keyword lookup (primary then supplemental), bytes per event, $TOT × width, $PnB/*/ present, where the CRC field starts |
AuxSegment, range, keywords, note |
supplemental TEXT / ANALYSIS: location, parsed keywords, why not parsed |
OffsetSource { Text, Header }, name |
which pair located DATA |
Header, HeaderError { TooShort, NoSignature, BadOffset }, HEADER_LEN, VERSIONS, version, data, other, header_len, blank_fields, parse_header, looks_like_fcs |
HEADER parsing and signature test |
SegmentRange, begin, end, new, is_unset, byte_len, absolute |
inclusive byte range and helpers |
Keyword, KeywordSet, name, value, entries, duplicates, push, get, contains, len, is_empty |
keyword-value pairs, ordered, case-insensitive lookup |
TextParse, empty_values, dangling_keyword, nonprintable_keywords, latin1_values, unterminated, parse_keywords |
result of parsing a keyword segment and its irregularities |
parse_uint, parse_float, is_padded |
numeric keyword values (trimmed) and the padding test |
DataType { Integer, Float, Double, Ascii }, from_code, code |
$DATATYPE |
ByteOrder { LittleEndian, BigEndian, Mixed }, from_value |
$BYTEORD |
Mode { List, Correlated, Uncorrelated } |
$MODE |
FieldWidth { Fixed, FreeFormat }, width |
$PnB |
Parameter, number, short_name, label, range_text, amplification, gain, voltage, wavelengths_nm, filter, detector_type, power_mw, percent_emitted, display, calibration, data_type, detector, measurement_type, feature, tag, analyte, byte_width, bit_mask, read_parameters |
one parameter’s $Pn* keywords and derived widths/masks |
storage_dtype, decode_fixed, decode_free_ascii |
column dtype rule and DATA decoding |
SpilloverMatrix, values, parse_spillover, spillover |
spillover/compensation matrix and which keyword supplied it |
keyword_prefix |
mechanical grouping of non-$ keywords for vendor_keywords |
scale_columns, file_matrix, parameter_names, is_time_parameter, is_fluorescence_parameter |
raw → scale values; the file’s own compensation matrix; $PnN/$PnS lists; parameter roles used by --transform defaults |
Family { BdFacsDiva, BdSpectral, CytekSpectral, BeckmanCytoflex, SonySpectral, SonySorter, MassCytometry }, family, vendor, technology, id, platform |
instrument family recognition and extra.platform |
channel_kind, column_extras, metal_tag, metal_marker |
per-column roles, metal tags and markers |
FcsDate, year, month, day, iso, next_day, parse_date, parse_time, parse_timestamp, acquisition_span |
$DATE/$BTIM/$ETIM/$LAST_MODIFIED to ISO-8601 |
Crc16, update, finish, CrcField { Absent, NotComputed, Value, Other }, read_crc_field |
data-set CRC |
RowCondition, column, op, threshold, CompareOp { Greater, GreaterEqual, Less, LessEqual, Equal, NotEqual }, symbol, test, parse_conditions, filtered_slice |
table --filter 'FITC-A > 1000' --count: row conditions (COLUMN OP NUMBER, all must hold; NaN meets none) tested over the whole table on the values table returns, raw or compensated/transformed (module filter) |
How this reader was derived, file by file: provenance log.