stack-3d/format_conversion/extract_zeiss_metadata.py

103 lines
4.1 KiB
Python
Raw Normal View History

2017-02-16 15:26:55 +00:00
#!/usr/bin/env python
"""
Extract and Parse Metadata from IMS/LSM/CZI files.
"""
from argparse import ArgumentParser
import os
import subprocess
import logging
import utility
import ome_schema
def extract_metadata(input_path, output_path):
"""
Extract OME metadata from the input file and write it out as a nicely formatted xml using
bftools. (http://www.openmicroscopy.org/site/support/bio-formats5.3/users/comlinetools/display.html)
"""
bf_tools_dir = os.getenv('BFTOOLS_DIR', os.getcwd()) + "/"
command = bf_tools_dir +"showinf -omexml-only -nopix " + input_path + " | " + bf_tools_dir + "xmlindent > " + output_path
p = subprocess.Popen(command, shell=True)
p.wait()
def get_metadata_as_class(input_xml_path):
"""
Return the OME metadata from the input XML file as a Python class. The class is automatically generated
using pyxbgen (http://pyxb.sourceforge.net/pyxbgen_cli.html) and the current OME XML Schema
(https://www.openmicroscopy.org/Schemas/OME/2016-06/ome.xsd).
If you need to use a newer schema you need to regenerate the file ome_schema.py by doing:
pip install pyxb
pyxbgen -m ome_schema -u https://www.openmicroscopy.org/Schemas/OME/2016-06/ome.xsd
where the web address points to the new schema. You can then access the elements of the OME XML as
instance attributes etc.
"""
xml = open(input_xml_path).read()
image_metadata = ome_schema.CreateFromDocument(xml)
return image_metadata
def integer_color_to_rgb(color):
"""
Convert integer color to (r,g,b)
"""
return ((color >> 16) & 255, (color >> 8) & 255, color & 255)
def print_metadata_overview(image_metadata):
"""
Print a reader-friendly metadata summary
"""
print "Number of Images: ", len(image_metadata.Image)
print "Image '0' - Name: ", image_metadata.Image[0].Name
print "Image '0' - Num Channels: ", image_metadata.Image[0].Pixels.SizeC
print "Image '0' - Num Times: ", image_metadata.Image[0].Pixels.SizeT
pixel_size_x = image_metadata.Image[0].Pixels.PhysicalSizeX
pixel_size_y = image_metadata.Image[0].Pixels.PhysicalSizeY
pixel_size_z = image_metadata.Image[0].Pixels.PhysicalSizeZ
pixel_unit_x = image_metadata.Image[0].Pixels.PhysicalSizeXUnit
pixel_unit_y = image_metadata.Image[0].Pixels.PhysicalSizeYUnit
pixel_unit_z = image_metadata.Image[0].Pixels.PhysicalSizeZUnit
print "Image '0' - Pixel Physical Size X: ", pixel_size_x, pixel_unit_x
print "Image '0' - Pixel Physical Size Y: ", pixel_size_y, pixel_unit_y
print "Image '0' - Pixel Physical Size Z: ", pixel_size_z, pixel_unit_z
print "Image '0' - Pixel Size X: ", image_metadata.Image[0].Pixels.SizeX
print "Image '0' - Pixel Size Y:", image_metadata.Image[0].Pixels.SizeY
print "Image '0' - Pixel Size Z:", image_metadata.Image[0].Pixels.SizeZ
print "Image '0' - Pixel Dimension Order: ", image_metadata.Image[0].Pixels.DimensionOrder
print "Image '0' - Pixel Bits: ", image_metadata.Image[0].Pixels.SignificantBits
for idx, eachChannel in enumerate(image_metadata.Image[0].Pixels.Channel):
print "Image '0' - Channel " +str(idx) + " Color: ", integer_color_to_rgb(eachChannel.Color)
if __name__ == "__main__":
# Do setup
tool_name = "extract_metadata"
utility.do_setup(tool_name)
logger1 = logging.getLogger('format_conversion.'+tool_name)
# Suppress XML Parse warnings
pyxb_logger = logging.getLogger('pyxb')
pyxb_logger.setLevel(logging.CRITICAL)
parser = ArgumentParser()
parser.add_argument("-i", "--input_file", type=str, help='Input file in a ZEISS format.')
parser.add_argument("-o", "--output_file", type=str, help='Output metadata file.')
parser.add_argument("--verbose", type=bool, help='Output a simple metadata summary.')
args = parser.parse_args()
logger1.info('Reading Metadata At: ' + args.input_file)
extract_metadata(args.input_file, args.output_file)
if(args.verbose):
image_metadata = get_metadata_as_class(args.output_file)
print_metadata_overview(image_metadata)
logger1.info('Completed Reading Metadata')