use indexmap::IndexSet;
use std::time::Instant;
use crate::methods::nmf_hals::nmf_preprocessing::*;
use crate::methods::nmf_hals::sparse::*;
use crate::methods::nmf_hals::*;
use crate::prelude::*;
use crate::single_cell::sc_data::data_io::from_gene_chunks;
pub fn nmf_single_run_sparse<T>(
data: CompressedSparseData2<T>,
k: usize,
preprocessing: &str,
use_second_layer: bool,
nmf_hals_params: Option<HalsOpts<T>>,
verbose: usize,
) -> Result<NmfResult<T>, BixverseErrors>
where
T: BixverseFloat + BixverseNumeric + std::iter::Sum<T> + BixverseSimd,
{
let nmf_preprocessing = parse_nmf_processing(preprocessing).unwrap_or_else(|| {
println!(
"Unknown string provided: {:?}. Using the default (No additional pre-processing)",
preprocessing
);
NmfPreprocessing::default()
});
let hals_opt = nmf_hals_params.unwrap_or_default();
let data_processed = nmf_process_sparse(&data, &nmf_preprocessing, use_second_layer)?;
let nmf_input: SparseInput<T, T> = if use_second_layer {
SparseInput::from_secondary(&data_processed)
} else {
SparseInput::from_primary(&data_processed)
}?;
let nmf_res = nmf_hals(&nmf_input, k, &hals_opt, verbose)?;
Ok(nmf_res)
}
#[allow(clippy::too_many_arguments)]
pub fn nmf_multiple_run_sparse<T>(
data: CompressedSparseData2<T>,
k: usize,
preprocessing: &str,
use_second_layer: bool,
nmf_hals_params: Option<HalsOpts<T>>,
n_runs: usize,
base_seed: usize,
verbose: usize,
) -> Result<StabilisedNmfResult<T>, BixverseErrors>
where
T: BixverseFloat + BixverseNumeric + std::iter::Sum<T> + BixverseSimd,
{
let nmf_preprocessing = parse_nmf_processing(preprocessing).unwrap_or_else(|| {
println!(
"Unknown string provided: {:?}. Using the default (No additional pre-processing)",
preprocessing
);
NmfPreprocessing::default()
});
let hals_opt = nmf_hals_params.unwrap_or_default();
let data_processed = nmf_process_sparse(&data, &nmf_preprocessing, use_second_layer)?;
let nmf_input: SparseInput<T, T> = if use_second_layer {
SparseInput::from_secondary(&data_processed)
} else {
SparseInput::from_primary(&data_processed)
}?;
let res = stabilised_nmf(&nmf_input, k, n_runs, base_seed as u64, &hals_opt, verbose)?;
Ok(res)
}
#[allow(clippy::too_many_arguments)]
pub fn nmf_single_run_sc(
f_path: &str,
gene_indices: &[usize],
cell_indices: &[usize],
k: usize,
preprocessing: &str,
use_second_layer: bool,
nmf_hals_params: Option<HalsOpts<f32>>,
verbose: usize,
) -> Result<NmfResult<f32>, BixverseErrors> {
let verbosity = parse_verbosity_level(verbose);
let n_cells = cell_indices.len();
let cell_set: IndexSet<u32> = cell_indices.iter().map(|&x| x as u32).collect();
let start_total = Instant::now();
if verbosity.normal_verbosity() {
println!("NMF: Loading data from disk ...")
}
let layer = if use_second_layer {
DataLayerReturn::Norm
} else {
DataLayerReturn::Raw
};
let reader = ParallelSparseReader::new(f_path)?;
let gene_chunks: Vec<CscGeneChunk> =
reader.read_gene_parallel_filtered(gene_indices, &cell_set)?;
let csc: CompressedSparseData2<f32> = from_gene_chunks::<f32>(gene_chunks, &layer, n_cells);
if verbosity.normal_verbosity() {
println!(" ... done in {:.2?}", start_total.elapsed())
}
if verbosity.normal_verbosity() {
println!("NMF: Running NMF for single cells ...")
}
let res = nmf_single_run_sparse(
csc,
k,
preprocessing,
use_second_layer,
nmf_hals_params,
verbose,
)?;
if verbosity.normal_verbosity() {
println!(" ... done in {:.2?}", start_total.elapsed())
}
Ok(res)
}
#[allow(clippy::too_many_arguments)]
pub fn nmf_multiple_run_sc(
f_path: &str,
gene_indices: &[usize],
cell_indices: &[usize],
k: usize,
preprocessing: &str,
use_second_layer: bool,
nmf_hals_params: Option<HalsOpts<f32>>,
n_runs: usize,
base_seed: usize,
verbose: usize,
) -> Result<StabilisedNmfResult<f32>, BixverseErrors> {
let verbosity = parse_verbosity_level(verbose);
let n_cells = cell_indices.len();
let cell_set: IndexSet<u32> = cell_indices.iter().map(|&x| x as u32).collect();
let start_total = Instant::now();
if verbosity.normal_verbosity() {
println!("NMF: Loading data from disk ...")
}
let layer = if use_second_layer {
DataLayerReturn::Norm
} else {
DataLayerReturn::Raw
};
let reader = ParallelSparseReader::new(f_path)?;
let gene_chunks: Vec<CscGeneChunk> =
reader.read_gene_parallel_filtered(gene_indices, &cell_set)?;
let csc: CompressedSparseData2<f32> = from_gene_chunks::<f32>(gene_chunks, &layer, n_cells);
if verbosity.normal_verbosity() {
println!(" ... done in {:.2?}", start_total.elapsed())
}
if verbosity.normal_verbosity() {
println!("NMF: Running multiple NMF runs for single cells ...")
}
let res = nmf_multiple_run_sparse(
csc,
k,
preprocessing,
use_second_layer,
nmf_hals_params,
n_runs,
base_seed,
verbose,
)?;
if verbosity.normal_verbosity() {
println!(" ... done in {:.2?}", start_total.elapsed())
}
Ok(res)
}