- bump ome-metadata dependency
- add extract-ome cli subcommand
This commit is contained in:
@@ -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"] }
|
||||||
|
|
||||||
|
|||||||
15
src/main.rs
15
src/main.rs
@@ -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,
|
||||||
|
|||||||
@@ -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,24 +125,22 @@ 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 = pixels.plane
|
||||||
let plane_a = 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 = pixels.plane
|
||||||
let plane_b = 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) {
|
if let (Some(a_t), Some(b_t)) = (a.delta_t, b.delta_t) {
|
||||||
if let (Some(a_t), Some(b_t)) = (a.delta_t, b.delta_t) {
|
return Ok(Some(
|
||||||
return Ok(Some(
|
(b.delta_t_unit.convert(&UnitsTime::s, b_t as f64)?
|
||||||
(b.delta_t_unit.convert(&UnitsTime::s, b_t as f64)?
|
- a.delta_t_unit.convert(&UnitsTime::s, a_t as f64)?)
|
||||||
- a.delta_t_unit.convert(&UnitsTime::s, a_t as f64)?)
|
.abs()
|
||||||
.abs()
|
/ (t as f64),
|
||||||
/ (t as f64),
|
));
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,14 +153,12 @@ 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))
|
{
|
||||||
{
|
if let Some(t) = p.exposure_time {
|
||||||
if let Some(t) = p.exposure_time {
|
return Ok(Some(p.exposure_time_unit.convert(&UnitsTime::s, t as f64)?));
|
||||||
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
|
/// 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)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user