ndbioimage/
lib.rs

1mod bioformats;
2
3pub mod axes;
4pub mod metadata;
5#[cfg(feature = "python")]
6mod py;
7pub mod reader;
8pub mod stats;
9pub mod view;
10
11pub mod colors;
12#[cfg(feature = "movie")]
13pub mod movie;
14#[cfg(feature = "tiff")]
15pub mod tiff;
16
17pub use bioformats::download_bioformats;
18
19#[cfg(test)]
20mod tests {
21    use crate::axes::Axis;
22    use crate::reader::{Frame, Reader};
23    use crate::stats::MinMax;
24    use crate::view::Item;
25    use anyhow::Result;
26    use ndarray::{Array, Array4, Array5, NewAxis};
27    use ndarray::{Array2, s};
28    use rayon::prelude::*;
29
30    fn open(file: &str) -> Result<Reader> {
31        let path = std::env::current_dir()?
32            .join("tests")
33            .join("files")
34            .join(file);
35        Reader::new(&path, 0)
36    }
37
38    fn get_pixel_type(file: &str) -> Result<String> {
39        let reader = open(file)?;
40        Ok(format!(
41            "file: {}, pixel type: {:?}",
42            file, reader.pixel_type
43        ))
44    }
45
46    fn get_frame(file: &str) -> Result<Frame> {
47        let reader = open(file)?;
48        reader.get_frame(0, 0, 0)
49    }
50
51    #[test]
52    fn read_ser() -> Result<()> {
53        let file = "Experiment-2029.czi";
54        let reader = open(file)?;
55        println!("size: {}, {}", reader.size_y, reader.size_y);
56        let frame = reader.get_frame(0, 0, 0)?;
57        if let Ok(arr) = <Frame as TryInto<Array2<i8>>>::try_into(frame) {
58            println!("{:?}", arr);
59        } else {
60            println!("could not convert Frame to Array<i8>");
61        }
62        Ok(())
63    }
64
65    #[test]
66    fn read_par() -> Result<()> {
67        let files = vec!["Experiment-2029.czi", "test.tif"];
68        let pixel_type = files
69            .into_par_iter()
70            .map(|file| get_pixel_type(file).unwrap())
71            .collect::<Vec<_>>();
72        println!("{:?}", pixel_type);
73        Ok(())
74    }
75
76    #[test]
77    fn read_frame_par() -> Result<()> {
78        let files = vec!["Experiment-2029.czi", "test.tif"];
79        let frames = files
80            .into_par_iter()
81            .map(|file| get_frame(file).unwrap())
82            .collect::<Vec<_>>();
83        println!("{:?}", frames);
84        Ok(())
85    }
86
87    #[test]
88    fn read_sequence() -> Result<()> {
89        let file = "YTL1841B2-2-1_1hr_DMSO_galinduction_1/Pos0/img_000000000_mScarlet_GFP-mSc-filter_004.tif";
90        let reader = open(file)?;
91        println!("reader: {:?}", reader);
92        let frame = reader.get_frame(0, 4, 0)?;
93        println!("frame: {:?}", frame);
94        let frame = reader.get_frame(0, 2, 0)?;
95        println!("frame: {:?}", frame);
96        Ok(())
97    }
98
99    #[test]
100    fn read_sequence1() -> Result<()> {
101        let file = "4-Pos_001_002/img_000000000_Cy3-Cy3_filter_000.tif";
102        let reader = open(file)?;
103        println!("reader: {:?}", reader);
104        Ok(())
105    }
106
107    #[test]
108    fn ome_xml() -> Result<()> {
109        let file = "Experiment-2029.czi";
110        let reader = open(file)?;
111        let xml = reader.get_ome_xml()?;
112        println!("{}", xml);
113        Ok(())
114    }
115
116    #[test]
117    fn view() -> Result<()> {
118        let file = "YTL1841B2-2-1_1hr_DMSO_galinduction_1/Pos0/img_000000000_mScarlet_GFP-mSc-filter_004.tif";
119        let reader = open(file)?;
120        let view = reader.view();
121        let a = view.slice(s![0, 5, 0, .., ..])?;
122        let b = reader.get_frame(0, 5, 0)?;
123        let c: Array2<isize> = a.try_into()?;
124        let d: Array2<isize> = b.try_into()?;
125        assert_eq!(c, d);
126        Ok(())
127    }
128
129    #[test]
130    fn view_shape() -> Result<()> {
131        let file = "YTL1841B2-2-1_1hr_DMSO_galinduction_1/Pos0/img_000000000_mScarlet_GFP-mSc-filter_004.tif";
132        let reader = open(file)?;
133        let view = reader.view();
134        let a = view.slice(s![0, ..5, 0, .., 100..200])?;
135        let shape = a.shape();
136        assert_eq!(shape, vec![5, 1024, 100]);
137        Ok(())
138    }
139
140    #[test]
141    fn view_new_axis() -> Result<()> {
142        let file = "YTL1841B2-2-1_1hr_DMSO_galinduction_1/Pos0/img_000000000_mScarlet_GFP-mSc-filter_004.tif";
143        let reader = open(file)?;
144        let view = reader.view();
145        let a = Array5::<u8>::zeros((1, 9, 1, 1024, 1024));
146        let a = a.slice(s![0, ..5, 0, NewAxis, 100..200, ..]);
147        let v = view.slice(s![0, ..5, 0, NewAxis, 100..200, ..])?;
148        assert_eq!(v.shape(), a.shape());
149        let a = a.slice(s![NewAxis, .., .., NewAxis, .., .., NewAxis]);
150        let v = v.slice(s![NewAxis, .., .., NewAxis, .., .., NewAxis])?;
151        assert_eq!(v.shape(), a.shape());
152        Ok(())
153    }
154
155    #[test]
156    fn view_permute_axes() -> Result<()> {
157        let file = "YTL1841B2-2-1_1hr_DMSO_galinduction_1/Pos0/img_000000000_mScarlet_GFP-mSc-filter_004.tif";
158        let reader = open(file)?;
159        let view = reader.view();
160        let s = view.shape();
161        let mut a = Array5::<u8>::zeros((s[0], s[1], s[2], s[3], s[4]));
162        assert_eq!(view.shape(), a.shape());
163        let b: Array5<usize> = view.clone().try_into()?;
164        assert_eq!(b.shape(), a.shape());
165
166        let view = view.swap_axes(Axis::C, Axis::Z)?;
167        a.swap_axes(0, 1);
168        assert_eq!(view.shape(), a.shape());
169        let b: Array5<usize> = view.clone().try_into()?;
170        assert_eq!(b.shape(), a.shape());
171        let view = view.permute_axes(&[Axis::X, Axis::Z, Axis::Y])?;
172        let a = a.permuted_axes([4, 1, 2, 0, 3]);
173        assert_eq!(view.shape(), a.shape());
174        let b: Array5<usize> = view.clone().try_into()?;
175        assert_eq!(b.shape(), a.shape());
176        Ok(())
177    }
178
179    macro_rules! test_max {
180        ($($name:ident: $b:expr $(,)?)*) => {
181            $(
182                #[test]
183                fn $name() -> Result<()> {
184                    let file = "YTL1841B2-2-1_1hr_DMSO_galinduction_1/Pos0/img_000000000_mScarlet_GFP-mSc-filter_004.tif";
185                    let reader = open(file)?;
186                    let view = reader.view();
187                    let array: Array5<usize> = view.clone().try_into()?;
188                    let view = view.max_proj($b)?;
189                    let a: Array4<usize> = view.clone().try_into()?;
190                    let b = array.max($b)?;
191                    assert_eq!(a.shape(), b.shape());
192                    assert_eq!(a, b);
193                    Ok(())
194                }
195            )*
196        };
197    }
198
199    test_max! {
200        max_c: 0
201        max_z: 1
202        max_t: 2
203        max_y: 3
204        max_x: 4
205    }
206
207    macro_rules! test_index {
208        ($($name:ident: $b:expr $(,)?)*) => {
209            $(
210                #[test]
211                fn $name() -> Result<()> {
212                    let file = "YTL1841B2-2-1_1hr_DMSO_galinduction_1/Pos0/img_000000000_mScarlet_GFP-mSc-filter_004.tif";
213                    let reader = open(file)?;
214                    let view = reader.view();
215                    let v4: Array<usize, _> = view.slice($b)?.try_into()?;
216                    let a5: Array5<usize> = reader.view().try_into()?;
217                    let a4 = a5.slice($b).to_owned();
218                    assert_eq!(a4, v4);
219                    Ok(())
220                }
221            )*
222        };
223    }
224
225    test_index! {
226        index_0: s![.., .., .., .., ..]
227        index_1: s![0, .., .., .., ..]
228        index_2: s![.., 0, .., .., ..]
229        index_3: s![.., .., 0, .., ..]
230        index_4: s![.., .., .., 0, ..]
231        index_5: s![.., .., .., .., 0]
232        index_6: s![0, 0, .., .., ..]
233        index_7: s![0, .., 0, .., ..]
234        index_8: s![0, .., .., 0, ..]
235        index_9: s![0, .., .., .., 0]
236        index_a: s![.., 0, 0, .., ..]
237        index_b: s![.., 0, .., 0, ..]
238        index_c: s![.., 0, .., .., 0]
239        index_d: s![.., .., 0, 0, ..]
240        index_e: s![.., .., 0, .., 0]
241        index_f: s![.., .., .., 0, 0]
242        index_g: s![0, 0, 0, .., ..]
243        index_h: s![0, 0, .., 0, ..]
244        index_i: s![0, 0, .., .., 0]
245        index_j: s![0, .., 0, 0, ..]
246        index_k: s![0, .., 0, .., 0]
247        index_l: s![0, .., .., 0, 0]
248        index_m: s![0, 0, 0, 0, ..]
249        index_n: s![0, 0, 0, .., 0]
250        index_o: s![0, 0, .., 0, 0]
251        index_p: s![0, .., 0, 0, 0]
252        index_q: s![.., 0, 0, 0, 0]
253        index_r: s![0, 0, 0, 0, 0]
254    }
255
256    #[test]
257    fn dyn_view() -> Result<()> {
258        let file = "YTL1841B2-2-1_1hr_DMSO_galinduction_1/Pos0/img_000000000_mScarlet_GFP-mSc-filter_004.tif";
259        let reader = open(file)?;
260        let a = reader.view().into_dyn();
261        let b = a.max_proj(1)?;
262        let c = b.slice(s![0, 0, .., ..])?;
263        let d = c.as_array::<usize>()?;
264        assert_eq!(d.shape(), [1024, 1024]);
265        Ok(())
266    }
267
268    #[test]
269    fn item() -> Result<()> {
270        let file = "1xp53-01-AP1.czi";
271        let reader = open(file)?;
272        let view = reader.view();
273        let a = view.slice(s![.., 0, 0, 0, 0])?;
274        let b = a.slice(s![0])?;
275        let item = b.item::<usize>()?;
276        assert_eq!(item, 2);
277        Ok(())
278    }
279
280    #[test]
281    fn slice_cztyx() -> Result<()> {
282        let file = "1xp53-01-AP1.czi";
283        let reader = open(file)?;
284        let view = reader.view().max_proj(Axis::Z)?.into_dyn();
285        println!("view.axes: {:?}", view.get_axes());
286        println!("view.slice: {:?}", view.get_slice());
287        let r = view.reset_axes()?;
288        println!("r.axes: {:?}", r.get_axes());
289        println!("r.slice: {:?}", r.get_slice());
290        let a = view.slice_cztyx(s![0, 0, 0, .., ..])?;
291        println!("a.axes: {:?}", a.get_axes());
292        println!("a.slice: {:?}", a.get_slice());
293        assert_eq!(a.axes(), [Axis::Y, Axis::X]);
294        Ok(())
295    }
296
297    #[test]
298    fn reset_axes() -> Result<()> {
299        let file = "1xp53-01-AP1.czi";
300        let reader = open(file)?;
301        let view = reader.view().max_proj(Axis::Z)?;
302        let view = view.reset_axes()?;
303        assert_eq!(view.axes(), [Axis::C, Axis::New, Axis::T, Axis::Y, Axis::X]);
304        let a = view.as_array::<f64>()?;
305        assert_eq!(a.ndim(), 5);
306        Ok(())
307    }
308
309    #[test]
310    fn reset_axes2() -> Result<()> {
311        let file = "Experiment-2029.czi";
312        let reader = open(file)?;
313        let view = reader.view().squeeze()?;
314        let a = view.reset_axes()?;
315        assert_eq!(a.axes(), [Axis::C, Axis::Z, Axis::T, Axis::Y, Axis::X]);
316        Ok(())
317    }
318
319    #[test]
320    fn reset_axes3() -> Result<()> {
321        let file = "Experiment-2029.czi";
322        let reader = open(file)?;
323        let view4 = reader.view().squeeze()?;
324        let view = view4.max_proj(Axis::Z)?.into_dyn();
325        let slice = view.slice_cztyx(s![0, .., .., .., ..])?.into_dyn();
326        let a = slice.as_array::<u16>()?;
327        assert_eq!(slice.shape(), [1, 10, 1280, 1280]);
328        assert_eq!(a.shape(), [1, 10, 1280, 1280]);
329        let r = slice.reset_axes()?;
330        let b = r.as_array::<u16>()?;
331        assert_eq!(r.shape(), [1, 1, 10, 1280, 1280]);
332        assert_eq!(b.shape(), [1, 1, 10, 1280, 1280]);
333        let q = slice.max_proj(Axis::C)?.max_proj(Axis::T)?;
334        let c = q.as_array::<f64>()?;
335        assert_eq!(q.shape(), [1, 1280, 1280]);
336        assert_eq!(c.shape(), [1, 1280, 1280]);
337        let p = q.reset_axes()?;
338        let d = p.as_array::<u16>()?;
339        println!("axes: {:?}", p.get_axes());
340        println!("operations: {:?}", p.get_operations());
341        println!("slice: {:?}", p.get_slice());
342        assert_eq!(p.shape(), [1, 1, 1, 1280, 1280]);
343        assert_eq!(d.shape(), [1, 1, 1, 1280, 1280]);
344        Ok(())
345    }
346
347    #[test]
348    fn max() -> Result<()> {
349        let file = "Experiment-2029.czi";
350        let reader = open(file)?;
351        let view = reader.view();
352        let m = view.max_proj(Axis::T)?;
353        let a = m.as_array::<u16>()?;
354        assert_eq!(m.shape(), [2, 1, 1280, 1280]);
355        assert_eq!(a.shape(), [2, 1, 1280, 1280]);
356        let mc = view.max_proj(Axis::C)?;
357        let a = mc.as_array::<u16>()?;
358        assert_eq!(mc.shape(), [1, 10, 1280, 1280]);
359        assert_eq!(a.shape(), [1, 10, 1280, 1280]);
360        let mz = mc.max_proj(Axis::Z)?;
361        let a = mz.as_array::<u16>()?;
362        assert_eq!(mz.shape(), [10, 1280, 1280]);
363        assert_eq!(a.shape(), [10, 1280, 1280]);
364        let mt = mz.max_proj(Axis::T)?;
365        let a = mt.as_array::<u16>()?;
366        assert_eq!(mt.shape(), [1280, 1280]);
367        assert_eq!(a.shape(), [1280, 1280]);
368        Ok(())
369    }
370}