- improve Imread slicing
- can_open function for Reader trait
This commit is contained in:
1 parent
f0404d0419
commit
3e33fe18c1
13 files changed
+735
-191
No files matched your search
@@ -52,6 +52,8 @@ class Flags:
|
||||
def __new__(cls) -> Flags: ...
|
||||
def __getnewargs__(self) -> None: ...
|
||||
def __getitem__(self, item: builtins.str) -> builtins.bool: ...
|
||||
def __str__(self) -> builtins.str: ...
|
||||
def __repr__(self) -> builtins.str: ...
|
||||
|
||||
class Imread:
|
||||
r"""
|
||||
@@ -211,6 +213,16 @@ class Imread:
|
||||
the name of the tube lens
|
||||
"""
|
||||
@property
|
||||
def channel_names(self) -> builtins.dict[builtins.int, builtins.str]:
|
||||
r"""
|
||||
names of the channels in order
|
||||
"""
|
||||
@property
|
||||
def summary(self) -> builtins.str:
|
||||
r"""
|
||||
gives a helpful summary of the recorded experiment
|
||||
"""
|
||||
@property
|
||||
def interpolation_order(self) -> typing.Optional[builtins.int]:
|
||||
r"""
|
||||
the bspline order used for interpolation when using transforms
|
||||
@@ -293,7 +305,9 @@ class Imread:
|
||||
r"""
|
||||
reshape the view with a new axis order
|
||||
"""
|
||||
def squeeze(self) -> numpy.ndarray | int | float: ...
|
||||
def squeeze(
|
||||
self, axes: str | typing.Sequence[int | str] = None
|
||||
) -> Imread | float | int: ...
|
||||
def close(self) -> None:
|
||||
r"""
|
||||
close the file: does nothing as this is handled automatically
|
||||
@@ -306,7 +320,19 @@ class Imread:
|
||||
r"""
|
||||
change the data type of the view: (u)int(8/16/32) or float(32/64)
|
||||
"""
|
||||
def __getitem__(self, n: typing.Any) -> typing.Any:
|
||||
def __call__(
|
||||
self,
|
||||
c: typing.Optional[int | slice | numpy.ArrayLike] = None,
|
||||
z: typing.Optional[int | slice | numpy.ArrayLike] = None,
|
||||
t: typing.Optional[int | slice | numpy.ArrayLike] = None,
|
||||
y: typing.Optional[int | slice | numpy.ArrayLike] = None,
|
||||
x: typing.Optional[int | slice | numpy.ArrayLike] = None,
|
||||
) -> typing.Optional[int | Imread]:
|
||||
r"""
|
||||
same as im[] but allowing keyword axes, but slices need to made with slice()
|
||||
also, no ellipsis or new axes
|
||||
"""
|
||||
def __getitem__(self, n: typing.Any) -> typing.Optional[int | Imread]:
|
||||
r"""
|
||||
slice the view and return a new view or a single number
|
||||
"""
|
||||
@@ -314,7 +340,7 @@ class Imread:
|
||||
self,
|
||||
dtype: typing.Optional[numpy.typing.DTypeLike] = None,
|
||||
copy: typing.Optional[builtins.bool] = None,
|
||||
) -> typing.Any:
|
||||
) -> numpy.typing.NDArray:
|
||||
r"""
|
||||
convert to a numpy array, optionally with a different dtype
|
||||
"""
|
||||
@@ -322,139 +348,199 @@ class Imread:
|
||||
r"""
|
||||
check if an item is contained in the view (not implemented)
|
||||
"""
|
||||
def __lt__(self, other: typing.Any) -> typing.Any:
|
||||
def __lt__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | bool:
|
||||
r"""
|
||||
element-wise less than comparison
|
||||
"""
|
||||
def __le__(self, other: typing.Any) -> typing.Any:
|
||||
def __le__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | bool:
|
||||
r"""
|
||||
element-wise less than or equal comparison
|
||||
"""
|
||||
def __eq__(self, other: typing.Any) -> typing.Any:
|
||||
def __eq__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | bool:
|
||||
r"""
|
||||
element-wise equality comparison
|
||||
"""
|
||||
def __ne__(self, other: typing.Any) -> typing.Any:
|
||||
def __ne__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | bool:
|
||||
r"""
|
||||
element-wise not equal comparison
|
||||
"""
|
||||
def __gt__(self, other: typing.Any) -> typing.Any:
|
||||
def __gt__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | bool:
|
||||
r"""
|
||||
element-wise greater than comparison
|
||||
"""
|
||||
def __ge__(self, other: typing.Any) -> typing.Any:
|
||||
def __ge__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | bool:
|
||||
r"""
|
||||
element-wise greater than or equal comparison
|
||||
"""
|
||||
def __add__(self, other: typing.Any) -> typing.Any:
|
||||
def __add__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise addition
|
||||
"""
|
||||
def __radd__(self, other: typing.Any) -> typing.Any:
|
||||
def __radd__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise addition (reflected)
|
||||
"""
|
||||
def __sub__(self, other: typing.Any) -> typing.Any:
|
||||
def __sub__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise subtraction
|
||||
"""
|
||||
def __rsub__(self, other: typing.Any) -> typing.Any:
|
||||
def __rsub__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise subtraction (reflected)
|
||||
"""
|
||||
def __mul__(self, other: typing.Any) -> typing.Any:
|
||||
def __mul__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise multiplication
|
||||
"""
|
||||
def __rmul__(self, other: typing.Any) -> typing.Any:
|
||||
def __rmul__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise multiplication (reflected)
|
||||
"""
|
||||
def __truediv__(self, other: typing.Any) -> typing.Any:
|
||||
def __truediv__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise true division
|
||||
"""
|
||||
def __rtruediv__(self, other: typing.Any) -> typing.Any:
|
||||
def __rtruediv__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise true division (reflected)
|
||||
"""
|
||||
def __floordiv__(self, other: typing.Any) -> typing.Any:
|
||||
def __floordiv__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise floor division
|
||||
"""
|
||||
def __rfloordiv__(self, other: typing.Any) -> typing.Any:
|
||||
def __rfloordiv__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise floor division (reflected)
|
||||
"""
|
||||
def __mod__(self, other: typing.Any) -> typing.Any:
|
||||
def __mod__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise modulo
|
||||
"""
|
||||
def __rmod__(self, other: typing.Any) -> typing.Any:
|
||||
def __rmod__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise modulo (reflected)
|
||||
"""
|
||||
def __matmul__(self, other: typing.Any) -> typing.Any:
|
||||
def __matmul__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise matrix multiplication
|
||||
"""
|
||||
def __rmatmul__(self, other: typing.Any) -> typing.Any:
|
||||
def __rmatmul__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise matrix multiplication (reflected)
|
||||
"""
|
||||
def __and__(self, other: typing.Any) -> typing.Any:
|
||||
def __and__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | bool:
|
||||
r"""
|
||||
element-wise bitwise AND
|
||||
"""
|
||||
def __rand__(self, other: typing.Any) -> typing.Any:
|
||||
def __rand__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | bool:
|
||||
r"""
|
||||
element-wise bitwise AND (reflected)
|
||||
"""
|
||||
def __or__(self, other: typing.Any) -> typing.Any:
|
||||
def __or__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | bool:
|
||||
r"""
|
||||
element-wise bitwise OR
|
||||
"""
|
||||
def __ror__(self, other: typing.Any) -> typing.Any:
|
||||
def __ror__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | bool:
|
||||
r"""
|
||||
element-wise bitwise OR (reflected)
|
||||
"""
|
||||
def __xor__(self, other: typing.Any) -> typing.Any:
|
||||
def __xor__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | bool:
|
||||
r"""
|
||||
element-wise bitwise XOR
|
||||
"""
|
||||
def __rxor__(self, other: typing.Any) -> typing.Any:
|
||||
def __rxor__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | bool:
|
||||
r"""
|
||||
element-wise bitwise XOR (reflected)
|
||||
"""
|
||||
def __lshift__(self, other: typing.Any) -> typing.Any:
|
||||
def __lshift__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise left shift
|
||||
"""
|
||||
def __rlshift__(self, other: typing.Any) -> typing.Any:
|
||||
def __rlshift__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise left shift (reflected)
|
||||
"""
|
||||
def __rshift__(self, other: typing.Any) -> typing.Any:
|
||||
def __rshift__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise right shift
|
||||
"""
|
||||
def __rrshift__(self, other: typing.Any) -> typing.Any:
|
||||
def __rrshift__(
|
||||
self, other: float | numpy.ArrayLike | Imread
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise right shift (reflected)
|
||||
"""
|
||||
def __neg__(self) -> typing.Any:
|
||||
def __neg__(self) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise negation
|
||||
"""
|
||||
def __pos__(self) -> typing.Any:
|
||||
def __pos__(self) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise positive
|
||||
"""
|
||||
def __abs__(self) -> typing.Any:
|
||||
def __abs__(self) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise absolute value
|
||||
"""
|
||||
def __invert__(self) -> typing.Any:
|
||||
def __invert__(self) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
element-wise bitwise inversion
|
||||
"""
|
||||
@@ -507,13 +593,19 @@ class Imread:
|
||||
r"""
|
||||
the file path as a string
|
||||
"""
|
||||
def frame(
|
||||
self, c: builtins.int, z: builtins.int, t: builtins.int
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
retrieve a single frame at czt, sliced accordingly, alias of get_frame
|
||||
"""
|
||||
def get_frame(
|
||||
self, c: builtins.int, z: builtins.int, t: builtins.int
|
||||
) -> typing.Any:
|
||||
) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
retrieve a single frame at czt, sliced accordingly
|
||||
"""
|
||||
def flatten(self) -> typing.Any:
|
||||
def flatten(self) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
flatten the view into a 1D numpy array
|
||||
"""
|
||||
@@ -529,6 +621,10 @@ class Imread:
|
||||
r"""
|
||||
find the position of an axis
|
||||
"""
|
||||
def swapaxes(self, ax0: int | str, ax1: int | str) -> Imread:
|
||||
r"""
|
||||
swap two axes
|
||||
"""
|
||||
def swap_axes(self, ax0: int | str, ax1: int | str) -> Imread:
|
||||
r"""
|
||||
swap two axes
|
||||
@@ -539,7 +635,7 @@ class Imread:
|
||||
r"""
|
||||
permute the order of the axes
|
||||
"""
|
||||
def as_array(self) -> typing.Any:
|
||||
def as_array(self) -> numpy.typing.NDArray | float:
|
||||
r"""
|
||||
collect data into a numpy array
|
||||
"""
|
||||
@@ -573,10 +669,6 @@ class Imread:
|
||||
r"""
|
||||
the name of a particular channel
|
||||
"""
|
||||
def summary(self) -> builtins.str:
|
||||
r"""
|
||||
gives a helpful summary of the recorded experiment
|
||||
"""
|
||||
@staticmethod
|
||||
def get_available_series(
|
||||
path: str | pathlib.Path | Imread, reader: typing.Optional[builtins.str] = None
|
||||
@@ -793,7 +885,7 @@ class Shape:
|
||||
arguments for pickling
|
||||
"""
|
||||
def __getitem__(
|
||||
self, idx: str | int | None | Ellipsis | slice | list[int] | tuple[int]
|
||||
self, idx: str | int | None | Ellipsis | slice | typing.Sequence[int]
|
||||
) -> typing.Optional[int | tuple[int]]:
|
||||
r"""
|
||||
get dimension size by index or axis name
|
||||
|
||||
@@ -35,7 +35,7 @@ ndbioimage_generate_stub = "ndbioimage:ndbioimage_generate_stub"
|
||||
|
||||
[tool.maturin]
|
||||
python-source = "py"
|
||||
features = ["python", "bioformats_java", "gpl-formats", "czi", "tiff", "tiffseq", "tiffwrite", "movie", "transforms"]
|
||||
features = ["python", "bioformats_java", "gpl-formats", "bioformats_rust", "czi", "tiff", "tiffseq", "tiffwrite", "movie", "transforms"]
|
||||
no-default-features = true
|
||||
module-name = "ndbioimage.ndbioimage_rs"
|
||||
include = ["py/ndbioimage/jassets/j4rs*", "py/ndbioimage/deps/libj4rs*"]
|
||||
|
||||
+13
-4
@@ -314,16 +314,16 @@ impl Index<&Axis> for Shape {
|
||||
impl Index<usize> for Shape {
|
||||
type Output = usize;
|
||||
|
||||
fn index(&self, dim: usize) -> &Self::Output {
|
||||
&self[self.order[dim % self.order.len()]]
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[self.order[index]]
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<&usize> for Shape {
|
||||
type Output = usize;
|
||||
|
||||
fn index(&self, dim: &usize) -> &Self::Output {
|
||||
&self[self.order[dim % self.order.len()]]
|
||||
fn index(&self, index: &usize) -> &Self::Output {
|
||||
&self[self.order[*index]]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,6 +406,10 @@ impl Shape {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, index: &usize) -> Option<&usize> {
|
||||
self.order.get(*index).map(|axis| &self[axis])
|
||||
}
|
||||
|
||||
/// the number of axes in the shape
|
||||
pub fn len(&self) -> usize {
|
||||
self.order.len()
|
||||
@@ -421,6 +425,11 @@ impl Shape {
|
||||
self.order.iter().map(|axis| self[axis]).collect()
|
||||
}
|
||||
|
||||
/// the sizes in cztyx order
|
||||
pub fn cztyx(&self) -> [usize; 5] {
|
||||
[self.c, self.z, self.t, self.y, self.x]
|
||||
}
|
||||
|
||||
/// the sizes along the axes as a map from axis to size
|
||||
pub fn to_hashmap(&self) -> HashMap<Axis, usize> {
|
||||
let mut map = HashMap::new();
|
||||
|
||||
+433
-138
File diff suppressed because it is too large.
Load diff
@@ -188,6 +188,12 @@ pub trait Reader: Clone + Sized + Debug + Send + Hash + Into<DynReader> {
|
||||
where
|
||||
P: AsRef<Path>;
|
||||
|
||||
/// a simple fast test to see if the reader can open a path without parsing the whole file
|
||||
/// not a guarantee of success, but rather an early failure
|
||||
fn can_open<P>(path: P) -> Result<bool, Error>
|
||||
where
|
||||
P: AsRef<Path>;
|
||||
|
||||
/// the name of the reader type
|
||||
fn reader_name(&self) -> &'static str {
|
||||
type_name::<Self>()
|
||||
@@ -478,6 +484,34 @@ impl Reader for DynReader {
|
||||
))
|
||||
}
|
||||
|
||||
fn can_open<P>(path: P) -> Result<bool, Error>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let mut can_open = false;
|
||||
#[cfg(feature = "tiff")]
|
||||
{
|
||||
can_open |= tiff::TiffReader::can_open(&path)?;
|
||||
}
|
||||
#[cfg(feature = "tiffseq")]
|
||||
{
|
||||
can_open |= tiffseq::TiffSeqReader::can_open(&path)?;
|
||||
}
|
||||
#[cfg(feature = "czi")]
|
||||
{
|
||||
can_open |= czi::CziReader::can_open(&path)?;
|
||||
}
|
||||
#[cfg(feature = "bioformats_rust")]
|
||||
{
|
||||
can_open |= bioformats_rust::BioFormatsRustReader::can_open(&path)?;
|
||||
}
|
||||
#[cfg(feature = "bioformats_java")]
|
||||
{
|
||||
can_open |= bioformats_java::BioFormatsJavaReader::can_open(&path)?;
|
||||
}
|
||||
Ok(can_open)
|
||||
}
|
||||
|
||||
fn reader_name(&self) -> &'static str {
|
||||
match self {
|
||||
#[cfg(feature = "tiff")]
|
||||
|
||||
@@ -666,6 +666,13 @@ impl Reader for BioFormatsJavaReader {
|
||||
Ok(new)
|
||||
}
|
||||
|
||||
fn can_open<P>(_path: P) -> Result<bool, Error>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Ome, Error> {
|
||||
self.get_ome()
|
||||
}
|
||||
|
||||
@@ -274,6 +274,13 @@ impl Reader for BioFormatsRustReader {
|
||||
Ok(new)
|
||||
}
|
||||
|
||||
fn can_open<P>(path: P) -> Result<bool, Error>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
Ok(path.as_ref().extension() != Some(std::ffi::OsStr::new("czi")))
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Ome, Error> {
|
||||
let reader = self.get_reader()?;
|
||||
let metadata = reader.metadata();
|
||||
|
||||
@@ -215,6 +215,13 @@ impl Reader for CziReader {
|
||||
Ok(new)
|
||||
}
|
||||
|
||||
fn can_open<P>(path: P) -> Result<bool, Error>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
Ok(path.as_ref().extension() == Some(std::ffi::OsStr::new("czi")))
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Ome, Error> {
|
||||
let mut ome = Ome::default();
|
||||
let xml = xmltree::Element::parse(self.metadata_xml()?.as_bytes())?;
|
||||
|
||||
@@ -232,6 +232,24 @@ impl Reader for TiffReader {
|
||||
Ok(new)
|
||||
}
|
||||
|
||||
fn can_open<P>(path: P) -> Result<bool, Error>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let path = path.as_ref();
|
||||
let mut file = File::open(path)?;
|
||||
let mut sig = [0; 2];
|
||||
file.read_exact(&mut sig)?;
|
||||
if sig == [73, 73] {
|
||||
file.read_exact(&mut sig)?;
|
||||
Ok((sig[0] == 42) || (sig[0] == 43))
|
||||
} else if sig == [77, 77] {
|
||||
Ok((sig[1] == 42) || (sig[1] == 43))
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Ome, Error> {
|
||||
let mut reader = self.get_reader()?;
|
||||
let image_description = reader.current_ifd().get_tag(Tag::ImageDescription);
|
||||
@@ -466,18 +484,36 @@ impl Reader for TiffReader {
|
||||
&self.pixel_type
|
||||
}
|
||||
|
||||
fn get_available_positions<P>(_path: P, _series: usize) -> Result<HashSet<usize>, Error>
|
||||
fn get_available_positions<P>(path: P, _series: usize) -> Result<HashSet<usize>, Error>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let path = path.as_ref();
|
||||
if Self::can_open(path)? {
|
||||
Ok(HashSet::from([0]))
|
||||
} else {
|
||||
Err(Error::InvalidReader(
|
||||
"TiffReader".to_string(),
|
||||
path.to_string_lossy().to_string(),
|
||||
"it is not a tiff".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_available_series<P>(_path: P) -> Result<HashSet<usize>, Error>
|
||||
fn get_available_series<P>(path: P) -> Result<HashSet<usize>, Error>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let path = path.as_ref();
|
||||
if Self::can_open(path)? {
|
||||
Ok(HashSet::from([0]))
|
||||
} else {
|
||||
Err(Error::InvalidReader(
|
||||
"TiffReader".to_string(),
|
||||
path.to_string_lossy().to_string(),
|
||||
"it is not a tiff".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -239,6 +239,13 @@ impl Reader for TiffSeqReader {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_open<P>(path: P) -> Result<bool, Error>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
Ok(path.as_ref().is_dir())
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Ome, Error> {
|
||||
let mut ome = Ome::default();
|
||||
let info = self.metadata_map.get("Info").and_then(|v| v.as_mapping());
|
||||
@@ -580,11 +587,20 @@ impl Reader for TiffSeqReader {
|
||||
&self.pixel_type
|
||||
}
|
||||
|
||||
fn get_available_positions<P>(_path: P, _series: usize) -> Result<HashSet<usize>, Error>
|
||||
fn get_available_positions<P>(path: P, _series: usize) -> Result<HashSet<usize>, Error>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let path = path.as_ref();
|
||||
if Self::can_open(path)? {
|
||||
Ok(HashSet::from([0]))
|
||||
} else {
|
||||
Err(Error::InvalidReader(
|
||||
"TiffSeqReader".to_string(),
|
||||
path.to_string_lossy().to_string(),
|
||||
"not a tiff sequence".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_available_series<P>(path: P) -> Result<HashSet<usize>, Error>
|
||||
|
||||
@@ -284,6 +284,21 @@ impl<D: Dimension, R: Reader> View<D, R> {
|
||||
.ok_or(Error::NoChannel(channel))
|
||||
}
|
||||
|
||||
/// names of the channels in order
|
||||
pub fn channel_names(&self) -> Result<HashMap<usize, String>, Error> {
|
||||
if self.channel_names.get().is_none() {
|
||||
let names = self.metadata()?.image[0]
|
||||
.pixels
|
||||
.channel
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, c)| (i, c.name.clone().unwrap_or_else(|| format!("{}", i))))
|
||||
.collect::<HashMap<_, _>>();
|
||||
let _ = self.channel_names.set(names);
|
||||
}
|
||||
Ok(self.channel_names.get().cloned().unwrap_or_default())
|
||||
}
|
||||
|
||||
/// set the maximum number of frames the process-wide cache may hold,
|
||||
/// evicting the least recently used frames
|
||||
pub fn with_cache_capacity(self, capacity: usize) -> Self {
|
||||
@@ -404,6 +419,28 @@ impl<D: Dimension, R: Reader> View<D, R> {
|
||||
view.slice(slice.as_slice())
|
||||
}
|
||||
|
||||
/// remove axes of size 1 in axes
|
||||
pub fn squeeze_axes(&self, axes: HashSet<Axis>) -> Result<View<IxDyn, R>, Error> {
|
||||
let view = self.clone().into_dyn();
|
||||
let slice: Vec<_> = self
|
||||
.shape()
|
||||
.into_iter()
|
||||
.zip(self.axes().iter())
|
||||
.map(|(s, a)| {
|
||||
if s == 1 && axes.contains(a) {
|
||||
SliceInfoElem::Index(0)
|
||||
} else {
|
||||
SliceInfoElem::Slice {
|
||||
start: 0,
|
||||
end: None,
|
||||
step: 1,
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
view.slice(slice.as_slice())
|
||||
}
|
||||
|
||||
pub(crate) fn op_axes(&self) -> Vec<Axis> {
|
||||
self.operations.keys().cloned().collect()
|
||||
}
|
||||
|
||||
@@ -26,8 +26,10 @@ def image(array):
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"s",
|
||||
list(
|
||||
combinations_with_replacement(
|
||||
(0, -1, 1, slice(None), slice(0, 1), slice(-1, 0), slice(1, 1)), 5
|
||||
)
|
||||
),
|
||||
)
|
||||
def test_slicing(s, image, array):
|
||||
|
||||
@@ -26,6 +26,7 @@ def image(array):
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"fun_and_axis",
|
||||
list(
|
||||
product(
|
||||
(
|
||||
np.sum,
|
||||
@@ -44,6 +45,7 @@ def image(array):
|
||||
np.nanstd,
|
||||
),
|
||||
(None, 0, 1, 2, 3, 4),
|
||||
)
|
||||
),
|
||||
)
|
||||
def test_ufuncs(fun_and_axis, image, array):
|
||||
|
||||
Reference in new issue
Block a user