- added ome_xml method
- some pyo3 methods
This commit is contained in:
@@ -31,7 +31,7 @@ macro_rules! method_arg {
|
||||
|
||||
macro_rules! method {
|
||||
($name:ident, $method:expr $(,[$($n:tt: $t:ty$(|$p:tt)?),*])? $(=> $tt:ty$(|$c:tt)?)?) => {
|
||||
pub fn $name(&self, $($($n: $t),*)?) -> method_return!($($tt)?) {
|
||||
pub(crate) fn $name(&self, $($($n: $t),*)?) -> method_return!($($tt)?) {
|
||||
let args: Vec<InvocationArg> = vec![$($( method_arg!($n:$t$(|$p)?) ),*)?];
|
||||
let _result = jvm().invoke(&self.0, $method, &args)?;
|
||||
|
||||
@@ -55,10 +55,10 @@ macro_rules! method {
|
||||
};
|
||||
}
|
||||
|
||||
pub struct DebugTools;
|
||||
pub(crate) struct DebugTools;
|
||||
|
||||
impl DebugTools {
|
||||
pub fn set_root_level(level: &str) -> Result<()> {
|
||||
pub(crate) fn set_root_level(level: &str) -> Result<()> {
|
||||
jvm().invoke_static(
|
||||
"loci.common.DebugTools",
|
||||
"setRootLevel",
|
||||
@@ -68,10 +68,10 @@ impl DebugTools {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ChannelSeparator(Instance);
|
||||
pub(crate) struct ChannelSeparator(Instance);
|
||||
|
||||
impl ChannelSeparator {
|
||||
pub fn new(image_reader: &ImageReader) -> Result<Self> {
|
||||
pub(crate) fn new(image_reader: &ImageReader) -> Result<Self> {
|
||||
let jvm = jvm();
|
||||
let channel_separator = jvm.create_instance(
|
||||
"loci.formats.ChannelSeparator",
|
||||
@@ -80,7 +80,7 @@ impl ChannelSeparator {
|
||||
Ok(ChannelSeparator(channel_separator))
|
||||
}
|
||||
|
||||
pub fn open_bytes(&self, index: i32) -> Result<Vec<u8>> {
|
||||
pub(crate) fn open_bytes(&self, index: i32) -> Result<Vec<u8>> {
|
||||
let bi8 = self.open_bi8(index)?;
|
||||
Ok(unsafe { std::mem::transmute::<Vec<i8>, Vec<u8>>(bi8) })
|
||||
}
|
||||
@@ -89,7 +89,7 @@ impl ChannelSeparator {
|
||||
method!(get_index, "getIndex", [z: i32|p, c: i32|p, t: i32|p] => i32|c);
|
||||
}
|
||||
|
||||
pub struct ImageReader(Instance);
|
||||
pub(crate) struct ImageReader(Instance);
|
||||
|
||||
impl Drop for ImageReader {
|
||||
fn drop(&mut self) {
|
||||
@@ -98,17 +98,27 @@ impl Drop for ImageReader {
|
||||
}
|
||||
|
||||
impl ImageReader {
|
||||
pub fn new() -> Result<Self> {
|
||||
pub(crate) fn new() -> Result<Self> {
|
||||
let reader = jvm().create_instance("loci.formats.ImageReader", InvocationArg::empty())?;
|
||||
Ok(ImageReader(reader))
|
||||
}
|
||||
|
||||
pub fn open_bytes(&self, index: i32) -> Result<Vec<u8>> {
|
||||
pub(crate) fn open_bytes(&self, index: i32) -> Result<Vec<u8>> {
|
||||
let bi8 = self.open_bi8(index)?;
|
||||
Ok(unsafe { std::mem::transmute::<Vec<i8>, Vec<u8>>(bi8) })
|
||||
}
|
||||
|
||||
pub(crate) fn ome_xml(&self) -> Result<String> {
|
||||
let mds = self.get_metadata_store()?;
|
||||
Ok(jvm()
|
||||
.chain(&mds)?
|
||||
.cast("loci.formats.ome.OMEPyramidStore")?
|
||||
.invoke("dumpXML", &[])?
|
||||
.to_rust()?)
|
||||
}
|
||||
|
||||
method!(set_metadata_store, "setMetadataStore", [ome_data: Instance]);
|
||||
method!(get_metadata_store, "getMetadataStore" => Instance);
|
||||
method!(set_id, "setId", [id: &str]);
|
||||
method!(set_series, "setSeries", [series: i32|p]);
|
||||
method!(open_bi8, "openBytes", [index: i32|p] => Vec<i8>|c);
|
||||
@@ -129,10 +139,10 @@ impl ImageReader {
|
||||
method!(close, "close");
|
||||
}
|
||||
|
||||
pub struct MetadataTools(Instance);
|
||||
pub(crate) struct MetadataTools(Instance);
|
||||
|
||||
impl MetadataTools {
|
||||
pub fn new() -> Result<Self> {
|
||||
pub(crate) fn new() -> Result<Self> {
|
||||
let meta_data_tools =
|
||||
jvm().create_instance("loci.formats.MetadataTools", InvocationArg::empty())?;
|
||||
Ok(MetadataTools(meta_data_tools))
|
||||
|
||||
43
src/lib.rs
43
src/lib.rs
@@ -144,7 +144,7 @@ pub struct Reader {
|
||||
image_reader: ImageReader,
|
||||
/// path to file
|
||||
pub path: PathBuf,
|
||||
/// which (if more) than 1 of the series in the file to open
|
||||
/// which (if more than 1) of the series in the file to open
|
||||
pub series: i32,
|
||||
/// size x (horizontal)
|
||||
pub size_x: usize,
|
||||
@@ -154,7 +154,7 @@ pub struct Reader {
|
||||
pub size_c: usize,
|
||||
/// size z (# slices)
|
||||
pub size_z: usize,
|
||||
/// size t (time/frames)
|
||||
/// size t (# time/frames)
|
||||
pub size_t: usize,
|
||||
/// pixel type ((u)int(8/16/32) or float(32/64))
|
||||
pub pixel_type: PixelType,
|
||||
@@ -214,6 +214,11 @@ impl Reader {
|
||||
})
|
||||
}
|
||||
|
||||
/// Get ome metadata as xml string
|
||||
pub fn ome_xml(&self) -> Result<String> {
|
||||
self.image_reader.ome_xml()
|
||||
}
|
||||
|
||||
fn deinterleave(&self, bytes: Vec<u8>, channel: usize) -> Result<Vec<u8>> {
|
||||
let chunk_size = match self.pixel_type {
|
||||
PixelType::INT8 => 1,
|
||||
@@ -311,7 +316,10 @@ mod tests {
|
||||
use rayon::prelude::*;
|
||||
|
||||
fn open(file: &str) -> Result<Reader> {
|
||||
let path = std::env::current_dir()?.join("tests").join("files").join(file);
|
||||
let path = std::env::current_dir()?
|
||||
.join("tests")
|
||||
.join("files")
|
||||
.join(file);
|
||||
Reader::new(&path, 0)
|
||||
}
|
||||
|
||||
@@ -363,4 +371,33 @@ mod tests {
|
||||
println!("{:?}", frames);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_sequence() -> Result<()> {
|
||||
let file = "YTL1841B2-2-1_1hr_DMSO_galinduction_1/Pos0/img_000000000_mScarlet_GFP-mSc-filter_004.tif";
|
||||
let reader = open(file)?;
|
||||
println!("reader: {:?}", reader);
|
||||
let frame = reader.get_frame(0, 4, 0)?;
|
||||
println!("frame: {:?}", frame);
|
||||
let frame = reader.get_frame(0, 2, 0)?;
|
||||
println!("frame: {:?}", frame);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_sequence1() -> Result<()> {
|
||||
let file = "4-Pos_001_002/img_000000000_Cy3-Cy3_filter_000.tif";
|
||||
let reader = open(file)?;
|
||||
println!("reader: {:?}", reader);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ome_xml() -> Result<()> {
|
||||
let file = "Experiment-2029.czi";
|
||||
let reader = open(file)?;
|
||||
let xml = reader.ome_xml()?;
|
||||
println!("{}", xml);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
49
src/py.rs
49
src/py.rs
@@ -1,14 +1,51 @@
|
||||
use crate::{Frame, Reader};
|
||||
use numpy::{IntoPyArray, PyArrayMethods, ToPyArray};
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::BoundObject;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Formats the sum of two numbers as string.
|
||||
#[pyfunction]
|
||||
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
|
||||
Ok((a + b).to_string())
|
||||
#[pyclass(subclass)]
|
||||
#[pyo3(name = "Reader")]
|
||||
#[derive(Debug)]
|
||||
struct PyReader {
|
||||
path: PathBuf,
|
||||
series: i32,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl PyReader {
|
||||
#[new]
|
||||
fn new(path: &str, series: usize) -> PyResult<Self> {
|
||||
Ok(PyReader {
|
||||
path: PathBuf::from(path),
|
||||
series: series as i32,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_frame<'py>(
|
||||
&self,
|
||||
py: Python<'py>,
|
||||
c: usize,
|
||||
z: usize,
|
||||
t: usize,
|
||||
) -> PyResult<Bound<'py, PyAny>> {
|
||||
let reader = Reader::new(&self.path, self.series)?; // TODO: prevent making a new Reader each time
|
||||
Ok(match reader.get_frame(c, z, t)? {
|
||||
Frame::INT8(arr) => arr.to_pyarray(py).into_any(),
|
||||
Frame::UINT8(arr) => arr.to_pyarray(py).into_any(),
|
||||
Frame::INT16(arr) => arr.to_pyarray(py).into_any(),
|
||||
Frame::UINT16(arr) => arr.to_pyarray(py).into_any(),
|
||||
Frame::INT32(arr) => arr.to_pyarray(py).into_any(),
|
||||
Frame::UINT32(arr) => arr.to_pyarray(py).into_any(),
|
||||
Frame::FLOAT(arr) => arr.to_pyarray(py).into_any(),
|
||||
Frame::DOUBLE(arr) => arr.to_pyarray(py).into_any(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A Python module implemented in Rust.
|
||||
#[pymodule]
|
||||
#[pyo3(name = "ndbioimage_rs")]
|
||||
fn ndbioimage_rs(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
|
||||
m.add_class::<PyReader>()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user