Skip to main content

Quickstart 🚀

This guide will walk you through a simple example of using SingleRust to analyze single-cell data.

Requirements & Installation​

We assume here you've already installed all necessary libraries and dependencies mentioned in the Requirements page and followed the installation instructions detailed on the Installation page.

Loading Data​

SingleRust supports loading data from H5AD files, which is the standard file format used by the Python package AnnData.

use single_rust::io::{read_h5ad_memory, FileScope};
use anyhow::Result;

fn main() -> Result<()> {
// Load a dataset into memory
let adata = read_h5ad_memory("path/to/your/data.h5ad")?;

// Print dataset dimensions
println!("Dataset dimensions: {} cells x {} genes", adata.n_obs(), adata.n_vars());

Ok(())
}

Basic Preprocessing​

SingleRust provides functions for common preprocessing steps in single-cell analysis.

Filtering Cells and Genes​

use single_rust::memory::processing::filtering::{mark_filter_cells, mark_filter_genes};

// Filter cells based on gene counts and UMI counts
let cell_filter = mark_filter_cells::<u32, f64>(
&adata,
Some(200), // min_genes: keep cells with at least 200 genes
Some(5000), // max_genes: remove cells with more than 5000 genes
Some(500.0), // min_counts: keep cells with at least 500 UMIs
None, // max_counts: no upper limit
None, // min_fraction: no minimum fraction
None, // max_fraction: no maximum fraction
)?;

// Filter genes based on cell counts
let gene_filter = mark_filter_genes::<u32, f64>(
&adata,
Some(10), // min_cells: keep genes expressed in at least 10 cells
None, // max_cells: no upper limit
None, // min_counts: no minimum counts
None, // max_counts: no maximum counts
None, // min_fraction: no minimum fraction
None, // max_fraction: no maximum fraction
)?;

Normalization​

use single_rust::memory::processing::normalize_expression;
use single_rust::Direction;
use single_rust::shared::Precision;

// Normalize expression by cell (row-wise) to a target sum of 10,000
normalize_expression(
&adata.x(),
10000, // target sum for each cell
&Direction::ROW, // normalize across rows (cells)
Some(Precision::Single), // use single precision (f32)
)?;

// Log-transform the data
use single_rust::memory::processing::log1p_expression;

log1p_expression(&adata.x(), Some(Precision::Single))?;

Finding Highly Variable Genes​

use single_rust::memory::processing::compute_highly_variable_genes;
use single_rust::shared::processing::{HVGParams, FlavorType};

// Find highly variable genes using the Seurat method
let hvg_params = HVGParams {
min_mean: 0.0125,
max_mean: 3.0,
min_dispersion: 0.5,
max_dispersion: f64::INFINITY,
n_bins: 20,
n_top_genes: Some(2000), // Select top 2000 genes
flavor: FlavorType::Seurat,
span: 0.3,
batch_key: None,
};

compute_highly_variable_genes(&adata, Some(hvg_params))?;

Complete Example​

Here's a complete example that loads a dataset, preprocesses it, and generates a PCA plot:

use single_rust::io::read_h5ad_memory;
use single_rust::memory::processing::{
filtering::{mark_filter_cells, mark_filter_genes},
normalize_expression, log1p_expression, compute_highly_variable_genes
};
use single_rust::memory::plot::plot_pca;
use single_rust::{Direction, PcaPlotSettings};
use single_rust::shared::Precision;
use single_rust::shared::processing::{HVGParams, FlavorType};
use plotters::style::RGBAColor;
use anyhow::Result;

fn main() -> Result<()> {
// Load dataset
let adata = read_h5ad_memory("data/sample.h5ad")?;
println!("Dataset dimensions: {} cells x {} genes", adata.n_obs(), adata.n_vars());

// Filter cells and genes
let _cell_filter = mark_filter_cells::<u32, f64>(
&adata, Some(200), Some(5000), Some(500.0), None, None, None
)?;

let _gene_filter = mark_filter_genes::<u32, f64>(
&adata, Some(10), None, None, None, None, None
)?;

// Normalize and log-transform
normalize_expression(&adata.x(), 10000, &Direction::ROW, Some(Precision::Single))?;
log1p_expression(&adata.x(), Some(Precision::Single))?;

// Find highly variable genes
let hvg_params = HVGParams {
n_top_genes: Some(2000),
flavor: FlavorType::Seurat,
..Default::default()
};

compute_highly_variable_genes(&adata, Some(hvg_params))?;

println!("Analysis completed successfully!");
Ok(())
}

What's Next?​

Now that you're familiar with the basics of SingleRust, check out the Tutorials for more in-depth examples and the API Reference for detailed API documentation.