Compare commits

...
2 Commits
Author SHA1 Message Date
w.pomp 645c75535c Merge remote-tracking branch 'origin/main'
pytest / Publish (pypi.org) (push) Failing after 32s
2026-11-04 17:10:29 +01:00
w.pomp 4a5a538bf3 - a lot of todo methods for Imread 2026-11-04 17:10:21 +01:00
4 changed files with 669 additions and 31 deletions

No files matched your search

+3
View File
@@ -117,6 +117,9 @@ pub enum Error {
/// the view is empty
#[error("empty view")]
EmptyView,
/// the view cannot be parsed as a scalar
#[error("not a scalar")]
NotScalar,
/// the color string could not be parsed
#[error("invalid color: {0}")]
InvalidColor(String),
+645 -5
View File
@@ -4,9 +4,10 @@ use crate::metadata::Metadata;
use crate::movie::MovieOptions;
use crate::readers::{DynReader, PixelType, Reader};
use crate::view::{Item, View};
use crate::view::View;
use itertools::Itertools;
use ndarray::{ArrayD, Ix0, Ix1, IxDyn, SliceInfo, SliceInfoElem};
use num::Zero;
use numpy::{
AllowTypeChange, IntoPyArray, PyArray, PyArrayDescr, PyArrayLike0, PyArrayLike1,
PyArrayMethods, dtype,
@@ -26,6 +27,8 @@ use pyo3_stub_gen::derive::*;
use pyo3_stub_gen::inventory::submit;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::fs::OpenOptions;
use std::io::Write;
use std::path::PathBuf;
/// class to read image files, while taking good care of important metadata,
@@ -70,7 +73,7 @@ unsafe impl Send for PyView {}
unsafe impl Sync for PyView {}
impl PyView {
fn item(py: Python, view: View<IxDyn>, dtype: PixelType) -> PyResult<Bound<PyAny>> {
fn scalar(py: Python, view: View<IxDyn>, dtype: PixelType) -> PyResult<Bound<PyAny>> {
macro_rules! item {
($t:tt) => {
Ok(view
@@ -486,7 +489,7 @@ impl PyView {
.collect::<Vec<_>>();
let view = view.permute_axes(&axes)?;
if view.ndim() == 0 {
Self::item(py, view, self.dtype)
Self::scalar(py, view, self.dtype)
} else {
PyView {
view,
@@ -544,7 +547,7 @@ impl PyView {
}
let view = self.view.slice(new_slice.as_slice())?;
if view.ndim() == 0 {
Self::item(py, view, self.dtype)
Self::scalar(py, view, self.dtype)
} else {
PyView {
view,
@@ -1157,7 +1160,7 @@ impl PyView {
}
let view = self.view.slice(new_slice.as_slice())?;
Some(if view.ndim() == 0 {
Self::item(py, view, self.dtype)
Self::scalar(py, view, self.dtype)
} else {
PyView {
view,
@@ -2006,6 +2009,643 @@ impl PyView {
/// backwards compatibility
#[expect(unused_variables)]
fn set_cache_size(&self, size: usize) {}
/// set a value at an index - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __setitem__(&self, key: Bound<PyAny>, value: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// delete an index - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __delitem__(&self, key: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// in-place addition - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __iadd__(&self, other: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// in-place subtraction - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __isub__(&self, other: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// in-place multiplication - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __imul__(&self, other: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// in-place true division - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __itruediv__(&self, other: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// in-place floor division - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __ifloordiv__(&self, other: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// in-place modulo - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __imod__(&self, other: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// in-place power - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __ipow__(&self, other: Bound<PyAny>, r#mod: Option<Bound<PyAny>>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// in-place bitwise AND - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __iand__(&self, other: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// in-place bitwise OR - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __ior__(&self, other: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// in-place bitwise XOR - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __ixor__(&self, other: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// in-place left shift - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __ilshift__(&self, other: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// in-place right shift - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __irshift__(&self, other: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// in-place matrix multiplication - not supported (read-only)
#[gen_stub(skip)]
#[expect(unused_variables)]
fn __imatmul__(&self, other: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// set a scalar at an index - not supported (read-only)
#[gen_stub(skip)]
#[pyo3(signature = (index, value))]
#[expect(unused_variables)]
fn itemset(&self, index: Bound<PyAny>, value: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// fill the view with a value - not supported (read-only)
#[gen_stub(skip)]
#[pyo3(signature = (value))]
#[expect(unused_variables)]
fn fill(&self, value: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// put values at indices - not supported (read-only)
#[gen_stub(skip)]
#[pyo3(signature = (indices, values, mode="raise"))]
#[expect(unused_variables)]
fn put(&self, indices: Bound<PyAny>, values: Bound<PyAny>, mode: &str) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// put values at masked indices - not supported (read-only)
#[gen_stub(skip)]
#[pyo3(signature = (mask, values))]
#[expect(unused_variables)]
fn putmask(&self, mask: Bound<PyAny>, values: Bound<PyAny>) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// resize the view in place - not supported (read-only)
#[gen_stub(skip)]
#[pyo3(signature = (new_shape, order="C", refcheck=true))]
#[expect(unused_variables)]
fn resize(&self, new_shape: Bound<PyAny>, order: &str, refcheck: bool) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// byteswap pixels in place - not supported (read-only)
#[gen_stub(skip)]
#[pyo3(signature = (inplace=false))]
#[expect(unused_variables)]
fn byteswap(&self, inplace: bool) -> PyResult<()> {
Err(PyNotImplementedError::new_err(
"Imread is a read-only, lazy view and cannot be mutated in place",
))
}
/// index of the maximum - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (axis=None, out=None, keepdims=None))]
#[expect(unused_variables)]
fn argmax(
&self,
axis: Option<Bound<PyAny>>,
out: Option<Bound<PyAny>>,
keepdims: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// index of the minimum - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (axis=None, out=None, keepdims=None))]
#[expect(unused_variables)]
fn argmin(
&self,
axis: Option<Bound<PyAny>>,
out: Option<Bound<PyAny>>,
keepdims: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// standard deviation - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (axis=None, dtype=None, out=None, ddof=None, keepdims=None))]
#[expect(unused_variables)]
fn std(
&self,
axis: Option<Bound<PyAny>>,
dtype: Option<Bound<PyAny>>,
out: Option<Bound<PyAny>>,
ddof: Option<Bound<PyAny>>,
keepdims: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// variance - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (axis=None, dtype=None, out=None, ddof=None, keepdims=None))]
#[expect(unused_variables)]
fn var(
&self,
axis: Option<Bound<PyAny>>,
dtype: Option<Bound<PyAny>>,
out: Option<Bound<PyAny>>,
ddof: Option<Bound<PyAny>>,
keepdims: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// product - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (axis=None, dtype=None, out=None, keepdims=None, initial=None))]
#[expect(unused_variables)]
fn prod(
&self,
axis: Option<Bound<PyAny>>,
dtype: Option<Bound<PyAny>>,
out: Option<Bound<PyAny>>,
keepdims: Option<Bound<PyAny>>,
initial: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// cumulative sum - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (axis=None, dtype=None, out=None))]
#[expect(unused_variables)]
fn cumsum(
&self,
axis: Option<Bound<PyAny>>,
dtype: Option<Bound<PyAny>>,
out: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// cumulative product - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (axis=None, dtype=None, out=None))]
#[expect(unused_variables)]
fn cumprod(
&self,
axis: Option<Bound<PyAny>>,
dtype: Option<Bound<PyAny>>,
out: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// get a single Python scalar - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (index))]
#[expect(unused_variables)]
fn item(&self, index: Bound<PyAny>) -> PyResult<()> {
todo!()
}
/// indices of non-zero elements - not implemented yet
#[gen_stub(skip)]
fn nonzero(&self) -> PyResult<()> {
todo!()
}
/// gather along an axis - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (indices, axis=None, mode=None, out=None))]
#[expect(unused_variables)]
fn take(
&self,
indices: Bound<PyAny>,
axis: Option<Bound<PyAny>>,
mode: Option<Bound<PyAny>>,
out: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// gather along an axis after broadcasting - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (arr, indices, axis))]
#[expect(unused_variables)]
fn take_along_axis(
&self,
arr: Bound<PyAny>,
indices: Bound<PyAny>,
axis: Bound<PyAny>,
) -> PyResult<()> {
todo!()
}
/// find insertion points - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (a, side=None, sorter=None))]
#[expect(unused_variables)]
fn searchsorted(
&self,
a: Bound<PyAny>,
side: Option<Bound<PyAny>>,
sorter: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// return the n-th diagonal - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (offset=None, axis1=None, axis2=None))]
#[expect(unused_variables)]
fn diagonal(
&self,
offset: Option<Bound<PyAny>>,
axis1: Option<Bound<PyAny>>,
axis2: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// repeat elements - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (repeats, axis=None, out=None))]
#[expect(unused_variables)]
fn repeat(
&self,
repeats: Bound<PyAny>,
axis: Option<Bound<PyAny>>,
out: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// truncate to a range - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (a_min=None, a_max=None, out=None))]
#[expect(unused_variables)]
fn clip(
&self,
a_min: Option<Bound<PyAny>>,
a_max: Option<Bound<PyAny>>,
out: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// round to decimals - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (decimals=None, out=None))]
#[expect(unused_variables)]
fn round(&self, decimals: Option<Bound<PyAny>>, out: Option<Bound<PyAny>>) -> PyResult<()> {
todo!()
}
/// select elements where a condition is true - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (condition, axis=None, out=None))]
#[expect(unused_variables)]
fn compress(
&self,
condition: Bound<PyAny>,
axis: Option<Bound<PyAny>>,
out: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// dot product - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (b))]
#[expect(unused_variables)]
fn dot(&self, b: Bound<PyAny>) -> PyResult<()> {
todo!()
}
/// trace along two axes - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (offset=None, axis1=None, axis2=None, dtype=None, out=None))]
#[expect(unused_variables)]
fn trace(
&self,
offset: Option<Bound<PyAny>>,
axis1: Option<Bound<PyAny>>,
axis2: Option<Bound<PyAny>>,
dtype: Option<Bound<PyAny>>,
out: Option<Bound<PyAny>>,
) -> PyResult<()> {
todo!()
}
/// real part
#[getter]
fn real(&self) -> PyView {
self.clone()
}
/// imaginary part
#[getter]
fn imag<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
macro_rules! imag {
($t:tt) => {
Ok(
ArrayD::<$t>::zeros(self.view.shape().into_iter().collect::<Vec<_>>())
.into_pyarray(py)
.into_any(),
)
};
}
match self.dtype {
PixelType::Bool => todo!(),
PixelType::I8 => imag!(i8),
PixelType::U8 => imag!(u8),
PixelType::I16 => imag!(i16),
PixelType::U16 => imag!(u16),
PixelType::I32 => imag!(i32),
PixelType::U32 => imag!(u32),
PixelType::F32 => imag!(f32),
PixelType::F64 => imag!(f64),
PixelType::I64 => imag!(i64),
PixelType::U64 => imag!(u64),
PixelType::I128 => Err(PyTypeError::new_err("i128 type is not supported")),
PixelType::U128 => Err(PyTypeError::new_err("u128 type is not supported")),
PixelType::F128 => Err(PyTypeError::new_err("f128 type is not supported")),
}
}
/// complex conjugate
fn conj(&self) -> Self {
self.clone()
}
/// complex conjugate
fn conjugate(&self) -> Self {
self.clone()
}
/// ctypes view - not implemented yet
#[gen_stub(skip)]
#[getter]
fn ctypes(&self) -> PyResult<()> {
todo!()
}
/// total bytes - not implemented yet
#[gen_stub(skip)]
#[getter]
fn nbytes(&self) -> PyResult<()> {
todo!()
}
/// bytes per element - not implemented yet
#[gen_stub(skip)]
#[getter]
fn itemsize(&self) -> PyResult<()> {
todo!()
}
/// strides - not implemented yet
#[gen_stub(skip)]
#[getter]
fn strides(&self) -> PyResult<()> {
todo!()
}
/// raw data buffer - not implemented yet
#[gen_stub(skip)]
#[getter]
fn data(&self) -> PyResult<()> {
todo!()
}
/// convert to a nested Python list - not implemented yet
#[gen_stub(skip)]
fn tolist(&self) -> PyResult<()> {
todo!()
}
/// pickle to a file
fn dump(&self, file: PathBuf) -> PyResult<()> {
OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(file)?
.write_all(&to_stdvec(self).map_err(Error::from)?)?;
Ok(())
}
/// pickle to a string
fn dumps(&self) -> PyResult<Vec<u8>> {
Ok(to_stdvec(self).map_err(Error::from)?)
}
/// a view of the same data
#[pyo3(signature = (dtype=None, r#type=None))]
fn view(&self, py: Python, dtype: Option<Bound<PyAny>>, r#type: Option<Bound<PyAny>>) -> PyResult<Self> {
if r#type.is_some() {
Err(PyNotImplementedError::new_err(
"type not None is not supported",
))
} else if let Some(dtype) = dtype {
self.as_type(py, dtype)
} else {
Ok(self.clone())
}
}
/// a structured view of the data - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (dtype=None))]
#[expect(unused_variables)]
fn tview(&self, dtype: Option<Bound<PyAny>>) -> PyResult<()> {
todo!()
}
/// a view sharing memory with a buffer - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (mem=None))]
#[expect(unused_variables)]
fn share_memory_with(&self, mem: Option<Bound<PyAny>>) -> PyResult<()> {
todo!()
}
/// split horizontally - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (n))]
#[expect(unused_variables)]
fn hsplit(&self, n: Bound<PyAny>) -> PyResult<()> {
todo!()
}
/// split vertically - not implemented yet
#[gen_stub(skip)]
#[pyo3(signature = (n=None))]
#[expect(unused_variables)]
fn vsplit(&self, n: Option<Bound<PyAny>>) -> PyResult<()> {
todo!()
}
/// boolean value
fn __bool__(&self) -> PyResult<bool> {
macro_rules! _bool {
($t:tt) => {
Ok(self.view.item::<$t>()? != $t::zero())
};
}
match self.dtype {
PixelType::Bool => todo!(),
PixelType::I8 => _bool!(i8),
PixelType::U8 => _bool!(u8),
PixelType::I16 => _bool!(i16),
PixelType::U16 => _bool!(u16),
PixelType::I32 => _bool!(i32),
PixelType::U32 => _bool!(u32),
PixelType::I64 => _bool!(i64),
PixelType::U64 => _bool!(u64),
PixelType::I128 => _bool!(i128),
PixelType::U128 => _bool!(u128),
PixelType::F32 => _bool!(f32),
PixelType::F64 => _bool!(f64),
PixelType::F128 => Err(PyTypeError::new_err("f128 type is not supported")),
}
}
/// convert to int - 0-dimensional Imread should always already be materialized
fn __int__(&self) -> PyResult<()> {
Err(PyTypeError::new_err(
"only 0-dimensional arrays can be converted to Python scalars",
))
}
/// convert to float - 0-dimensional Imread should always already be materialized
fn __float__(&self) -> PyResult<()> {
Err(PyTypeError::new_err(
"only 0-dimensional arrays can be converted to Python scalars",
))
}
/// convert to complex - not implemented yet
#[gen_stub(skip)]
fn __complex__(&self) -> PyResult<()> {
todo!()
}
/// convert to integer (index) - not implemented yet
#[gen_stub(skip)]
fn __index__(&self) -> PyResult<()> {
todo!()
}
/// object size in bytes - not implemented yet
#[gen_stub(skip)]
fn __sizeof__(&self) -> PyResult<()> {
todo!()
}
}
submit! {
+20 -25
View File
@@ -787,7 +787,25 @@ impl<D: Dimension, R: Reader> View<D, R> {
let slice: Vec<_> = index.iter().map(|s| SliceInfoElem::Index(*s)).collect();
let view = self.clone().into_dyn().slice(slice.as_slice())?;
let arr = view.as_array()?;
Ok(*arr.first().unwrap())
Ok(*arr.first().expect("there should be exactly one value"))
}
/// retrieve the single item in the slice
pub fn item<T>(&self) -> Result<T, Error>
where
T: Number,
ArrayD<T>: MinMax<Output = ArrayD<T>>,
Array1<T>: MinMax<Output = Array0<T>>,
Array2<T>: MinMax<Output = Array1<T>>,
{
match self.shape().cztyx().iter().product() {
0 => Err(Error::EmptyView),
1 => Ok(*self
.as_array()?
.first()
.expect("there should be exactly one value")),
_ => Err(Error::NotScalar),
}
}
/// collect the view into an ndarray
@@ -1535,17 +1553,6 @@ where
}
}
/// trait to define a function to retrieve the only item in a 0d array
pub trait Item {
/// the single item in the 0d array, cast to `T`
fn item<T>(&self) -> Result<T, Error>
where
T: Number,
ArrayD<T>: MinMax<Output = ArrayD<T>>,
Array1<T>: MinMax<Output = Array0<T>>,
Array2<T>: MinMax<Output = Array1<T>>;
}
impl<R: Reader> View<Ix5, R> {
/// create a view on the image at `path`, parsing series and position from the file name
pub fn from_path<P>(path: P) -> Result<Self, Error>
@@ -1557,18 +1564,6 @@ impl<R: Reader> View<Ix5, R> {
}
}
impl<R: Reader> Item for View<Ix0, R> {
fn item<T>(&self) -> Result<T, Error>
where
T: Number,
ArrayD<T>: MinMax<Output = ArrayD<T>>,
Array1<T>: MinMax<Output = Array0<T>>,
Array2<T>: MinMax<Output = Array1<T>>,
{
Ok(*self.as_array()?.first().ok_or(Error::EmptyView)?)
}
}
impl<D: Dimension, R: Reader> Display for View<D, R> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if let Ok(summary) = self.summary() {
@@ -1612,7 +1607,7 @@ mod tests {
use crate::error::Error;
use crate::readers::{DynReader, Frame, Reader};
use crate::stats::MinMax;
use crate::view::{Item, View};
use crate::view::View;
use indexmap::IndexMap;
use ndarray::{Array, Array4, Array5, Ix4, Ix5, NewAxis};
use ndarray::{Array2, ArrayD, IxDyn, SliceInfoElem, s};