#[cfg(feature = "hdf5")]
mod h5ad;
mod mtx;
#[cfg(feature = "hdf5")]
mod tenx_matrix;
#[cfg(feature = "hdf5")]
mod tenx_molecule;
#[cfg(feature = "hdf5")]
pub use h5ad::{from_h5ad, stage_h5ad, H5adImport};
pub use mtx::{from_mtx, stage_mtx, MtxImport};
#[cfg(feature = "hdf5")]
pub use tenx_matrix::{from_10x_matrix, stage_10x_matrix, TenxMatrixImport};
#[cfg(feature = "hdf5")]
pub use tenx_molecule::{from_10x_molecule, stage_10x_molecule, TenxMoleculeImport};
use crate::sparse_io::{open_sparse_matrix_by_path, SparseIoBackend};
use log::info;
#[derive(Clone, Debug)]
pub struct Output {
pub output: Box<str>,
pub backend: SparseIoBackend,
pub zip: bool,
pub squeeze: Option<Squeeze>,
}
impl Output {
pub fn new(output: &str) -> Self {
Self {
output: output.into(),
backend: SparseIoBackend::Zarr,
zip: true,
squeeze: None,
}
}
fn stage(&self) -> anyhow::Result<(Staged, SparseIoBackend)> {
let (effective, backend, working) =
crate::zarr_io::prepare_output(&self.output, self.backend.clone(), self.zip)?;
let squeeze = self.squeeze;
Ok((
Staged {
effective,
working,
squeeze,
},
backend,
))
}
}
#[derive(Clone, Copy, Debug)]
pub struct Squeeze {
pub rows: usize,
pub columns: usize,
pub block_size: Option<usize>,
}
impl Default for Squeeze {
fn default() -> Self {
Self {
rows: 1,
columns: 1,
block_size: None,
}
}
}
impl Squeeze {
pub fn apply(&self, backend_file: &str) -> anyhow::Result<()> {
crate::qc::squeeze_in_place(backend_file, self.rows, self.columns, self.block_size)
}
}
#[derive(Debug)]
#[must_use = "a staged backend is only in place once finished"]
pub struct Staged {
effective: Box<str>,
working: Box<str>,
squeeze: Option<Squeeze>,
}
impl Staged {
pub fn working(&self) -> &str {
&self.working
}
pub fn finish(self) -> anyhow::Result<Box<str>> {
if let Some(squeeze) = &self.squeeze {
squeeze.apply(&self.working)?;
}
let found = crate::zarr_io::finalize_output(&self.working, &self.effective)?;
info!("done");
Ok(found.into())
}
pub fn discard(self) -> anyhow::Result<()> {
remove_build(&self.working)
}
}
pub(crate) fn remove_build(working: &str) -> anyhow::Result<()> {
info!("deleting {working}");
open_sparse_matrix_by_path(working)?.remove_backend_file()?;
crate::zarr_io::leave_stage(working);
Ok(())
}
pub(crate) fn log_feature_type_histogram(label: &str, row_types: &[Box<str>]) {
let mut counts: std::collections::BTreeMap<&str, usize> = std::collections::BTreeMap::new();
for t in row_types {
*counts.entry(t.as_ref()).or_insert(0) += 1;
}
info!("Feature types in {}: {:?}", label, counts);
}
#[cfg(test)]
mod tests;