Skill Tracer
Skills › Scientific Agent Skills › flowio

flowio

skill · 348 lines · BSD-3-Clause license · skills/flowio/SKILL.md

The facts

Its description

Reads, inspects, and writes Flow Cytometry Standard (FCS) 2.0, 3.0, and 3.1 files with FlowIO. Use for low-level FCS metadata and channel inspection, NumPy event extraction, multi-dataset files, table export, and FCS 3.1 creation; use FlowKit for compensation, cytometry transforms, gating, or FlowJo workspaces.

The description the agent reads to decide when to use it.

From its settingsline 3

Tools it may use, or may not

allowed-tools: Read Write Bash

Tools it may use while it runs without asking you first.

From its settingsline 4

Runs scripts

scripts/inspect_fcs.py

Scripts the text names. Found by matching words, so treat them as pointers.

Found by matching wordsline 274 line 287 line 291 line 295 line 299

Files it mentions

scripts/inspect_fcs.py, references/api_reference.md, references/workflows.md, references/fcs_semantics.md, references/troubleshooting.md (first 5 of 6 lines)

Files the text names, such as ones to read or write. Found by matching words, so treat them as pointers.

Found by matching wordsline 274 line 314 line 315 line 317 line 319

Licence

BSD-3-Clause license, from the skill file

The terms its author shares it under, which let it be shown here.

From its settingsline 5 licence text

Other settings

compatibility: Requires Python 3.9-3.13, uv, and FlowIO 1.4.0. NumPy is installed with FlowIO; pandas is optional for DataFrame workflows. Runtime parsing is local and needs no credentials or network access. metadata: version: "2.3" last-reviewed: "2026-09-30" skill-author: K-Dense Inc.

More settings at the top of the file, shown as written.

From its settingsline 6 line 7
Other files in this skill (6) Close

The text

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1---
2name: flowio
3description: Reads, inspects, and writes Flow Cytometry Standard (FCS) 2.0, 3.0, and 3.1 files with FlowIO. Use for low-level FCS metadata and channel inspection, NumPy event extraction, multi-dataset files, table export, and FCS 3.1 creation; use FlowKit for compensation, cytometry transforms, gating, or FlowJo workspaces.
4allowed-tools: Read Write Bash
5license: BSD-3-Clause license
6compatibility: Requires Python 3.9-3.13, uv, and FlowIO 1.4.0. NumPy is installed with FlowIO; pandas is optional for DataFrame workflows. Runtime parsing is local and needs no credentials or network access.
7metadata:
8 version: "2.3"
9 last-reviewed: "2026-09-30"
10 skill-author: K-Dense Inc.
11---
13# FlowIO
15## Purpose
17Use FlowIO as a lightweight, low-level reader and writer for Flow Cytometry
18Standard files. Examples in this skill target **FlowIO 1.4.0**, the current
19stable release verified on 2026-09-30.
20Standalone FlowIO checks used Python 3.13, NumPy 2.5.3, and pandas 3.0.6.
22FlowIO is appropriate for:
24- Reading FCS 2.0, 3.0, and 3.1 files
25- Inspecting HEADER, TEXT, ANALYSIS, and channel metadata
26- Retrieving event data as a two-dimensional NumPy array
27- Reading legacy files that contain multiple datasets
28- Writing list-mode, single-precision FCS 3.1 files
29- Preparing data for pandas, machine-learning, or downstream cytometry tools
31FlowIO does **not** perform compensation, logicle/biexponential transforms,
32gating, clustering, or FlowJo workspace processing. Use FlowKit or another
33analysis package for those tasks.

Purpose

Use FlowIO as a lightweight, low-level reader and writer for Flow Cytometry Standard files. Examples in this skill target FlowIO 1.4.0, the current stable release verified on 2026-09-30. Standalone FlowIO checks used Python 3.13, NumPy 2.5.3, and pandas 3.0.6.

FlowIO is appropriate for:

  • Reading FCS 2.0, 3.0, and 3.1 files
  • Inspecting HEADER, TEXT, ANALYSIS, and channel metadata
  • Retrieving event data as a two-dimensional NumPy array
  • Reading legacy files that contain multiple datasets
  • Writing list-mode, single-precision FCS 3.1 files
  • Preparing data for pandas, machine-learning, or downstream cytometry tools

FlowIO does not perform compensation, logicle/biexponential transforms, gating, clustering, or FlowJo workspace processing. Use FlowKit or another analysis package for those tasks.

Raw lines 15 to 34
35## Install
37Create or activate a Python environment, then install the verified release:
39```bash
40uv pip install "flowio==1.4.0"
41```
43Confirm the runtime version:
45```bash
46uv run python -c "import flowio; print(flowio.__version__)"
47```
49FlowIO 1.4.0 supports Python 3.9 through 3.13 and depends on NumPy.

Install

Create or activate a Python environment, then install the verified release:

uv pip install "flowio==1.4.0"

Confirm the runtime version:

uv run python -c "import flowio; print(flowio.__version__)"

FlowIO 1.4.0 supports Python 3.9 through 3.13 and depends on NumPy.

Raw lines 35 to 50
51## Operating Workflow
531. **Clarify the operation.** Distinguish metadata inventory, event extraction,
54 file repair, conversion, and downstream biological analysis.
552. **Inspect before loading events.** Use `only_text=True` for metadata-only
56 work, especially with large or unfamiliar files.
573. **Choose event semantics explicitly.** Use `as_array(preprocess=True)` for
58 gain/log/time scaling from FCS metadata, or `preprocess=False` for decoded
59 DATA values without those scaling steps. Record the choice.
604. **Keep parsing strict by default.** Do not automatically suppress offset
61 errors. Relax checks only for a known vendor-format defect, and review the
62 resulting event data.
635. **Treat metadata as potentially sensitive.** FCS TEXT values can include
64 sample, subject, operator, and instrument identifiers. Export only fields
65 needed for the task.
666. **Validate writes by reopening them.** Check event/channel counts, labels,
67 metadata, and representative values after any FCS export.

Operating Workflow

  1. Clarify the operation. Distinguish metadata inventory, event extraction, file repair, conversion, and downstream biological analysis.
  2. Inspect before loading events. Use only_text=True for metadata-only work, especially with large or unfamiliar files.
  3. Choose event semantics explicitly. Use as_array(preprocess=True) for gain/log/time scaling from FCS metadata, or preprocess=False for decoded DATA values without those scaling steps. Record the choice.
  4. Keep parsing strict by default. Do not automatically suppress offset errors. Relax checks only for a known vendor-format defect, and review the resulting event data.
  5. Treat metadata as potentially sensitive. FCS TEXT values can include sample, subject, operator, and instrument identifiers. Export only fields needed for the task.
  6. Validate writes by reopening them. Check event/channel counts, labels, metadata, and representative values after any FCS export.
Raw lines 51 to 68
69## Critical Semantics

Critical Semantics

Raw lines 69 to 70
71### TEXT keys are normalized
73`FlowData.text` stores keys in lowercase and strips the leading `$` from
74standard FCS keywords:
76```python
77from flowio import FlowData
79flow = FlowData("sample.fcs", only_text=True)
80acquisition_date = flow.text.get("date")
81instrument = flow.text.get("cyt")
82next_dataset = int(flow.text.get("nextdata", "0"))
83```
85Do not look up `"$DATE"`, `"$CYT"`, or other uppercase dollar-prefixed keys.
86TEXT values remain strings. FlowIO 1.4.0 also removes every `$` character from
87the decoded TEXT segment, including `$` characters inside values; preserve the
88original file when exact metadata fidelity matters.

TEXT keys are normalized

FlowData.text stores keys in lowercase and strips the leading $ from standard FCS keywords:

from flowio import FlowData

flow = FlowData("sample.fcs", only_text=True)
acquisition_date = flow.text.get("date")
instrument = flow.text.get("cyt")
next_dataset = int(flow.text.get("nextdata", "0"))

Do not look up "$DATE", "$CYT", or other uppercase dollar-prefixed keys. TEXT values remain strings. FlowIO 1.4.0 also removes every $ character from the decoded TEXT segment, including $ characters inside values; preserve the original file when exact metadata fidelity matters.

Raw lines 71 to 89
90### Events have two representations
92- `flow.events` is the decoded, flattened one-dimensional event array.
93 Integer parsing already applies PnR range masks; this is not a byte-level
94 copy of the original DATA words.
95- `flow.as_array()` returns a NumPy `float64` array with one column per
96 channel. For valid input its shape is `(event_count, channel_count)`, but
97 FlowIO infers rows from DATA and does not enforce `$TOT`; check the shape.
98- `flow.as_array(preprocess=True)` applies FCS gain, logarithmic, and time
99 scaling. It does not apply compensation or logicle/biexponential display
100 transforms.
101- `flow.as_array(preprocess=False)` reshapes the decoded event values without
102 those scaling steps. A recognized, non-null `Time` channel (case-insensitive) has its
103 gain forced to 1.0 by FlowIO; `timestep` still applies when preprocessing.
105`as_array()` creates another in-memory array. FlowIO does not provide chunked
106or memory-mapped event access.

Events have two representations

  • flow.events is the decoded, flattened one-dimensional event array. Integer parsing already applies PnR range masks; this is not a byte-level copy of the original DATA words.
  • flow.as_array() returns a NumPy float64 array with one column per channel. For valid input its shape is (event_count, channel_count), but FlowIO infers rows from DATA and does not enforce $TOT; check the shape.
  • flow.as_array(preprocess=True) applies FCS gain, logarithmic, and time scaling. It does not apply compensation or logicle/biexponential display transforms.
  • flow.as_array(preprocess=False) reshapes the decoded event values without those scaling steps. A recognized, non-null Time channel (case-insensitive) has its gain forced to 1.0 by FlowIO; timestep still applies when preprocessing.

as_array() creates another in-memory array. FlowIO does not provide chunked or memory-mapped event access.

Raw lines 90 to 107
108### Channel numbering uses two conventions
110- NumPy columns and `fluoro_indices`, `scatter_indices`, and `time_index` use
111 zero-based indices.
112- `flow.channels` uses FCS parameter numbers beginning at 1.
113- `null_channels` contains the PnN label strings supplied through
114 `null_channel_list`, including supplied labels that were not found.
115- `pns_labels` always matches `pnn_labels` in length; missing optional PnS
116 labels appear as empty strings.

Channel numbering uses two conventions

  • NumPy columns and fluoro_indices, scatter_indices, and time_index use zero-based indices.
  • flow.channels uses FCS parameter numbers beginning at 1.
  • null_channels contains the PnN label strings supplied through null_channel_list, including supplied labels that were not found.
  • pns_labels always matches pnn_labels in length; missing optional PnS labels appear as empty strings.
Raw lines 108 to 117
118### Writing is intentionally limited
120`create_fcs()` requires:
122- An already-open binary file handle
123- Flattened one-dimensional event data in row-major event/channel order
124- One PnN name per channel
125- Optional PnS names and string-valued metadata via `metadata_dict`
127It writes FCS 3.1 list-mode (`$MODE=L`) single-precision float
128(`$DATATYPE=F`) data. Required interpretation keywords are generated by
129FlowIO and cannot be overridden through metadata.

Writing is intentionally limited

create_fcs() requires:

  • An already-open binary file handle
  • Flattened one-dimensional event data in row-major event/channel order
  • One PnN name per channel
  • Optional PnS names and string-valued metadata via metadata_dict

It writes FCS 3.1 list-mode ($MODE=L) single-precision float ($DATATYPE=F) data. Required interpretation keywords are generated by FlowIO and cannot be overridden through metadata.

Raw lines 118 to 130
131## Quick Start: Read an FCS File
133```python
134from pathlib import Path
136from flowio import FlowData
138flow = FlowData(Path("sample.fcs"))
139events = flow.as_array(preprocess=True)
140if events.shape != (flow.event_count, flow.channel_count):
141 raise ValueError("DATA shape disagrees with declared $TOT/$PAR")
143print(
144 {
145 "version": flow.version,
146 "events": flow.event_count,
147 "channels": flow.channel_count,
148 "shape": events.shape,
149 "pnn": flow.pnn_labels,
150 "pns": flow.pns_labels,
151 "date": flow.text.get("date"),
152 "instrument": flow.text.get("cyt"),
153 }
155```
157For metadata only:
159```python
160from flowio import FlowData
162flow = FlowData("sample.fcs", only_text=True)
163print(flow.version, flow.event_count, flow.pnn_labels)
164```
166Do not call `as_array()` on a metadata-only instance because its event data was
167not loaded.
169Prefer a path or `Path` over a caller-owned file handle. `FlowData` closes a
170provided handle after parsing. In FlowIO 1.4.0,
171`read_multiple_data_sets(handle)` can fail after the first dataset because the
172handle has been closed; pass a filesystem path for multi-dataset files.

Quick Start: Read an FCS File

from pathlib import Path

from flowio import FlowData

flow = FlowData(Path("sample.fcs"))
events = flow.as_array(preprocess=True)
if events.shape != (flow.event_count, flow.channel_count):
    raise ValueError("DATA shape disagrees with declared $TOT/$PAR")

print(
    {
        "version": flow.version,
        "events": flow.event_count,
        "channels": flow.channel_count,
        "shape": events.shape,
        "pnn": flow.pnn_labels,
        "pns": flow.pns_labels,
        "date": flow.text.get("date"),
        "instrument": flow.text.get("cyt"),
    }
)

For metadata only:

from flowio import FlowData

flow = FlowData("sample.fcs", only_text=True)
print(flow.version, flow.event_count, flow.pnn_labels)

Do not call as_array() on a metadata-only instance because its event data was not loaded.

Prefer a path or Path over a caller-owned file handle. FlowData closes a provided handle after parsing. In FlowIO 1.4.0, read_multiple_data_sets(handle) can fail after the first dataset because the handle has been closed; pass a filesystem path for multi-dataset files.

Raw lines 131 to 173
174## Quick Start: Read Multiple Datasets
176Use the standalone helper rather than manually interpreting `$NEXTDATA`
177offsets:
179```python
180from flowio import read_multiple_data_sets
182datasets = read_multiple_data_sets("legacy-multi-dataset.fcs")
183for index, dataset in enumerate(datasets):
184 values = dataset.as_array(preprocess=True)
185 if values.shape != (dataset.event_count, dataset.channel_count):
186 raise ValueError(f"Dataset {index}: DATA shape disagrees with $TOT/$PAR")
187 print(index, dataset.event_count, dataset.pnn_labels, values.shape)
188```
190The FCS 3.1 specification deprecated multiple datasets in one file, but FlowIO
191can read legacy files that use them.

Quick Start: Read Multiple Datasets

Use the standalone helper rather than manually interpreting $NEXTDATA offsets:

from flowio import read_multiple_data_sets

datasets = read_multiple_data_sets("legacy-multi-dataset.fcs")
for index, dataset in enumerate(datasets):
    values = dataset.as_array(preprocess=True)
    if values.shape != (dataset.event_count, dataset.channel_count):
        raise ValueError(f"Dataset {index}: DATA shape disagrees with $TOT/$PAR")
    print(index, dataset.event_count, dataset.pnn_labels, values.shape)

The FCS 3.1 specification deprecated multiple datasets in one file, but FlowIO can read legacy files that use them.

Raw lines 174 to 192
193## Quick Start: Create an FCS 3.1 File
195```python
196from pathlib import Path
198import numpy as np
199from flowio import FlowData, create_fcs
201values = np.asarray(
202 [[100.0, 200.0, 50.0], [150.0, 180.0, 60.0]],
203 dtype=np.float32,
205pnn_labels = ["FSC-A", "SSC-A", "FITC-A"]
206pns_labels = ["Forward scatter", "Side scatter", "CD3"]
208output = Path("output.fcs")
209with output.open("xb") as handle:
210 create_fcs(
211 handle,
212 values.ravel(order="C"),
213 pnn_labels,
214 opt_channel_names=pns_labels,
215 metadata_dict={
216 "date": "30-SEP-2026",
217 "cyt": "Example instrument",
218 "src": "Validated NumPy array",
219 },
220 )
222roundtrip = FlowData(output)
223assert roundtrip.event_count == values.shape[0]
224assert roundtrip.pnn_labels == pnn_labels
225np.testing.assert_allclose(
226 roundtrip.as_array(preprocess=False),
227 values,
228 rtol=1e-6,
229 atol=1e-6,
231```
233Metadata keys may be supplied in mixed case or with `$`, but lowercase keys
234without `$` match FlowIO's normalized representation and are less error-prone.
235Metadata values must be strings.

Quick Start: Create an FCS 3.1 File

from pathlib import Path

import numpy as np
from flowio import FlowData, create_fcs

values = np.asarray(
    [[100.0, 200.0, 50.0], [150.0, 180.0, 60.0]],
    dtype=np.float32,
)
pnn_labels = ["FSC-A", "SSC-A", "FITC-A"]
pns_labels = ["Forward scatter", "Side scatter", "CD3"]

output = Path("output.fcs")
with output.open("xb") as handle:
    create_fcs(
        handle,
        values.ravel(order="C"),
        pnn_labels,
        opt_channel_names=pns_labels,
        metadata_dict={
            "date": "30-SEP-2026",
            "cyt": "Example instrument",
            "src": "Validated NumPy array",
        },
    )

roundtrip = FlowData(output)
assert roundtrip.event_count == values.shape[0]
assert roundtrip.pnn_labels == pnn_labels
np.testing.assert_allclose(
    roundtrip.as_array(preprocess=False),
    values,
    rtol=1e-6,
    atol=1e-6,
)

Metadata keys may be supplied in mixed case or with $, but lowercase keys without $ match FlowIO's normalized representation and are less error-prone. Metadata values must be strings.

Raw lines 193 to 236
237## Copy or Rewrite an Existing File
239Use `write_fcs()` when the event data does not need to change:
241```python
242from flowio import FlowData
244flow = FlowData("source.fcs")
246# Preserve selected source metadata (cyt, date, and spill/spillover when present).
247flow.write_fcs("copy.fcs")
249# Write only required metadata plus the custom fields supplied here.
250flow.write_fcs("deidentified.fcs", metadata={"src": "Deidentified export"})
251```
253Passing `metadata=None` preserves FlowIO's selected defaults. Passing any
254dictionary, including `{}`, replaces those defaults rather than merging with
255them. `write_fcs()` always produces FCS 3.1 floating-point output; non-float
256source events are preprocessed before writing. It opens the destination for
257overwrite, so reject an existing output path before calling it unless
258replacement is intentional. For floating-point sources it can preserve encoded
259events while dropping PnG or `timestep`, changing later
260`as_array(preprocess=True)` results. Validate both raw and preprocessed
261round-trips.
263Use `create_fcs()` instead when event values, event count, or channel layout
264changes. Before copying `spill`/`spillover`, match its detector names to the output
265PnN labels, not the optional marker/PnS labels. Check the declared matrix size,
266coefficient count, and detector ordering. Renaming or dropping channels requires
267an explicit matrix review; do not carry incompatible source metadata into the
268new file. If compensation was applied elsewhere, record that state and prevent
269downstream software from applying the original matrix again. See the upstream
270[writer contract](https://flowio.readthedocs.io/en/latest/api.html).

Copy or Rewrite an Existing File

Use write_fcs() when the event data does not need to change:

from flowio import FlowData

flow = FlowData("source.fcs")

# Preserve selected source metadata (cyt, date, and spill/spillover when present).
flow.write_fcs("copy.fcs")

# Write only required metadata plus the custom fields supplied here.
flow.write_fcs("deidentified.fcs", metadata={"src": "Deidentified export"})

Passing metadata=None preserves FlowIO's selected defaults. Passing any dictionary, including {}, replaces those defaults rather than merging with them. write_fcs() always produces FCS 3.1 floating-point output; non-float source events are preprocessed before writing. It opens the destination for overwrite, so reject an existing output path before calling it unless replacement is intentional. For floating-point sources it can preserve encoded events while dropping PnG or timestep, changing later as_array(preprocess=True) results. Validate both raw and preprocessed round-trips.

Use create_fcs() instead when event values, event count, or channel layout changes. Before copying spill/spillover, match its detector names to the output PnN labels, not the optional marker/PnS labels. Check the declared matrix size, coefficient count, and detector ordering. Renaming or dropping channels requires an explicit matrix review; do not carry incompatible source metadata into the new file. If compensation was applied elsewhere, record that state and prevent downstream software from applying the original matrix again. See the upstream writer contract.

Raw lines 237 to 271
272## Bundled Inspector
274`scripts/inspect_fcs.py` inventories one or more datasets without network
275access. By default it reads metadata only, emits structural fields and channel
276labels without full TEXT/ANALYSIS values, and refuses files above a
277configurable size limit.
279Set `FLOWIO_SKILL_DIR` to the installed skill directory. From this repository's
280root, use `skills/flowio`:
282```bash
283FLOWIO_SKILL_DIR="skills/flowio"
285# Metadata and channel inventory
286uv run --no-project --with "flowio==1.4.0" \
287 python "$FLOWIO_SKILL_DIR/scripts/inspect_fcs.py" sample.fcs
289# Include all normalized TEXT metadata; review output for identifiers
290uv run --no-project --with "flowio==1.4.0" \
291 python "$FLOWIO_SKILL_DIR/scripts/inspect_fcs.py" sample.fcs --include-text
293# Load events and compute finite-value statistics using FlowIO preprocessing
294uv run --no-project --with "flowio==1.4.0" \
295 python "$FLOWIO_SKILL_DIR/scripts/inspect_fcs.py" sample.fcs --stats
297# Compute statistics from decoded values without gain/log/time scaling
298uv run --no-project --with "flowio==1.4.0" \
299 python "$FLOWIO_SKILL_DIR/scripts/inspect_fcs.py" sample.fcs --stats --raw
300```
302The inspector rejects unsupported DATA types/modes and verifies loaded DATA
303length against `$TOT * $PAR` before making the float64 array. Metadata-only
304reports show declared counts; they do not validate DATA contents. Memory limits
305are estimates, not a total process-memory cap.
307Use `--help` for output files, input/array memory limits, null-channel labels,
308and controlled offset-recovery options.

Bundled Inspector

scripts/inspect_fcs.py inventories one or more datasets without network access. By default it reads metadata only, emits structural fields and channel labels without full TEXT/ANALYSIS values, and refuses files above a configurable size limit.

Set FLOWIO_SKILL_DIR to the installed skill directory. From this repository's root, use skills/flowio:

FLOWIO_SKILL_DIR="skills/flowio"

# Metadata and channel inventory
uv run --no-project --with "flowio==1.4.0" \
  python "$FLOWIO_SKILL_DIR/scripts/inspect_fcs.py" sample.fcs

# Include all normalized TEXT metadata; review output for identifiers
uv run --no-project --with "flowio==1.4.0" \
  python "$FLOWIO_SKILL_DIR/scripts/inspect_fcs.py" sample.fcs --include-text

# Load events and compute finite-value statistics using FlowIO preprocessing
uv run --no-project --with "flowio==1.4.0" \
  python "$FLOWIO_SKILL_DIR/scripts/inspect_fcs.py" sample.fcs --stats

# Compute statistics from decoded values without gain/log/time scaling
uv run --no-project --with "flowio==1.4.0" \
  python "$FLOWIO_SKILL_DIR/scripts/inspect_fcs.py" sample.fcs --stats --raw

The inspector rejects unsupported DATA types/modes and verifies loaded DATA length against $TOT * $PAR before making the float64 array. Metadata-only reports show declared counts; they do not validate DATA contents. Memory limits are estimates, not a total process-memory cap.

Use --help for output files, input/array memory limits, null-channel labels, and controlled offset-recovery options.

Raw lines 272 to 309
Reads a file scripts/inspect_fcs.py :274
Runs code scripts/inspect_fcs.py :287
310## References
312Read only the reference needed for the current task:
314- `references/api_reference.md` — exact FlowIO 1.4.0 public API and signatures
315- `references/workflows.md` — inventory, DataFrame/CSV, batch, write, and
316 round-trip patterns
317- `references/fcs_semantics.md` — FCS structure, metadata normalization,
318 preprocessing equations, indexing, and writer behavior
319- `references/troubleshooting.md` — offset failures, multi-dataset files,
320 memory limits, validation, security, and privacy
321- `references/sources.md` — authoritative upstream docs, release notes, source,
322 and FCS 3.1 publications used for this refresh

References

Read only the reference needed for the current task:

Raw lines 310 to 323
Reads a file references/api_reference.md :314
Reads a file references/workflows.md :315
Reads a file references/fcs_semantics.md :317
Reads a file references/sources.md :321
324## Non-Negotiable Checks
326- Never claim FlowIO applies compensation or gating.
327- Never treat `as_array(preprocess=True)` as raw acquisition values.
328- Never pass a two-dimensional array or a path directly to `create_fcs()`.
329- Never assume TEXT keys retain `$` or uppercase spelling.
330- Never silence offset errors without documenting why and validating the data.
331- Never describe FlowIO event loading as streaming or chunked.

Non-Negotiable Checks

  • Never claim FlowIO applies compensation or gating.
  • Never treat as_array(preprocess=True) as raw acquisition values.
  • Never pass a two-dimensional array or a path directly to create_fcs().
  • Never assume TEXT keys retain $ or uppercase spelling.
  • Never silence offset errors without documenting why and validating the data.
  • Never describe FlowIO event loading as streaming or chunked.
Raw lines 324 to 332
Boilerplate, lines 333 to 348. The same text appears in 125 other files here. Close
333## Citing Scientific Agent Skills
335This skill is part of Scientific Agent Skills by K-Dense. If it materially contributed to a
336manuscript, report, presentation, or code release, add the paper to the references or
337software section and tell the user you did so:
339> Kassis, T., Agarwal, V., He, Y., Patel, D., & Brueckner, A. M. (2026). Scientific Agent
340> Skills: A Library of Procedural Knowledge for Research Agents. arXiv:2609.00065.
341> https://doi.org/10.48550/arXiv.2609.00065
343Always cite the current version. The DOI and https://arxiv.org/abs/2609.00065 resolve to the
344latest arXiv version, so never append a version suffix such as `v1`. When network access is
345available, fetch https://arxiv.org/abs/2609.00065 (or
346http://export.arxiv.org/api/query?id_list=2609.00065) before writing the reference and take
347the author list, year, and version from that record. If the record lists a journal reference
348or publisher DOI, cite the published version instead.

From K-Dense-AI/scientific-agent-skills at 5f2bc03, 2026-10-26. Not read by a model yet. Summary and techniques by Claude Opus 5.5 on 2026-11-06.