- implement shape in Rust

- implement more readers
- fix downloading of bioformats jar
- (mostly) compatible with python version
This commit is contained in:
w.pomp
2026-07-13 13:40:34 +02:00
parent 705ca16379
commit ff7cd562af
36 changed files with 7946 additions and 2843 deletions
+94
View File
@@ -0,0 +1,94 @@
use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf};
use std::sync::{LazyLock, RwLock};
use indexmap::{Equivalent, IndexMap};
use ndarray::IxDyn;
use crate::error::Error;
use crate::readers::ArrayT;
static CACHE: LazyLock<RwLock<IndexMap<ViewHash, ArrayT<IxDyn>>>> =
LazyLock::new(|| RwLock::new(IndexMap::new()));
#[derive(Debug, Clone, Eq, PartialEq)]
struct ViewHash {
reader: String,
path: PathBuf,
series: usize,
position: usize,
c: isize,
z: isize,
t: isize,
}
impl Hash for ViewHash {
fn hash<H: Hasher>(&self, state: &mut H) {
self.reader.as_str().hash(state);
self.path.as_path().hash(state);
self.series.hash(state);
self.position.hash(state);
self.c.hash(state);
self.z.hash(state);
self.t.hash(state);
}
}
impl ViewHash {
fn new(reader: String, path: PathBuf, series: usize, position: usize, c: isize, z: isize, t: isize) -> Self {
Self { reader, path, series, position, c, z, t }
}
}
struct ViewEquiv<'a> {
reader: &'a str,
path: &'a Path,
series: usize,
position: usize,
c: isize,
z: isize,
t: isize,
}
impl Hash for ViewEquiv<'_> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.reader.hash(state);
self.path.hash(state);
self.series.hash(state);
self.position.hash(state);
self.c.hash(state);
self.z.hash(state);
self.t.hash(state);
}
}
impl<'a> ViewEquiv<'a> {
fn new(reader: &'a str, path: &'a Path, series: usize, position: usize, c: isize, z: isize, t: isize) -> ViewEquiv<'a> {
Self { reader, path, series, position, c, z, t }
}
}
impl Equivalent<ViewEquiv<'_>> for ViewHash {
fn equivalent(&self, key: &ViewEquiv) -> bool {
(self.reader == key.reader) && (self.path == key.path) && (self.series == key.series) && (self.position == key.position) && (self.c == key.c) && (self.z == key.z) && (self.t == key.t)
}
}
impl Equivalent<ViewHash> for ViewEquiv<'_> {
fn equivalent(&self, key: &ViewHash) -> bool {
key.equivalent(self)
}
}
pub fn cache_get_or_insert(f: &dyn Fn() -> ArrayT<IxDyn>, reader: &str, path: &Path, series: usize, position: usize, c: isize, z: isize, t: isize) -> Result<ArrayT<IxDyn>, Error> {
if let Some(frame) = CACHE.read().unwrap().get(&ViewEquiv::new(reader, path, series, position, c, z, t)) {
Ok(frame.clone())
} else {
let a = f();
let mut cache = CACHE.write().unwrap();
cache.insert(ViewHash::new(reader.to_string(), path.to_path_buf(), series, position, c, z, t), a.clone());
// TODO: find an IndexMapDeque to pop efficiently at the other end
while cache.len() > 1024 {
cache.pop();
}
Ok(a)
}
}