- bump ome-metadata dependency
- add extract-ome cli subcommand
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ndbioimage"
|
||||
version = "2026.1.1"
|
||||
version = "2026.1.2"
|
||||
edition = "2024"
|
||||
rust-version = "1.85.1"
|
||||
authors = ["Wim Pomp <w.pomp@nki.nl>"]
|
||||
@@ -36,7 +36,7 @@ serde_json = { version = "1", optional = true }
|
||||
serde_with = "3"
|
||||
tiffwrite = { version = "2025.12.0", optional = true}
|
||||
thread_local = "1"
|
||||
ome-metadata = "0.3.2"
|
||||
ome-metadata = "0.4"
|
||||
lazy_static = "1"
|
||||
thiserror = "2"
|
||||
|
||||
@@ -46,8 +46,8 @@ features = ["extension-module", "abi3-py310", "generate-import-lib", "anyhow"]
|
||||
optional = true
|
||||
|
||||
[dev-dependencies]
|
||||
rayon = "1"
|
||||
downloader = "0.2"
|
||||
rayon = "1"
|
||||
regex = "1"
|
||||
reqwest = { version = "0.13", features = ["blocking"] }
|
||||
|
||||
|
||||
15
src/main.rs
15
src/main.rs
@@ -4,7 +4,7 @@ use ndarray::SliceInfoElem;
|
||||
use ndbioimage::error::Error;
|
||||
#[cfg(feature = "movie")]
|
||||
use ndbioimage::movie::MovieOptions;
|
||||
use ndbioimage::reader::split_path_and_series;
|
||||
use ndbioimage::reader::{split_path_and_series, Reader};
|
||||
#[cfg(feature = "tiff")]
|
||||
use ndbioimage::tiff::TiffOptions;
|
||||
use ndbioimage::view::View;
|
||||
@@ -24,6 +24,11 @@ enum Commands {
|
||||
#[arg(value_name = "FILE", num_args(1..))]
|
||||
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
|
||||
#[cfg(feature = "tiff")]
|
||||
Tiff {
|
||||
@@ -113,6 +118,14 @@ pub(crate) fn main() -> Result<(), Error> {
|
||||
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")]
|
||||
Commands::Tiff {
|
||||
file,
|
||||
|
||||
@@ -9,18 +9,13 @@ impl Metadata for Ome {
|
||||
fn get_instrument(&self) -> Option<&Instrument> {
|
||||
let instrument_id = self.get_image()?.instrument_ref.as_ref()?.id.clone();
|
||||
self.instrument
|
||||
.as_ref()?
|
||||
.iter()
|
||||
.find(|i| i.id == instrument_id)
|
||||
}
|
||||
|
||||
fn get_image(&self) -> Option<&Image> {
|
||||
if let Some(image) = &self.image {
|
||||
if !image.is_empty() {
|
||||
Some(&image[0])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if let Some(image) = &self.image.first() {
|
||||
Some(&image)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -130,24 +125,22 @@ pub trait Metadata {
|
||||
/// time interval in seconds for time-lapse images
|
||||
fn time_interval(&self) -> Result<Option<f64>, Error> {
|
||||
if let Some(pixels) = self.get_pixels() {
|
||||
if let Some(plane) = &pixels.plane {
|
||||
if let Some(t) = plane.iter().map(|p| p.the_t).max() {
|
||||
if t > 0 {
|
||||
let plane_a = plane
|
||||
.iter()
|
||||
.find(|p| (p.the_c == 0) && (p.the_z == 0) && (p.the_t == 0));
|
||||
let plane_b = plane
|
||||
.iter()
|
||||
.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_t), Some(b_t)) = (a.delta_t, b.delta_t) {
|
||||
return Ok(Some(
|
||||
(b.delta_t_unit.convert(&UnitsTime::s, b_t as f64)?
|
||||
- a.delta_t_unit.convert(&UnitsTime::s, a_t as f64)?)
|
||||
.abs()
|
||||
/ (t as f64),
|
||||
));
|
||||
}
|
||||
if let Some(t) = pixels.plane.iter().map(|p| p.the_t).max() {
|
||||
if t > 0 {
|
||||
let plane_a = pixels.plane
|
||||
.iter()
|
||||
.find(|p| (p.the_c == 0) && (p.the_z == 0) && (p.the_t == 0));
|
||||
let plane_b = pixels.plane
|
||||
.iter()
|
||||
.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_t), Some(b_t)) = (a.delta_t, b.delta_t) {
|
||||
return Ok(Some(
|
||||
(b.delta_t_unit.convert(&UnitsTime::s, b_t as f64)?
|
||||
- a.delta_t_unit.convert(&UnitsTime::s, a_t as f64)?)
|
||||
.abs()
|
||||
/ (t as f64),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,14 +153,12 @@ pub trait Metadata {
|
||||
fn exposure_time(&self, channel: usize) -> Result<Option<f64>, Error> {
|
||||
let c = channel as i32;
|
||||
if let Some(pixels) = self.get_pixels() {
|
||||
if let Some(plane) = &pixels.plane {
|
||||
if let Some(p) = plane
|
||||
.iter()
|
||||
.find(|p| (p.the_c == c) && (p.the_z == 0) && (p.the_t == 0))
|
||||
{
|
||||
if let Some(t) = p.exposure_time {
|
||||
return Ok(Some(p.exposure_time_unit.convert(&UnitsTime::s, t as f64)?));
|
||||
}
|
||||
if let Some(p) = pixels.plane
|
||||
.iter()
|
||||
.find(|p| (p.the_c == c) && (p.the_z == 0) && (p.the_t == 0))
|
||||
{
|
||||
if let Some(t) = p.exposure_time {
|
||||
return Ok(Some(p.exposure_time_unit.convert(&UnitsTime::s, t as f64)?));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,10 +344,8 @@ impl Reader {
|
||||
/// Get ome metadata as ome structure
|
||||
pub fn get_ome(&self) -> Result<Ome, Error> {
|
||||
let mut ome = self.ome_xml()?.parse::<Ome>()?;
|
||||
if let Some(image) = ome.image.as_ref() {
|
||||
if image.len() > 1 {
|
||||
ome.image = Some(vec![image[self.series].clone()]);
|
||||
}
|
||||
if ome.image.len() > 1 {
|
||||
ome.image = vec![ome.image[self.series].clone()];
|
||||
}
|
||||
Ok(ome)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user