
Package index
Run the pipeline
One call does everything. The stage functions below are the same code, split so a step can be run, inspected or replaced on its own.
-
run_cyraven() - run_cyraven
Reading and transformation
Getting FCS files into a matrix on a sensible scale. The transform is selectable, and its parameters are derived once per panel so every sample stays on one ruler.
-
read_fcs_resolved() - Read one FCS file and resolve marker symbols
-
fingerprint_panels() - Group files into panels by their exact marker set
-
maybe_compensate() - Apply the spillover matrix if one is present
-
read_spillover_file() - Read a spillover matrix from a CSV file
-
make_transform() - Build the intensity transform the whole run uses
-
derive_cofactor() - Derive the arcsinh cofactor from the data
-
derive_cofactor_pooled() - Derive the panel cofactor from SEVERAL samples, not from whichever file was read first
-
derive_logicle_pooled() - Derive one set of transform parameters for a panel
Gating
Thresholds derived from each sample’s own density rather than transferred from fixed coordinates. The reference for a marker that resolves no minimum can be an unstained tube or a fluorescence-minus-one control, and a single sample’s cut can be corrected by hand with the correction recorded.
-
density_valley() - Find the deepest density valley between two modes
-
resolve_threshold() - Resolve a threshold for one marker, recording where the value came from
-
apply_gate_hierarchy() - Apply the full gate hierarchy to one file
-
staining_verdict() - Staining QC verdict per file
-
sample_override() - Look up a per-sample, per-marker threshold override
-
parse_fmo_map() - Parse the
fmo_forcolumn into a marker-to-file map -
fmo_for_sample() - Which FMO file, if any, controls a given marker for a given sample
-
control_cut() - Place a cut on a control channel, and refuse a control that cannot be one
-
fmo_agreement() - Distance between a derived cut and its FMO-anchored equivalent
Acquisition and panel quality
Two questions the gating stage cannot answer on its own: whether the instrument was doing the same thing throughout the acquisition, and whether a marker that resolves no density minimum is failing because of the panel.
-
find_time_column() - Locate the Time channel in a read FCS file
-
detect_time_anomalies() - Flag acquisition intervals whose rate or signal departs from the file
-
run_acquisition_qc() - Run acquisition-time QC across a cohort
-
frequency_delta_if_cleaned() - How far each population moves if the flagged windows are excluded
-
fig_acquisition_qc() - Event rate across the acquisition, with the flagged intervals marked
-
spreading_pairs() - Spreading received by each marker from each other marker
-
run_spreading_report() - Spreading across a cohort, and which markers it is costing
-
spillover_spreading_matrix() - Spillover spreading matrix from single-stain controls
Calibration
Channel units are comparable within an instrument and never between two. Beads of assigned fluorophore equivalence convert them to units that are.
-
bead_peaks() - Locate bead populations in one channel
-
fit_bead_calibration() - Fit a channel-units to assigned-units calibration from a bead acquisition
-
apply_bead_calibration() - Apply a fitted calibration to a sample's linear channel values
Uncertainty
How far a threshold can move, how many cells were behind the frequency it produced, and what each of those costs. Every cut is resampled and re-derived over the settings that placed it, and the resulting spread is propagated to the populations that read it; the counting term is reported beside it, because a well-placed cut and a sufficient number of events are different guarantees. None of this changes a reported number; it puts a second number next to it.
-
threshold_uncertainty() - Uncertainty in one per-sample threshold
-
counting_uncertainty() - Counting uncertainty and detection limits for a population frequency
-
population_frequency_uncertainty() - Propagate threshold uncertainty into one sample's population frequencies
-
run_gate_uncertainty() - Run the whole uncertainty analysis over a scored cohort
-
annotate_gate_uncertainty() - Compare a between-group difference against the gate uncertainty behind it
-
valley_setting_grid() - The settings sweep that produces the method component
-
score_populations() - Evaluate the population spec against one file's thresholded markers
-
resolve_population_parents() - Resolve
parent:declarations in a population specification -
derive_scoped_cuts() - Derive the cuts a specification places within parent populations
-
default_population_spec() - Built-in population spec, derived from the supplied gating strategy
-
default_functional_blocks() - Functional marker blocks, transcribed from the document's four scoping rules
-
expected_positive_markers() - Markers each population's gate definition requires to be POSITIVE
-
compute_population_ratios() - Derived abundance ratios (e.g. CD4:CD8), from the config's
ratios:block -
immune_subset_spec() - Immune subset definitions resolvable from a given marker panel
Absolute cell counts
An externally measured cell yield per acquisition, joined on patient and timepoint, turns a share into a number of cells. That is the one thing a frequency table cannot express, because shares are constrained to sum to 100 and so cannot separate one population expanding from every other contracting.
-
load_total_counts() - Load, normalize, parse and sample-match a –total-counts input
-
attach_absolute_cells() - Attach absolute cell numbers to a per-sample abundance table
-
select_umap_features() - Choose the markers that define the embedding space
-
plan_subsample() - Draw a size-balanced subsample of gated cells across samples
-
density_weights() - Inverse-density sampling weights in marker space
-
draw_subsample_rare() - Draw a subsample that preserves sparse regions of marker space
-
run_umap() - Build the UMAP input matrix and run the embedding
-
save_umap_model() - Save a trained UMAP model plus the scaling needed to reproduce its input
-
load_umap_model() - Load a saved UMAP model
-
project_umap() - Project new cells into a saved embedding
Clustering
Unsupervised clustering as a cross-check on the gate specification, and reference-defined subclustering.
-
run_unsupervised_clusters() - Unsupervised clustering of the embedded cells
-
cluster_gate_agreement() - Cross-tabulate unsupervised clusters against gate labels
-
subcluster_by_reference() - Split each cluster into subclusters DEFINED ON THE REFERENCE GROUP
-
choose_subcluster_k() - Choose k per population from the reference group's cells
-
write_suggested_config() - Write the declared specification plus a draft entry per uncovered cluster
Learned gates
The inverse of the gating stage: given a set of labelled cells, learn a two-marker gating strategy that selects them. This is what turns “this cluster matches no described population” into a gate someone can draw. Descriptive throughout – it proposes gates and never changes a scored one.
-
learn_convex_gate() - Learn a convex two-marker gate for a labelled set of cells
-
explain_cluster() - Learn a hierarchical gating strategy for one labelled population
-
explain_unmatched_clusters() - Propose gating strategies for clusters the spec does not describe
-
rank_gate_markers() - Rank markers by how differently they are distributed in targets and the rest
-
fig_gate_strategy() - Draw a proposed gating strategy, one panel per gate
Labels from another tool
Take a cell labelling this package did not produce, a cyCONDOR clustering for instance, learn a gate that selects it, and find out whether that gate holds on a donor it was not fitted to. Held-out cells come from the same donors as the training cells and overstate transferability; refitting with one donor withheld does not.
-
read_external_labels() - Read cell labels produced by another tool
-
join_external_labels() - Attach external labels to the embedding cell table
-
explain_external_labels() - Learn and validate a gate for each externally supplied label
-
gate_transferability() - Does the gate work on a donor it was not fitted to
-
apply_gate_strategy() - Apply a learned gating strategy to new cells
Gate export
A learned gate that stays in R cannot be sorted on. These write it out in the units the FCS file stores, as ISAC Gating-ML 2.0 and as a plain table of vertices.
-
write_gating_ml() - Write learned gating strategies as a Gating-ML 2.0 document
-
polygons_linear_table() - The same polygons as a plain table in linear units
-
polygon_to_linear() - Subdivide polygon edges and return them in linear units
-
abundance_measure() - Pick the best available abundance measure, and say what it means
-
stats_group_comparison() - Test each population's abundance between groups
-
fig_group_volcano() - Between-group differences for every population in one figure
-
stats_marker_state() - Sample-level differential-state test: population x marker x group
-
stats_subcluster_shifts() - Per (cluster, subcluster, marker, study): how far is this study from reference
-
clr_frequencies() - Zero-safe centred log-ratio of each sample's population composition
-
exclusive_label_frequencies() - Each sample's composition by exclusive label
-
compositional_concordance() - Concordance between the raw-percentage test and the CLR test
-
stats_confounding() - Is a covariate confounded with cohort, and does it track the outcome?
-
stats_rank_ancova() - Rank ANCOVA: cohort effect after adjusting for covariates (EXPLORATORY)
-
stats_paired_comparison() - Paired / repeated-measures abundance test
Clinical variables
A severity score, a laboratory value or an outcome flag is neither the study group nor a confounder: a confounder is screened to decide whether a group difference can be believed, a clinical variable is the question. The test follows the variable’s type – Spearman for numeric, Wilcoxon with Cliff’s delta for two levels, Kruskal-Wallis for more – and multiplicity is corrected within each variable rather than across all of them. Association only: a 28-day flag is a two-group comparison, and no time-to-event model is fitted because the sheet carries no follow-up time. The figures are in reading order: the variables against each other, then the association across all of them, then the cohort as one annotated matrix, then per variable the effects with their bootstrap intervals. Every signed effect carries a percentile bootstrap interval, because on ten patients the interval usually spans zero and that is the finding.
-
stats_clinical_association() - Clinical variables against population frequencies and marker intensities
-
fig_clinical_correlogram() - Spearman correlation between the clinical variables themselves
-
fig_clinical_landscape() - The cohort as one picture: populations, samples and every clinical variable
-
fig_clinical_forest() - Ordered effect sizes with bootstrap intervals for one clinical variable
-
fig_clinical_trajectory() - Per-patient trajectories across timepoints, split by outcome
Batch structure
Measure the batch effect first, then decide. Correction is opt-in and is refused when batch and study group overlap far enough that removing one removes the other.
-
lisi_score() - Local Inverse Simpson's Index of a label over a neighbourhood graph
-
batch_mixing_report() - Batch-mixing diagnostic with a permutation null and a confounding check
-
marker_batch_drift() - Per-marker distributional drift between acquisition batches
-
emd_1d() - One-dimensional Earth Mover's distance between two samples
-
correct_batch() - Correct batch effects in the transformed marker matrix
-
stats_threshold_drift() - Test each marker's per-sample threshold for a cohort difference
-
write_run_manifest() - Write the run manifest
-
write_miflowcyt() - Write a MIFlowCyt-structured report of the run
-
write_run_report() - Write a single self-contained HTML report of everything a run produced
Conformance across runs
The within-run check in thresholds_used.csv compares each sample against its peers and catches one bad tube. It cannot catch a cohort that moved as a whole, because the peer median moves with it. A baseline written from an accepted run is the fixed reference that can.
-
write_spec_baseline() - Write a conformance baseline from an accepted run
-
read_spec_baseline() - Read a conformance baseline
-
specification_conformance() - Test this run against a baseline
-
spec_fingerprint() - Canonical text form of a population specification
-
fig_absolute_counts_qc() - QC heatmap for –absolute-counts: one tile per sample x population
-
fig_acquisition_qc() - Event rate across the acquisition, with the flagged intervals marked
-
fig_batch_diagnostic() - Batch diagnostic figure: the embedding coloured by batch, plus the LISI distribution against its permutation null
-
fig_clinical_correlogram() - Spearman correlation between the clinical variables themselves
-
fig_clinical_detail() - Per-population detail against one clinical variable
-
fig_clinical_forest() - Ordered effect sizes with bootstrap intervals for one clinical variable
-
fig_clinical_heatmap() - Heatmap of clinical association across populations or markers
-
fig_clinical_landscape() - The cohort as one picture: populations, samples and every clinical variable
-
fig_clinical_trajectory() - Per-patient trajectories across timepoints, split by outcome
-
fig_cohort_confusion() - Cohort composition heatmap ("confusion matrix")
-
fig_density_by_sample() - Per-sample (or per-group) density comparison over the shared embedding
-
fig_detection_limits() - How many samples each population is actually measurable in
-
fig_frequency_uncertainty() - Population frequencies with the uncertainty of the gate that produced them
-
fig_functional_markers() - Functional-marker positivity figure
-
fig_gate_strategy() - Draw a proposed gating strategy, one panel per gate
-
fig_gating_qc() - Per-gate QC figure: every applied gate shown per sample with its threshold
-
fig_group_comparison() - Grouped abundance figure: one panel per population, bar + SD + every sample
-
fig_group_volcano() - Between-group differences for every population in one figure
-
fig_marker_grid() - Marker-expression grid over the shared embedding
-
fig_marker_state() - Differential-state figure, drawn by the baseline's own comparison figure
-
fig_marker_umaps_by_group() - One UMAP per marker, pooled and split by every category present
-
fig_multigraph_overlay() - FlowJo-style Multigraph Overlay: every cluster x every marker, one peak per group
-
fig_population_frequencies() - Population frequency figure – one lettered panel per population
-
fig_population_marker_heatmap() - Population x marker phenotype heatmap
-
fig_population_ratios() - Population-ratio figure – same layout as fig_group_comparison(), one panel per ratio defined in the config's
ratios:block -
fig_populations_by_batch() - Population abundance per batch
-
fig_recon_diagnostics() - Initial reconnaissance / QC diagnostic figure – run on EVERY batch
-
fig_threshold_drift() - Threshold-drift figure: per-sample cut for every marker, coloured by cohort
-
fig_umap_overview() - Population + sample + covariate colouring panel set
-
fig_umap_overview_by_group() - Combined + per-group UMAP small multiples
-
fig_uncertainty_budget() - Where each population's uncertainty comes from
-
fig_unsupervised_clusters() - Unsupervised-clustering figure: the embedding by cluster, next to the same embedding by gate label
-
theme_cyto() - Publication-oriented minimal theme WHY: consistent, legible defaults across every emitted figure; outward ticks and frameless legends read better in print than ggplot2 defaults.
-
theme_panel_borders() - Panel borders and gutters for any faceted figure
-
natural_cluster_factor() - Order cluster labels k1, k2, ... k30 rather than k1, k10, k11, ... k2
Inputs
The sample sheet is one row per FCS file, carrying its identity, its subject’s attributes, its study variables and any externally measured counts. It is read into the same structures the three separate loaders below produce, by calling the same code, so the two routes cannot diverge.
-
write_demo_cohort() - Write the demonstration cohort
-
write_config_template() - Write the annotated config template
-
read_samplesheet() - Read the unified sample sheet
-
samplesheet_columns() - Reserved column names of the unified sample sheet
-
load_patient_table() - Read, filter, rename and translate the patient table
-
load_sample_map() - Read and validate the sample map
-
load_absolute_counts() - Load, normalize, parse and sample-match an –absolute-counts input
-
export_flowjo_fcs() - Write UMAP-annotated FCS files for FlowJo
-
default_colors() - Every colour this script draws with, in one place
-
fcs_colors()set_fcs_colors() - The colour palette every figure draws with
-
reference_group()set_reference_group() - The cohort every comparison is drawn against