From 0eda5aaf6dc303c204165f96f8147f053c98e339 Mon Sep 17 00:00:00 2001 From: Ian Date: Thu, 4 Sep 2025 23:09:09 +0000 Subject: [PATCH 1/2] Added test verison in order to be tested in SingleRust --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a1962b..24bf98a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -341,7 +341,7 @@ dependencies = [ [[package]] name = "single-statistics" -version = "0.7.0" +version = "0.8.0-beta" dependencies = [ "anyhow", "approx", diff --git a/Cargo.toml b/Cargo.toml index dbbf221..8e301e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "single-statistics" -version = "0.7.0" +version = "0.8.0-beta" edition = "2024" license-file = "LICENSE.md" readme = "README.md" From d41dad211431a2464a6770058feeff43e301eeb3 Mon Sep 17 00:00:00 2001 From: Ian Date: Thu, 11 Sep 2025 11:19:03 +0000 Subject: [PATCH 2/2] Added documentation to library --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/enrichment/aucell.rs | 105 ------------------------- src/enrichment/mod.rs | 19 +++++ src/lib.rs | 26 ++++++ src/testing/correction/mod.rs | 24 +++++- src/testing/inference/mod.rs | 61 ++++++++++++++ src/testing/inference/nonparametric.rs | 65 +++++++++++++++ src/testing/inference/parametric.rs | 51 ++++++++++++ src/testing/mod.rs | 90 ++++++++++++++++++++- src/testing/utils.rs | 18 ++++- 11 files changed, 348 insertions(+), 115 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24bf98a..4bdd418 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -341,7 +341,7 @@ dependencies = [ [[package]] name = "single-statistics" -version = "0.8.0-beta" +version = "0.8.1" dependencies = [ "anyhow", "approx", diff --git a/Cargo.toml b/Cargo.toml index 8e301e5..dd56e9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "single-statistics" -version = "0.8.0-beta" +version = "0.8.1" edition = "2024" license-file = "LICENSE.md" readme = "README.md" diff --git a/src/enrichment/aucell.rs b/src/enrichment/aucell.rs index 2b8110e..f528ab1 100644 --- a/src/enrichment/aucell.rs +++ b/src/enrichment/aucell.rs @@ -1,107 +1,2 @@ // Following the general implementation presented here, But adapted to nalgebra_sparse and multithreading: https://github.com/scverse/decoupler/blob/main/src/decoupler/mt/_aucell.py -use std::mem::offset_of; - -use nalgebra_sparse::CsrMatrix; -use ndarray::Array2; -use single_utilities::traits::{FloatOps, FloatOpsTS}; - -fn validate_n_up(n_genes: usize, n_up: Option) -> anyhow::Result -where -T: FloatOps { - let n_up_value = match n_up { - Some(val) => { - let n_up_int = num_traits::Float::ceil(val).to_usize().unwrap(); - n_up_int - }, - None => { - let n_up_float = T::from(0.05).unwrap() * T::from(n_genes).unwrap(); - let n_up_ceil = num_traits::Float::ceil(n_up_float); - let n_up_int = n_up_ceil.to_usize().unwrap(); - n_up_int.clamp(2, n_genes) - }, - }; - - if n_up_value <= 1 || n_up_value > n_genes { - return Err(anyhow::anyhow!( - "For n_genes={}, n_up={} must be between 1 and {}", - n_genes, n_up_value, n_genes - )); - } - Ok(n_up_value) -} - -fn get_gene_set( - connectivity: &[usize], - starts: &[usize], - offsets: &[usize], - source_idx: usize -) -> Vec { - let start = starts[source_idx]; - let offset = offsets[source_idx]; - connectivity[start..start + offset].to_vec() -} - -fn rank_data(values: &[T]) -> Vec -where - T: FloatOps - { - let mut indexed_values: Vec<(usize, T)> = values - .iter() - .enumerate() - .map(|(i, &v)| (i,v)) - .collect(); - - indexed_values.sort_by(|a, b| { - b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal) - }); - - let mut ranks = vec![0; values.len()]; - for (rank, (original_idx, _)) in indexed_values.iter().enumerate() { - ranks[*original_idx] = rank + 1; - } - - ranks - } - - - -fn compute_chunk_size(n_cells: usize, n_genes: usize) -> usize { - let n_cores = rayon::current_num_threads(); - - let base_chunk_size = if n_genes > 20000 { - 200 - } else if n_genes > 10000 { - 500 - } else { - 1000 - }; - - let min_chunks = n_cores; - let max_chunk_size = (n_cells + min_chunks - 1) / min_chunks; - base_chunk_size.min(max_chunk_size).max(1) -} - -pub(crate) fn aucell_compute( - matrix: &CsrMatrix, - connectivity: &[usize], - starts: &[usize], - offsets: &[usize], - n_up: Option -) -> anyhow::Result> -where - T: FloatOpsTS { - let n_cells = matrix.nrows(); - let n_genes = matrix.ncols(); - let n_sources = starts.len(); - - if connectivity.is_empty() || starts.is_empty() || offsets.is_empty() { - return Err(anyhow::anyhow!("Connectivity arrays cannot be empty!!")) - } - - if starts.len() != offsets.len() { - return Err(anyhow::anyhow!("Starts and offsets must have the same length!")) - } - - todo!() - } \ No newline at end of file diff --git a/src/enrichment/mod.rs b/src/enrichment/mod.rs index 989f450..6f0882a 100644 --- a/src/enrichment/mod.rs +++ b/src/enrichment/mod.rs @@ -1,3 +1,22 @@ +//! Gene set enrichment analysis methods for single-cell data. +//! +//! This module provides various approaches to gene set enrichment analysis, allowing you to +//! determine whether predefined sets of genes show statistically significant enrichment in +//! your single-cell data. +//! +//! ## Available Methods +//! +//! - **GSEA** (`gsea`): Gene Set Enrichment Analysis using ranking-based approaches +//! - **AUCell** (`aucell`): Area Under the Curve method for gene set activity scoring +//! - **ORA** (`ora`): Over-Representation Analysis using hypergeometric testing +//! +//! ## Quick Example +//! +//! ```rust,no_run +//! // Gene set enrichment analysis workflow would go here +//! // (Implementation depends on the specific modules) +//! ``` + mod gsea; mod aucell; mod ora; \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 6b164c5..0c727c1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,28 @@ +//! # single-statistics +//! +//! A specialized Rust library for statistical analysis of single-cell data, part of the single-rust ecosystem. +//! +//! This crate provides robust statistical methods for biological analysis of single-cell data, focusing on +//! differential expression analysis, marker gene identification, and related statistical tests. It is optimized +//! for sparse single-cell matrices and provides both parametric and non-parametric statistical tests. +//! +//! ## Core Features +//! +//! - **Differential Expression Analysis**: T-tests, Mann-Whitney U tests, and other statistical methods +//! - **Multiple Testing Correction**: FDR, Bonferroni, and other correction methods +//! - **Effect Size Calculations**: Cohen's d and other effect size measures +//! - **Sparse Matrix Support**: Optimized for `CsrMatrix` from nalgebra-sparse +//! +//! ## Quick Start +//! +//! Use the `MatrixStatTests` trait to perform differential expression analysis on sparse matrices. +//! The library supports various statistical tests including t-tests and Mann-Whitney U tests, +//! with automatic multiple testing correction. +//! +//! ## Module Organization +//! +//! - **[`testing`]**: Statistical tests, hypothesis testing, and multiple testing correction +//! - **[`enrichment`]**: Gene set enrichment analysis methods (GSEA, ORA, AUCell) + pub mod testing; pub mod enrichment; \ No newline at end of file diff --git a/src/testing/correction/mod.rs b/src/testing/correction/mod.rs index 18d71fd..84413a4 100644 --- a/src/testing/correction/mod.rs +++ b/src/testing/correction/mod.rs @@ -1,10 +1,28 @@ +//! Multiple testing correction methods for controlling false positives in differential expression analysis. +//! +//! When testing thousands of genes simultaneously (as is common in single-cell RNA-seq analysis), +//! the probability of false positives increases dramatically. These correction methods help control +//! either the Family-Wise Error Rate (FWER) or False Discovery Rate (FDR). +//! +//! ## Available Methods +//! +//! - **Bonferroni**: Conservative FWER control, multiplies p-values by number of tests +//! - **Benjamini-Hochberg**: FDR control, less conservative than Bonferroni +//! - **Benjamini-Yekutieli**: FDR control for dependent tests +//! - **Holm-Bonferroni**: Step-down FWER control, less conservative than Bonferroni +//! - **Storey's q-value**: Improved FDR estimation +//! +//! ## Choosing a Method +//! +//! - **For single-cell DE analysis**: Use Benjamini-Hochberg (most common) +//! - **For very strict control**: Use Bonferroni or Holm-Bonferroni +//! - **For dependent tests**: Use Benjamini-Yekutieli +//! - **For large datasets**: Consider Storey's q-value + use anyhow::{Result, anyhow}; use single_utilities::traits::FloatOps; use std::cmp::Ordering; -/// Multiple testing correction methods to control for false positives -/// when performing many statistical tests simultaneously. - /// Apply Bonferroni correction to p-values /// /// Bonferroni correction is a simple but conservative method that multiplies diff --git a/src/testing/inference/mod.rs b/src/testing/inference/mod.rs index 3b7ea8d..c35a2d1 100644 --- a/src/testing/inference/mod.rs +++ b/src/testing/inference/mod.rs @@ -11,10 +11,40 @@ pub mod parametric; pub mod nonparametric; +/// Statistical testing methods for sparse matrices, particularly suited for single-cell data. +/// +/// This trait extends sparse matrix types (like `CsrMatrix`) with statistical testing capabilities. +/// It provides methods for differential expression analysis and other statistical comparisons +/// optimized for single-cell RNA-seq data. +/// +/// # Matrix Format +/// +/// The expected matrix format is **genes × cells** (features × observations), where: +/// - Rows represent genes/features +/// - Columns represent cells/observations +/// - Values represent expression levels (normalized counts, log-transformed, etc.) +/// + pub trait MatrixStatTests where T: FloatOpsTS, { + /// Perform t-tests comparing two groups of cells for all genes. + /// + /// Runs Student's or Welch's t-test for each gene (row) in the matrix, comparing + /// expression levels between the specified groups of cells (columns). + /// + /// # Arguments + /// + /// * `group1_indices` - Column indices for the first group of cells + /// * `group2_indices` - Column indices for the second group of cells + /// * `test_type` - Type of t-test (`Student` or `Welch`) + /// + /// # Returns + /// + /// Vector of `TestResult` objects, one per gene, containing test statistics and p-values. + /// + fn t_test( &self, group1_indices: &[usize], @@ -22,6 +52,20 @@ where test_type: TTestType, ) -> anyhow::Result>>; + /// Perform Mann-Whitney U tests comparing two groups of cells for all genes. + /// + /// Runs non-parametric Mann-Whitney U (Wilcoxon rank-sum) tests for each gene, + /// comparing the distributions between the specified groups. + /// + /// # Arguments + /// + /// * `group1_indices` - Column indices for the first group of cells + /// * `group2_indices` - Column indices for the second group of cells + /// * `alternative` - Type of alternative hypothesis (two-sided, less, greater) + /// + /// # Returns + /// + /// Vector of `TestResult` objects containing U statistics and p-values. fn mann_whitney_test( &self, group1_indices: &[usize], @@ -29,6 +73,23 @@ where alternative: Alternative, ) -> anyhow::Result>>; + /// Comprehensive differential expression analysis with multiple testing correction. + /// + /// This is the main method for differential expression analysis. It performs the + /// specified statistical test on all genes and applies multiple testing correction + /// to control the false discovery rate. + /// + /// # Arguments + /// + /// * `group_ids` - Vector assigning each cell to a group (currently supports 2 groups) + /// * `test_method` - Statistical test to perform + /// + /// # Returns + /// + /// `MultipleTestResults` containing statistics, p-values, adjusted p-values, and + /// metadata for all genes. + /// + fn differential_expression( &self, group_ids: &[usize], diff --git a/src/testing/inference/nonparametric.rs b/src/testing/inference/nonparametric.rs index 19dd3ef..f545443 100644 --- a/src/testing/inference/nonparametric.rs +++ b/src/testing/inference/nonparametric.rs @@ -1,3 +1,12 @@ +//! Non-parametric statistical tests for single-cell data analysis. +//! +//! This module implements non-parametric statistical tests that make fewer assumptions about +//! data distribution. These tests are particularly useful for single-cell data which often +//! exhibits non-normal distributions, high sparsity, and outliers. +//! +//! The primary test implemented is the Mann-Whitney U test (also known as the Wilcoxon +//! rank-sum test), which compares the distributions of two groups without assuming normality. + use std::{cmp::Ordering, f64}; use nalgebra_sparse::CsrMatrix; @@ -13,6 +22,34 @@ struct TieInfo { tie_correction: f64, } +/// Perform Mann-Whitney U tests on all genes comparing two groups of cells. +/// +/// This function efficiently computes Mann-Whitney U statistics for all genes in a sparse +/// matrix, comparing expression distributions between two groups of cells. The implementation +/// uses parallel processing for improved performance on large datasets. +/// +/// # Arguments +/// +/// * `matrix` - Sparse expression matrix (genes × cells) +/// * `group1_indices` - Column indices for the first group of cells +/// * `group2_indices` - Column indices for the second group of cells +/// * `alternative` - Type of alternative hypothesis (two-sided, less, greater) +/// +/// # Returns +/// +/// Vector of `TestResult` objects containing U statistics and p-values for each gene. +/// let group1 = vec![0, 1, 2]; // First group of cells +/// let group2 = vec![3, 4, 5]; // Second group of cells +/// +/// let results = mann_whitney_matrix_groups( +/// &matrix, +/// &group1, +/// &group2, +/// Alternative::TwoSided +/// )?; +/// # Ok(()) +/// # } +/// ``` pub fn mann_whitney_matrix_groups( matrix: &CsrMatrix, group1_indices: &[usize], @@ -48,6 +85,34 @@ where Ok(results) } +/// Perform an optimized Mann-Whitney U test on two samples. +/// +/// This function computes the Mann-Whitney U statistic and p-value for comparing two +/// independent samples. It handles ties correctly and supports different alternative +/// hypotheses. +/// +/// # Arguments +/// +/// * `x` - First sample +/// * `y` - Second sample +/// * `alternative` - Type of alternative hypothesis +/// +/// # Returns +/// +/// `TestResult` containing the U statistic and p-value. +/// +/// # Example +/// +/// ```rust +/// use single_statistics::testing::inference::nonparametric::mann_whitney_optimized; +/// use single_statistics::testing::Alternative; +/// +/// let group1 = vec![1.0, 2.0, 3.0]; +/// let group2 = vec![4.0, 5.0, 6.0]; +/// let result = mann_whitney_optimized(&group1, &group2, Alternative::TwoSided); +/// +/// println!("U statistic: {}, p-value: {}", result.statistic, result.p_value); +/// ``` pub fn mann_whitney_optimized(x: &[f64], y: &[f64], alternative: Alternative) -> TestResult { let nx = x.len(); let ny = y.len(); diff --git a/src/testing/inference/parametric.rs b/src/testing/inference/parametric.rs index ed5b8c4..f428ef0 100644 --- a/src/testing/inference/parametric.rs +++ b/src/testing/inference/parametric.rs @@ -1,9 +1,30 @@ +//! Parametric statistical tests for single-cell data analysis. +//! +//! This module implements parametric statistical tests, primarily t-tests, optimized for +//! sparse single-cell expression matrices. The implementations are designed for efficiency +//! when testing thousands of genes across different cell groups. + use crate::testing::utils::accumulate_gene_statistics_two_groups; use crate::testing::{TTestType, TestResult}; use nalgebra_sparse::CsrMatrix; use single_utilities::traits::{FloatOps, FloatOpsTS}; use statrs::distribution::{ContinuousCDF, StudentsT}; +/// Perform t-tests on all genes comparing two groups of cells. +/// +/// This is an optimized implementation that efficiently computes summary statistics +/// for sparse matrices and performs t-tests for each gene. +/// +/// # Arguments +/// +/// * `matrix` - Sparse expression matrix (genes × cells) +/// * `group1_indices` - Column indices for the first group of cells +/// * `group2_indices` - Column indices for the second group of cells +/// * `test_type` - Type of t-test to perform (Student's or Welch's) +/// +/// # Returns +/// +/// Vector of `TestResult` objects, one per gene, containing t-statistics and p-values. pub fn t_test_matrix_groups( matrix: &CsrMatrix, group1_indices: &[usize], @@ -39,6 +60,20 @@ where Ok(results) } +/// Perform a t-test comparing two samples. +/// +/// This function performs either Student's t-test (assuming equal variances) or +/// Welch's t-test (allowing unequal variances) on two samples. +/// +/// # Arguments +/// +/// * `x` - First sample +/// * `y` - Second sample +/// * `test_type` - Type of t-test to perform +/// +/// # Returns +/// +/// `TestResult` containing the t-statistic and p-value. pub fn t_test(x: &[T], y: &[T], test_type: TTestType) -> TestResult where T: FloatOps, @@ -136,6 +171,22 @@ where ) } +/// Perform a t-test using precomputed summary statistics. +/// +/// This is an optimized function that computes t-tests directly from sum and sum-of-squares, +/// avoiding the need to store or iterate through the original data. Particularly useful for +/// sparse matrix operations where computing these statistics is done efficiently during +/// matrix traversal. +/// +/// # Arguments +/// +/// * `sum1`, `sum_sq1`, `n1` - Sum, sum of squares, and count for group 1 +/// * `sum2`, `sum_sq2`, `n2` - Sum, sum of squares, and count for group 2 +/// * `test_type` - Type of t-test to perform (Student's or Welch's) +/// +/// # Returns +/// +/// `TestResult` containing the t-statistic and p-value. pub fn fast_t_test_from_sums( sum1: f64, sum_sq1: f64, diff --git a/src/testing/mod.rs b/src/testing/mod.rs index 3962acd..8887a00 100644 --- a/src/testing/mod.rs +++ b/src/testing/mod.rs @@ -1,3 +1,27 @@ +//! Statistical testing framework for single-cell data analysis. +//! +//! This module provides a comprehensive suite of statistical tests and methods specifically designed +//! for single-cell RNA-seq data analysis. It includes parametric and non-parametric tests, multiple +//! testing correction methods, and effect size calculations. +//! +//! ## Key Components +//! +//! - **Core Data Structures**: [`TestResult`] and [`MultipleTestResults`] for storing test outcomes +//! - **Test Methods**: [`TestMethod`] enum defining available statistical tests +//! - **Matrix Operations**: [`MatrixStatTests`] trait for running tests on sparse matrices +//! +//! ## Submodules +//! +//! - [`correction`]: Multiple testing correction methods (FDR, Bonferroni, etc.) +//! - [`effect`]: Effect size calculations (Cohen's d, etc.) +//! - [`inference`]: Core statistical inference implementations +//! - [`utils`]: Utility functions for data preparation and validation +//! +//! ## Usage +//! +//! Use the `MatrixStatTests` trait on sparse matrices to perform differential expression +//! analysis with various statistical methods and automatic multiple testing correction. + use single_utilities::traits::FloatOps; use std::collections::HashMap; @@ -7,27 +31,78 @@ pub mod inference; pub mod utils; +/// Statistical test methods available for differential expression analysis. +/// +/// This enum defines the different statistical tests that can be applied to single-cell data. +/// Each method has specific assumptions and use cases. #[derive(Debug, Clone, Copy)] pub enum TestMethod { + /// Student's or Welch's t-test for comparing means between two groups. + /// + /// **Use when**: Data is approximately normal, comparing continuous expression values. + /// **Best for**: Most differential expression analyses in single-cell data. TTest(TTestType), + + /// Mann-Whitney U test (Wilcoxon rank-sum test) for non-parametric comparison. + /// + /// **Use when**: Data is not normally distributed, or you want a robust rank-based test. + /// **Best for**: Highly skewed expression data or small sample sizes. MannWhitney, + + /// Negative binomial test for count data with overdispersion. + /// + /// **Use when**: Working with raw UMI counts and modeling overdispersion. + /// **Best for**: Count-based differential expression (like DESeq2/edgeR approach). NegativeBinomial, + + /// Zero-inflated models for data with excess zeros. + /// + /// **Use when**: High proportion of zero values (dropout) needs explicit modeling. + /// **Best for**: Single-cell data with significant technical dropout. ZeroInflated, } +/// Type of t-test to perform, differing in variance assumptions. #[derive(Debug, Clone, Copy)] pub enum TTestType { - Student, // Equal variance - Welch, // Unequal variance + /// Student's t-test assuming equal variances between groups. + /// + /// **Use when**: Groups have similar variance (homoscedasticity). + /// **Faster** but less robust than Welch's t-test. + Student, + + /// Welch's t-test allowing unequal variances between groups. + /// + /// **Use when**: Groups may have different variances (heteroscedasticity). + /// **Recommended** for most single-cell analyses as the default choice. + Welch, } +/// Alternative hypothesis for statistical tests. #[derive(Debug, Clone, Copy)] pub enum Alternative { + /// Two-sided test: group means are not equal (μ₁ ≠ μ₂). + /// + /// **Most common** choice for differential expression analysis. TwoSided, + + /// One-sided test: group 1 mean is less than group 2 (μ₁ < μ₂). + /// + /// **Use when**: You specifically want to test for downregulation. Less, + + /// One-sided test: group 1 mean is greater than group 2 (μ₁ > μ₂). + /// + /// **Use when**: You specifically want to test for upregulation. Greater, } +/// Result of a single statistical test. +/// +/// Contains the test statistic, p-value, and optional additional information like effect sizes +/// and confidence intervals. This structure is used for individual gene/feature tests. +/// + #[derive(Debug, Clone)] pub struct TestResult { /// The test statistic value (e.g., t-statistic, U statistic) @@ -36,9 +111,9 @@ pub struct TestResult { pub p_value: T, /// Confidence interval for the effect size/difference (if available) pub confidence_interval: Option<(T, T)>, - /// Degrees of freedom (for parametric inference) + /// Degrees of freedom (for parametric tests) pub degrees_of_freedom: Option, - /// Effect size measurement + /// Effect size measurement (Cohen's d, etc.) pub effect_size: Option, /// Standard error of the effect size or test statistic pub standard_error: Option, @@ -106,6 +181,13 @@ where } } +/// Results from multiple statistical tests, typically for differential expression analysis. +/// +/// This structure contains results from testing multiple features (genes) simultaneously, +/// including multiple testing correction. It's the primary output of differential expression +/// analysis workflows. +/// + #[derive(Debug, Clone)] pub struct MultipleTestResults { /// Test statistics for each feature/gene diff --git a/src/testing/utils.rs b/src/testing/utils.rs index 700c5b1..c85cc1a 100644 --- a/src/testing/utils.rs +++ b/src/testing/utils.rs @@ -1,6 +1,11 @@ +//! Utility functions for statistical testing operations. + use nalgebra_sparse::CsrMatrix; use single_utilities::traits::FloatOpsTS; +/// Extract unique group identifiers from a group assignment vector. +/// +/// Returns a sorted vector of unique group IDs, removing duplicates. pub fn extract_unique_groups(group_ids: &[usize]) -> Vec { let mut unique_groups = group_ids.to_vec(); unique_groups.sort(); @@ -8,7 +13,10 @@ pub fn extract_unique_groups(group_ids: &[usize]) -> Vec { unique_groups } -/// Get indices for each group +/// Extract indices of cells belonging to each of the two groups. +/// +/// Returns a tuple of (group1_indices, group2_indices) where each vector contains +/// the row/column indices of cells belonging to that group. pub fn get_group_indices(group_ids: &[usize], unique_groups: &[usize]) -> (Vec, Vec) { let group1 = unique_groups[0]; let group2 = unique_groups[1]; @@ -26,6 +34,14 @@ pub fn get_group_indices(group_ids: &[usize], unique_groups: &[usize]) -> (Vec( matrix: &CsrMatrix, group1_indices: &[usize],