| name | bio-flow-cytometry-fcs-handling |
| description | Read and manipulate Flow Cytometry Standard (FCS) files. Covers loading data, accessing parameters, and basic data exploration. Use when loading and inspecting flow or mass cytometry data before preprocessing. |
| tool_type | r |
| primary_tool | flowCore |
Version Compatibility
Reference examples tested with: flowCore 2.14+, scanpy 1.10+
Before using code patterns, verify installed versions match. If versions differ:
- R:
packageVersion('<pkg>') then ?function_name to verify parameters
If code throws ImportError, AttributeError, or TypeError, introspect the installed
package and adapt the example to match the actual API rather than retrying.
FCS File Handling
"Load my FCS files into R or Python" → Read Flow Cytometry Standard (FCS) files, access channel parameters and metadata, and explore event data for downstream analysis.
- R:
flowCore::read.FCS() or flowCore::read.flowSet() for multiple files
- Python:
fcsparser.parse() or FlowCal.io.FCSData()
Load FCS Files
Goal: Read a single FCS file and inspect its parameters and metadata.
Approach: Use flowCore's read.FCS with transformation disabled to load raw data, then examine parameter names and descriptions.
library(flowCore)
fcs <- read.FCS('sample.fcs', transformation = FALSE, truncate_max_range = FALSE)
print(fcs)
colnames(fcs)
pData(parameters(fcs))
Load Multiple Files
Goal: Read a batch of FCS files into a single flowSet container for uniform processing.
Approach: List FCS files from a directory and load them into a flowSet with read.flowSet.
files <- list.files('data', pattern = '\\.fcs$', full.names = TRUE)
fs <- read.flowSet(files, transformation = FALSE, truncate_max_range = FALSE)
sampleNames(fs)
fcs1 <- fs[[1]]
Access Expression Data
Goal: Extract the expression matrix from a flowFrame for numeric analysis.
Approach: Call exprs() to get the cells-by-channels matrix, then subset or summarize as needed.
expr <- exprs(fcs)
head(expr)
dim(expr)
summary(expr)
cd4_expr <- expr[, 'CD4']
Channel Metadata
Goal: Retrieve channel names, descriptions, and ranges from the FCS parameter table.
Approach: Access the parameters slot via pData(parameters(fcs)) and build a short-name to description mapping.
params <- pData(parameters(fcs))
print(params)
channel_map <- setNames(params$desc, params$name)
Rename Channels
rename_channels <- function(fcs) {
params <- pData(parameters(fcs))
new_names <- ifelse(is.na(params$desc) | params$desc == '',
params$name, params$desc)
colnames(fcs) <- new_names
return(fcs)
}
fcs_renamed <- rename_channels(fcs)
Subsetting Data
fcs_subset <- fcs[1:1000, ]
fcs_markers <- fcs[, c('CD4', 'CD8', 'CD3')]
high_cd4 <- fcs[exprs(fcs)[, 'CD4'] > 1000, ]
Merge flowSets
fs_combined <- rbind2(fs1, fs2)
all_data <- fsApply(fs, exprs)
all_data <- do.call(rbind, all_data)
Write FCS Files
write.FCS(fcs, 'output.fcs')
write.flowSet(fs, outdir = 'output_dir')
Sample Metadata
pData(fs) <- data.frame(
name = sampleNames(fs),
condition = c('Control', 'Control', 'Treatment', 'Treatment'),
patient = c('P1', 'P2', 'P1', 'P2')
)
pData(fs)
Basic Visualization
library(ggcyto)
autoplot(fcs, 'FSC-A')
autoplot(fcs, 'CD4', 'CD8')
autoplot(fs, 'CD4', 'CD8')
Check Data Quality
if ('Time' %in% colnames(fcs)) {
time <- exprs(fcs)[, 'Time']
plot(time, type = 'l', main = 'Acquisition Time')
}
fsApply(fs, nrow)
saturation <- apply(exprs(fcs), 2, function(x) mean(x == max(x)) * 100)
print(saturation)
Convert to Data Frame
library(tidyverse)
df <- as.data.frame(exprs(fcs))
df$sample <- 'sample1'
df_all <- fsApply(fs, function(f) {
d <- as.data.frame(exprs(f))
d$sample <- identifier(f)
d
}, simplify = FALSE)
df_all <- bind_rows(df_all)
Related Skills
- compensation-transformation - Apply compensation and transforms
- gating-analysis - Define cell populations
- clustering-phenotyping - Unsupervised analysis