MCPcopy Index your code
hub / github.com/SingleRust/SingleRust / subset_genes

Function subset_genes

src/memory/processing/hvg/mod.rs:404–466  ·  view source on GitHub ↗

Select highly variable genes based on dispersion scores and expression filters. Final step of HVG detection that applies thresholds to identify the most biologically relevant genes. Supports both top-N selection and threshold-based selection. ## Parameters `log_means` - Log-transformed mean expression values `dispersion_norm` - Normalized dispersion scores `n_top_genes` - Optional: select this m

(
    log_means: &[f64], // These are already log-transformed
    dispersion_norm: &[f64],
    n_top_genes: Option<usize>,
    min_mean: f64,
    max_mean: f64,
    min_dispersion: f64,
)

Source from the content-addressed store, hash-verified

402/// - Otherwise: Apply all threshold filters (mean and dispersion)
403/// - Genes with NaN dispersions are handled appropriately for each mode
404fn subset_genes(
405 log_means: &[f64], // These are already log-transformed
406 dispersion_norm: &[f64],
407 n_top_genes: Option<usize>,
408 min_mean: f64,
409 max_mean: f64,
410 min_dispersion: f64,
411) -> anyhow::Result<Vec<bool>> {
412 let mut highly_variable = vec![false; log_means.len()];
413
414 if let Some(n_top) = n_top_genes {
415 // Python's approach for n_top_genes:
416 // 1. First, remove NaN values to compute threshold
417 let non_nan_dispersions: Vec<f64> = dispersion_norm
418 .iter()
419 .filter(|&&d| !d.is_nan())
420 .copied()
421 .collect();
422
423 if non_nan_dispersions.is_empty() {
424 return Ok(highly_variable);
425 }
426
427 // Find the nth highest value
428 let n_to_select = n_top.min(non_nan_dispersions.len());
429 let mut sorted_dispersions = non_nan_dispersions.clone();
430 sorted_dispersions.sort_by(|a, b| b.partial_cmp(a).unwrap_or(std::cmp::Ordering::Equal));
431
432 let threshold = sorted_dispersions[n_to_select - 1];
433
434 // 2. Now apply threshold to nan_to_num version (NaN → -inf)
435 for i in 0..dispersion_norm.len() {
436 let disp_value = if dispersion_norm[i].is_nan() {
437 f64::NEG_INFINITY // Python uses -inf for NaN in final selection
438 } else {
439 dispersion_norm[i]
440 };
441
442 if disp_value >= threshold {
443 highly_variable[i] = true;
444 }
445 }
446 } else {
447 // Original cutoff-based selection
448 // Python applies nan_to_num (NaN → 0) before checking bounds
449 let clean_dispersions: Vec<f64> = dispersion_norm
450 .iter()
451 .map(|&d| if d.is_nan() { 0.0 } else { d })
452 .collect();
453
454 // Apply mean filters
455 let valid_by_mean: Vec<bool> = log_means
456 .iter()
457 .map(|&log_mean| log_mean > min_mean && log_mean < max_mean)
458 .collect();
459
460 for i in 0..log_means.len() {
461 highly_variable[i] = valid_by_mean[i] && clean_dispersions[i] > min_dispersion;

Callers 1

compute_seurat_hvgFunction · 0.85

Calls 1

cloneMethod · 0.80

Tested by

no test coverage detected