| Crates.io | peacoqc-rs |
| lib.rs | peacoqc-rs |
| version | 0.1.3 |
| created_at | 2026-01-14 15:42:58.862413+00 |
| updated_at | 2026-01-18 16:30:22.973968+00 |
| description | PeacoQC quality control algorithms for flow cytometry |
| homepage | |
| repository | https://github.com/jrmoynihan/flow/peacoqc-rs |
| max_upload_size | |
| id | 2043070 |
| size | 471,161 |
PeacoQC-RS is a Rust implementation of PeacoQC (Peak-based Quality Control) algorithms for flow cytometry data. This library provides efficient, trait-based quality control methods that work with any FCS data structure through a simple trait interface.
PeacoQCData traitAdd this to your Cargo.toml:
[dependencies]
peacoqc-rs = { path = "../peacoqc-rs", version = "0.1.0", features = ["flow-fcs"] }
Or from crates.io (when published):
[dependencies]
peacoqc-rs = { version = "0.1.0", features = ["flow-fcs"] }
flow-fcs (default): Enable integration with the flow-fcs crate for FCS file supportuse peacoqc_rs::{PeacoQCConfig, PeacoQCData, QCMode, peacoqc};
// Assuming you have an FCS struct that implements PeacoQCData
let config = PeacoQCConfig {
channels: vec!["FL1-A".to_string(), "FL2-A".to_string()],
determine_good_cells: QCMode::All,
..Default::default()
};
let result = peacoqc(&fcs, &config)?;
// Apply the `good_cells` boolean mask from the PeacoQCResult struct
let clean_fcs = fcs.filter(&result.good_cells)?;
println!("Removed {:.2}% of events", result.percentage_removed);
// Export QC results for downstream analysis
result.export_csv_boolean("qc_results.csv")?;
result.export_json_metadata(&config, "qc_metadata.json")?;
See examples/basic_usage.rs for a complete working example.
PeacoQC-RS uses trait-based design for maximum interoperability. To use PeacoQC with your own FCS data structure, simply implement the PeacoQCData trait:
use peacoqc_rs::{PeacoQCData, Result};
struct MyFcs {
// your data fields
}
impl PeacoQCData for MyFcs {
fn n_events(&self) -> usize {
// return number of events
}
fn channel_names(&self) -> Vec<String> {
// return channel names
}
fn get_channel_range(&self, channel: &str) -> Option<(f64, f64)> {
// return channel range if available
}
fn get_channel_f64(&self, channel: &str) -> Result<Vec<f64>> {
// return channel data as Vec<f64>
}
}
Additionally, implement FcsFilter to enable filtering:
use peacoqc_rs::{FcsFilter, Result};
impl FcsFilter for MyFcs {
fn filter(&self, mask: &[bool]) -> Result<Self> {
// return a new instance with filtered data
}
}
If you enable the flow-fcs feature flag, PeacoQC-RS provides trait implementations for the Fcs struct provided by it:
use flow_fcs::Fcs;
use peacoqc_rs::{PeacoQCConfig, QCMode, peacoqc};
let fcs = Fcs::open("data.fcs")?;
let config = PeacoQCConfig {
channels: fcs.get_fluorescence_channels(), // Auto-detect channels
determine_good_cells: QCMode::All,
..Default::default()
};
let result = peacoqc(&fcs, &config)?;
// Apply the `good_cells` boolean mask from the PeacoQCResult struct
let clean_fcs = fcs.filter(&result.good_cells)?;
fn peacoqc<T: PeacoQCData>(fcs: &T, config: &PeacoQCConfig) -> Result<PeacoQCResult>
fn remove_margins<T: PeacoQCData>(fcs: &T, config: &MarginConfig) -> Result<MarginResult>
fn remove_doublets<T: PeacoQCData>(fcs: &T, config: &DoubletConfig) -> Result<DoubletResult>
PeacoQCConfig: Main configuration for quality control
channels: Channels to analyzedetermine_good_cells: QC mode (All, IsolationTree, MAD, None)mad: MAD threshold (default: 6.0)it_limit: Isolation Tree limit (default: 0.6)consecutive_bins: Consecutive bins threshold (default: 5)MarginConfig: Configuration for margin event removal
DoubletConfig: Configuration for doublet detection
PeacoQCResult: Complete QC results
good_cells: Boolean mask (true = keep, false = remove)percentage_removed: Percentage of events removedpeaks: Peak detection results per channeln_bins: Number of bins usedevents_per_bin: Events per binexport_csv_boolean(): Export as boolean CSV (0/1 values)export_csv_numeric(): Export as numeric CSV (2000/6000 values, R-compatible)export_json_metadata(): Export comprehensive QC metrics as JSONPeacoQC-RS supports multiple export formats for QC results, enabling integration with various downstream analysis tools.
Export QC results as a CSV file with 0/1 values:
result.export_csv_boolean("qc_results.csv")?;
Format:
PeacoQC
1
1
0
1
1 = good event (keep)0 = bad event (remove)Use cases:
df[df['PeacoQC'] == 1]df[df$PeacoQC == 1, ]WHERE PeacoQC = 1Export QC results as a CSV file with numeric codes matching the R PeacoQC package:
result.export_csv_numeric("qc_results_r.csv", 2000, 6000)?;
Format:
PeacoQC
2000
2000
6000
2000
2000 (or custom good_value) = good event (keep)6000 (or custom bad_value) = bad event (remove)Use cases:
Export comprehensive QC metrics and configuration as JSON:
result.export_json_metadata(&config, "qc_metadata.json")?;
Format:
{
"n_events_before": 713904,
"n_events_after": 631400,
"n_events_removed": 82504,
"percentage_removed": 11.56,
"it_percentage": 0.0,
"mad_percentage": 11.56,
"consecutive_percentage": 0.0,
"n_bins": 1427,
"events_per_bin": 500,
"channels_analyzed": ["FL1-A", "FL2-A"],
"config": {
"qc_mode": "All",
"mad": 6.0,
"it_limit": 0.6,
"consecutive_bins": 5,
"remove_zeros": false
}
}
Use cases:
You can specify custom column names for CSV exports:
result.export_csv_boolean_with_name("qc_results.csv", "QC_Status")?;
result.export_csv_numeric_with_name("qc_results_r.csv", 2000, 6000, "PeacoQC_Status")?;
Uses kernel density estimation (KDE) with Gaussian kernels to detect peaks in binned data. Peaks are identified using Silverman's rule for bandwidth selection.
An isolation forest-based outlier detection method. Events in bins with low isolation scores are flagged as outliers.
Detects outliers using the median absolute deviation method. Events exceeding a MAD threshold are flagged.
Removes short consecutive regions that may represent artifacts rather than real biological populations.
Detects channels with monotonic trends (increasing or decreasing) which may indicate technical problems:
Uses kernel smoothing (matching R's stats::ksmooth with bandwidth=50) to smooth bin medians, then checks if smoothed values satisfy monotonicity conditions using cummax/cummin. Channels are flagged if >75% of smoothed values are non-decreasing (increasing) or non-increasing (decreasing). This matches the original R implementation's algorithm.
PeacoQC-RS is optimized for performance:
rayon for parallel computation:
flow-fcs feature flag) for columnar storageRun benchmarks with:
cargo bench --bench peacoqc_bench
Benchmarks are currently being developed and will provide performance metrics for various dataset sizes.
The library includes comprehensive unit tests covering:
Run tests with:
cargo test
See examples/basic_usage.rs for a complete example demonstrating:
Run with:
cargo run --example basic_usage
All functions return Result<T, PeacoQCError>. The PeacoQCError enum covers:
InvalidChannel: Invalid or non-numeric channelChannelNotFound: Channel not found in dataInsufficientData: Not enough events for analysisStatsError: Statistical computation failedConfigError: Configuration errorNoPeaksDetected: No peaks detected in dataPolarsError: Polars DataFrame error (when using flow-fcs feature)MIT License - see LICENSE file for details
This Rust implementation is based on the original PeacoQC algorithm and R package. We gratefully acknowledge the original authors:
Original Paper:
Original R Implementation:
https://github.com/saeyslab/PeacoQCThis Rust version provides:
Contributions are welcome! Please feel free to open issues or submit a Pull Request on Github.