- bump ome-metadata dependency

- add extract-ome cli subcommand
This commit is contained in:
Wim Pomp
2026-01-04 17:03:14 +01:00
parent b1f8dd998b
commit d2c725440c
4 changed files with 43 additions and 41 deletions

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "ndbioimage" name = "ndbioimage"
version = "2026.1.1" version = "2026.1.2"
edition = "2024" edition = "2024"
rust-version = "1.85.1" rust-version = "1.85.1"
authors = ["Wim Pomp <w.pomp@nki.nl>"] authors = ["Wim Pomp <w.pomp@nki.nl>"]
@@ -36,7 +36,7 @@ serde_json = { version = "1", optional = true }
serde_with = "3" serde_with = "3"
tiffwrite = { version = "2025.12.0", optional = true} tiffwrite = { version = "2025.12.0", optional = true}
thread_local = "1" thread_local = "1"
ome-metadata = "0.3.2" ome-metadata = "0.4"
lazy_static = "1" lazy_static = "1"
thiserror = "2" thiserror = "2"
@@ -46,8 +46,8 @@ features = ["extension-module", "abi3-py310", "generate-import-lib", "anyhow"]
optional = true optional = true
[dev-dependencies] [dev-dependencies]
rayon = "1"
downloader = "0.2" downloader = "0.2"
rayon = "1"
regex = "1" regex = "1"
reqwest = { version = "0.13", features = ["blocking"] } reqwest = { version = "0.13", features = ["blocking"] }

View File

@@ -4,7 +4,7 @@ use ndarray::SliceInfoElem;
use ndbioimage::error::Error; use ndbioimage::error::Error;
#[cfg(feature = "movie")] #[cfg(feature = "movie")]
use ndbioimage::movie::MovieOptions; use ndbioimage::movie::MovieOptions;
use ndbioimage::reader::split_path_and_series; use ndbioimage::reader::{split_path_and_series, Reader};
#[cfg(feature = "tiff")] #[cfg(feature = "tiff")]
use ndbioimage::tiff::TiffOptions; use ndbioimage::tiff::TiffOptions;
use ndbioimage::view::View; use ndbioimage::view::View;
@@ -24,6 +24,11 @@ enum Commands {
#[arg(value_name = "FILE", num_args(1..))] #[arg(value_name = "FILE", num_args(1..))]
file: Vec<PathBuf>, file: Vec<PathBuf>,
}, },
/// save ome metadata as xml
ExtractOME {
#[arg(value_name = "FILE", num_args(1..))]
file: Vec<PathBuf>,
},
/// Save the image as tiff file /// Save the image as tiff file
#[cfg(feature = "tiff")] #[cfg(feature = "tiff")]
Tiff { Tiff {
@@ -113,6 +118,14 @@ pub(crate) fn main() -> Result<(), Error> {
println!("{}", view.summary()?); println!("{}", view.summary()?);
} }
} }
Commands::ExtractOME { file } => {
for f in file {
let (path, series) = split_path_and_series(f)?;
let reader = Reader::new(&path, series.unwrap_or(0))?;
let xml = reader.get_ome_xml()?;
std::fs::write(path.with_extension("xml"), xml)?;
}
}
#[cfg(feature = "tiff")] #[cfg(feature = "tiff")]
Commands::Tiff { Commands::Tiff {
file, file,

View File

@@ -9,18 +9,13 @@ impl Metadata for Ome {
fn get_instrument(&self) -> Option<&Instrument> { fn get_instrument(&self) -> Option<&Instrument> {
let instrument_id = self.get_image()?.instrument_ref.as_ref()?.id.clone(); let instrument_id = self.get_image()?.instrument_ref.as_ref()?.id.clone();
self.instrument self.instrument
.as_ref()?
.iter() .iter()
.find(|i| i.id == instrument_id) .find(|i| i.id == instrument_id)
} }
fn get_image(&self) -> Option<&Image> { fn get_image(&self) -> Option<&Image> {
if let Some(image) = &self.image { if let Some(image) = &self.image.first() {
if !image.is_empty() { Some(&image)
Some(&image[0])
} else {
None
}
} else { } else {
None None
} }
@@ -130,13 +125,12 @@ pub trait Metadata {
/// time interval in seconds for time-lapse images /// time interval in seconds for time-lapse images
fn time_interval(&self) -> Result<Option<f64>, Error> { fn time_interval(&self) -> Result<Option<f64>, Error> {
if let Some(pixels) = self.get_pixels() { if let Some(pixels) = self.get_pixels() {
if let Some(plane) = &pixels.plane { if let Some(t) = pixels.plane.iter().map(|p| p.the_t).max() {
if let Some(t) = plane.iter().map(|p| p.the_t).max() {
if t > 0 { if t > 0 {
let plane_a = plane let plane_a = pixels.plane
.iter() .iter()
.find(|p| (p.the_c == 0) && (p.the_z == 0) && (p.the_t == 0)); .find(|p| (p.the_c == 0) && (p.the_z == 0) && (p.the_t == 0));
let plane_b = plane let plane_b = pixels.plane
.iter() .iter()
.find(|p| (p.the_c == 0) && (p.the_z == 0) && (p.the_t == t)); .find(|p| (p.the_c == 0) && (p.the_z == 0) && (p.the_t == t));
if let (Some(a), Some(b)) = (plane_a, plane_b) { if let (Some(a), Some(b)) = (plane_a, plane_b) {
@@ -152,7 +146,6 @@ pub trait Metadata {
} }
} }
} }
}
Ok(None) Ok(None)
} }
@@ -160,8 +153,7 @@ pub trait Metadata {
fn exposure_time(&self, channel: usize) -> Result<Option<f64>, Error> { fn exposure_time(&self, channel: usize) -> Result<Option<f64>, Error> {
let c = channel as i32; let c = channel as i32;
if let Some(pixels) = self.get_pixels() { if let Some(pixels) = self.get_pixels() {
if let Some(plane) = &pixels.plane { if let Some(p) = pixels.plane
if let Some(p) = plane
.iter() .iter()
.find(|p| (p.the_c == c) && (p.the_z == 0) && (p.the_t == 0)) .find(|p| (p.the_c == c) && (p.the_z == 0) && (p.the_t == 0))
{ {
@@ -170,7 +162,6 @@ pub trait Metadata {
} }
} }
} }
}
Ok(None) Ok(None)
} }

View File

@@ -344,10 +344,8 @@ impl Reader {
/// Get ome metadata as ome structure /// Get ome metadata as ome structure
pub fn get_ome(&self) -> Result<Ome, Error> { pub fn get_ome(&self) -> Result<Ome, Error> {
let mut ome = self.ome_xml()?.parse::<Ome>()?; let mut ome = self.ome_xml()?.parse::<Ome>()?;
if let Some(image) = ome.image.as_ref() { if ome.image.len() > 1 {
if image.len() > 1 { ome.image = vec![ome.image[self.series].clone()];
ome.image = Some(vec![image[self.series].clone()]);
}
} }
Ok(ome) Ok(ome)
} }