From 2eae542835e4d6ec7e133238cf289b987fcbcfce Mon Sep 17 00:00:00 2001 From: Alistair Muldal Date: Tue, 29 Mar 2016 18:24:16 +0100 Subject: [PATCH 01/10] automatically fix Python3 string handling using `python-modernize --no-six --future-unicode -w`, massive whitespace cleanup --- bioformats/__init__.py | 30 +- bioformats/formatreader.py | 170 +++---- bioformats/formatwriter.py | 186 ++++---- bioformats/metadatatools.py | 74 ++-- bioformats/noseplugin.py | 6 +- bioformats/omexml.py | 413 +++++++++--------- bioformats/tests/test_formatreader.py | 20 +- bioformats/tests/test_formatwriter.py | 18 +- .../tests/test_load_using_bioformats.py | 22 +- bioformats/tests/test_omexml.py | 242 +++++----- demo/demo.py | 8 +- docs/conf.py | 20 +- nosetests.py | 2 + setup.py | 10 +- 14 files changed, 625 insertions(+), 596 deletions(-) diff --git a/bioformats/__init__.py b/bioformats/__init__.py index 32fc333..84ceb2c 100644 --- a/bioformats/__init__.py +++ b/bioformats/__init__.py @@ -1,7 +1,7 @@ # Python-bioformats is distributed under the GNU General Public # License, but this file is licensed under the more permissive BSD # license. See the accompanying file LICENSE for details. -# +# # Copyright (c) 2009-2014 Broad Institute # All rights reserved. @@ -9,6 +9,8 @@ ''' +from __future__ import absolute_import, unicode_literals + try: from _version import __version__ except ImportError: @@ -30,18 +32,18 @@ to the Java virtual machine's class path.""" # See http://www.loci.wisc.edu/software/bio-formats -READABLE_FORMATS = ('al3d', 'am', 'amiramesh', 'apl', 'arf', 'avi', 'bmp', - 'c01', 'cfg', 'cxd', 'dat', 'dcm', 'dicom', 'dm3', 'dv', - 'eps', 'epsi', 'fits', 'flex', 'fli', 'gel', 'gif', 'grey', - 'hdr', 'html', 'hx', 'ics', 'ids', 'img', 'ims', 'ipl', - 'ipm', 'ipw', 'jp2', 'jpeg', 'jpg', 'l2d', 'labels', 'lei', - 'lif', 'liff', 'lim', 'lsm', 'mdb', 'mnc', 'mng', 'mov', - 'mrc', 'mrw', 'mtb', 'naf', 'nd', 'nd2', 'nef', 'nhdr', - 'nrrd', 'obsep', 'oib', 'oif', 'ome', 'ome.tiff', 'pcx', - 'pgm', 'pic', 'pict', 'png', 'ps', 'psd', 'r3d', 'raw', - 'scn', 'sdt', 'seq', 'sld', 'stk', 'svs', 'tif', 'tiff', +READABLE_FORMATS = ('al3d', 'am', 'amiramesh', 'apl', 'arf', 'avi', 'bmp', + 'c01', 'cfg', 'cxd', 'dat', 'dcm', 'dicom', 'dm3', 'dv', + 'eps', 'epsi', 'fits', 'flex', 'fli', 'gel', 'gif', 'grey', + 'hdr', 'html', 'hx', 'ics', 'ids', 'img', 'ims', 'ipl', + 'ipm', 'ipw', 'jp2', 'jpeg', 'jpg', 'l2d', 'labels', 'lei', + 'lif', 'liff', 'lim', 'lsm', 'mdb', 'mnc', 'mng', 'mov', + 'mrc', 'mrw', 'mtb', 'naf', 'nd', 'nd2', 'nef', 'nhdr', + 'nrrd', 'obsep', 'oib', 'oif', 'ome', 'ome.tiff', 'pcx', + 'pgm', 'pic', 'pict', 'png', 'ps', 'psd', 'r3d', 'raw', + 'scn', 'sdt', 'seq', 'sld', 'stk', 'svs', 'tif', 'tiff', 'tnb', 'txt', 'vws', 'xdce', 'xml', 'xv', 'xys', 'zvi') -WRITABLE_FORMATS = ('avi', 'eps', 'epsi', 'ics', 'ids', 'jp2', 'jpeg', 'jpg', +WRITABLE_FORMATS = ('avi', 'eps', 'epsi', 'ics', 'ids', 'jp2', 'jpeg', 'jpg', 'mov', 'ome', 'ome.tiff', 'png', 'ps', 'tif', 'tiff') OMETiffWriter = _formatwriter.make_ome_tiff_writer_class() @@ -51,7 +53,7 @@ from .metadatatools import createOMEXMLMetadata as create_ome_xml_metadata from .metadatatools import wrap_imetadata_object -import metadatatools as _metadatatools +from . import metadatatools as _metadatatools PixelType = _metadatatools.make_pixel_type_class() get_metadata_options = _metadatatools.get_metadata_options @@ -101,6 +103,6 @@ def init_logger(): if __name__ == "__main__": # Handy-dandy PyShell for exploring BioFormats / Rhino / ImageJ import wx.py.PyCrust - + wx.py.PyCrust.main() J.kill_vm() diff --git a/bioformats/formatreader.py b/bioformats/formatreader.py index c2dc6f4..37f2b11 100644 --- a/bioformats/formatreader.py +++ b/bioformats/formatreader.py @@ -1,7 +1,7 @@ # Python-bioformats is distributed under the GNU General Public # License, but this file is licensed under the more permissive BSD # license. See the accompanying file LICENSE for details. -# +# # Copyright (c) 2009-2014 Broad Institute # All rights reserved. @@ -9,7 +9,7 @@ Example: import bioformats.formatreader as biordr - + env = biordr.get_env() ChannelSeparator = biordr.make_reader_wrapper_class(env, 'loci/formats/ChannelSeparator') @@ -21,7 +21,9 @@ [cs.open_bytes(cs.getIndex(0,i,0)) for i in range(3)] ''' - + +from __future__ import absolute_import, unicode_literals + __version__ = "$Revision$" import logging @@ -52,13 +54,13 @@ def make_format_tools_class(): '''Get a wrapper for the loci/formats/FormatTools class - + The FormatTools class has many of the constants needed by other classes as statics. ''' class FormatTools(object): '''A wrapper for loci.formats.FormatTools - + See http://hudson.openmicroscopy.org.uk/job/LOCI/javadoc/loci/formats/FormatTools.html ''' env = jutil.get_env() @@ -74,23 +76,23 @@ class FormatTools(object): UINT16 = jutil.get_static_field(klass, 'UINT16', 'I') UINT32 = jutil.get_static_field(klass, 'UINT32', 'I') UINT8 = jutil.get_static_field(klass, 'UINT8', 'I') - + @classmethod def getPixelTypeString(cls, pixel_type): return jutil.static_call('loci/formats/FormatTools', 'getPixelTypeString', '(I)Ljava/lang/String;', pixel_type) - + return FormatTools def make_iformat_reader_class(): '''Bind a Java class that implements IFormatReader to a Python class - + Returns a class that implements IFormatReader through calls to the implemented class passed in. The returned class can be subclassed to provide additional bindings. ''' class IFormatReader(object): '''A wrapper for loci.formats.IFormatReader - + See http://hudson.openmicroscopy.org.uk/job/LOCI/javadoc/loci/formats/ImageReader.html ''' close = jutil.make_method('close','()V', @@ -144,13 +146,13 @@ class IFormatReader(object): 'Get the specified image plane as a byte array') openBytesXYWH = jutil.make_method('openBytes','(IIIII)[B', '''Get the specified image plane as a byte array - + (corresponds to openBytes(int no, int x, int y, int w, int h)) no - image plane number x,y - offset into image w,h - dimensions of image to return''') setSeries = jutil.make_method('setSeries','(I)V','Set the currently selected image series') - setGroupFiles = jutil.make_method('setGroupFiles', '(Z)V', + setGroupFiles = jutil.make_method('setGroupFiles', '(Z)V', 'Force reader to group or not to group files in a multi-file set') setMetadataStore = jutil.make_method('setMetadataStore', '(Lloci/formats/meta/MetadataStore;)V', @@ -166,9 +168,9 @@ class IFormatReader(object): 'isThisType', '(Ljava/lang/String;Z)Z', '''Return true if the named file is handled by this reader. - + filename - name of file - + allowOpen - True if the reader is allowed to open files when making its determination ''') @@ -176,17 +178,17 @@ class IFormatReader(object): 'isThisType', '(Lloci/common/RandomAccessInputStream;)Z', '''Return true if the stream might be parseable by this reader. - + stream - the RandomAccessInputStream to be used to read the file contents - + Note that both isThisTypeS and isThisTypeStream must return true for the type to truly be handled.''') def setId(self, path): '''Set the name of the file''' - jutil.call(self.o, 'setId', + jutil.call(self.o, 'setId', '(Ljava/lang/String;)V', path) - + getMetadataStore = jutil.make_method('getMetadataStore', '()Lloci/formats/meta/MetadataStore;', 'Retrieves the current metadata store for this reader.') get8BitLookupTable = jutil.make_method( @@ -198,7 +200,7 @@ def setId(self, path): def get_class_name(self): return jutil.call(jutil.call(self.o, 'getClass', '()Ljava/lang/Class;'), 'getName', '()Ljava/lang/String;') - + @property def suffixNecessary(self): if self.get_class_name() == 'loci.formats.in.JPKReader': @@ -209,7 +211,7 @@ def suffixNecessary(self): if field_id is None: return None return env.get_boolean_field(self.o, field_id) - + @property def suffixSufficient(self): if self.get_class_name() == 'loci.formats.in.JPKReader': @@ -220,8 +222,8 @@ def suffixSufficient(self): if field_id is None: return None return env.get_boolean_field(self.o, field_id) - - + + return IFormatReader def get_class_list(): @@ -239,13 +241,13 @@ class ClassList(object): get_classes = jutil.make_method( 'getClasses', '()[Ljava/lang/Class;', 'Get the classes in the list as an array') - + def __init__(self): env = jutil.get_env() class_name = 'loci/formats/ImageReader' klass = env.find_class(class_name) base_klass = env.find_class('loci/formats/IFormatReader') - self.o = jutil.make_instance("loci/formats/ClassList", + self.o = jutil.make_instance("loci/formats/ClassList", "(Ljava/lang/String;" "Ljava/lang/Class;" # base "Ljava/lang/Class;)V", # location in jar @@ -267,8 +269,8 @@ def __init__(self): self.remove_class(klass) self.add_class(klass) return ClassList() - - + + def make_image_reader_class(): '''Return an image reader class for the given Java environment''' env = jutil.get_env() @@ -277,7 +279,7 @@ def make_image_reader_class(): base_klass = env.find_class('loci/formats/IFormatReader') IFormatReader = make_iformat_reader_class() class_list = get_class_list() - + class ImageReader(IFormatReader): new_fn = jutil.make_new(class_name, '(Lloci/formats/ClassList;)V') def __init__(self): @@ -289,7 +291,7 @@ def __init__(self): '()Lloci/formats/IFormatReader;') def allowOpenToCheckType(self, allow): '''Allow the "isThisType" function to open files - + For the cluster, you want to tell potential file formats not to open the image file to test if it's their format. ''' @@ -306,8 +308,8 @@ def allowOpenToCheckType(self, allow): jexception = jutil.get_env().exception_occurred() if jexception is not None: raise jutil.JavaException(jexception) - - boolean_value = jutil.make_instance('java/lang/Boolean', + + boolean_value = jutil.make_instance('java/lang/Boolean', '(Z)V', allow) args = jutil.get_env().make_object_array(1, object_class) jexception = jutil.get_env().exception_occurred() @@ -320,26 +322,26 @@ def allowOpenToCheckType(self, allow): self.allowOpenToCheckType_method.invoke(self.o, args) return ImageReader - + def make_reader_wrapper_class(class_name): '''Make an ImageReader wrapper class - - class_name - the name of the wrapper class, for instance, + + class_name - the name of the wrapper class, for instance, "loci/formats/ChannelSeparator" - + You can instantiate an instance of the wrapper class like this: rdr = ChannelSeparator(ImageReader()) ''' IFormatReader = make_iformat_reader_class() class ReaderWrapper(IFormatReader): __doc__ = '''A wrapper for %s - + See http://hudson.openmicroscopy.org.uk/job/LOCI/javadoc/loci/formats/ImageReader.html '''%class_name new_fn = jutil.make_new(class_name, '(Lloci/formats/IFormatReader;)V') def __init__(self, rdr): self.new_fn(rdr) - + setId = jutil.make_method('setId', '(Ljava/lang/String;)V', 'Set the name of the data file') return ReaderWrapper @@ -347,7 +349,7 @@ def __init__(self, rdr): __has_omero_jars = None def has_omero_packages(): '''Return True if we can find the packages needed for OMERO - + In order to run OMERO, you'll need the OMERO client and ICE on your class path (not supplied with python-bioformats and specific to your server's version) @@ -357,11 +359,11 @@ def has_omero_packages(): class_loader = jutil.static_call( "java/lang/ClassLoader", "getSystemClassLoader", "()Ljava/lang/ClassLoader;") - for klass in ("Glacier2.PermissionDeniedException", + for klass in ("Glacier2.PermissionDeniedException", "loci.ome.io.OmeroReader", "omero.client"): try: jutil.call( - class_loader, "loadClass", + class_loader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;", klass) except: __has_omero_jars = False @@ -382,7 +384,7 @@ def has_omero_packages(): def set_omero_credentials(omero_server, omero_port, omero_username, omero_password): '''Set the credentials to be used to connect to the Omero server - + :param omero_server: DNS name of the server :param omero_port: use this port to connect to the server @@ -390,7 +392,7 @@ def set_omero_credentials(omero_server, omero_port, omero_username, omero_passwo :param omero_username: log on as this user :param omero_password: log on using this password - + The session ID is valid after this function is called. An exception is thrown if the login fails. :func:`bioformats.omero_logout()` can be called to log out. @@ -413,16 +415,16 @@ def set_omero_credentials(omero_server, omero_port, omero_username, omero_passwo user = __omero_username, password = omero_password)) return __omero_session_id - + def get_omero_credentials(): '''Return a pickleable dictionary representing the Omero credentials. - + Call :func:`bioformats.use_omero_credentials` in some other process to use this. ''' if __omero_session_id is None: omero_login() - + return dict(omero_server = __omero_server, omero_port = __omero_port, omero_user = __omero_username, @@ -439,21 +441,21 @@ def omero_login(): env = jutil.get_env() config = env.make_object_array(1, env.find_class("java/lang/String")) env.set_object_array_element( - config, 0, env.new_string(u"--Ice.Config=%s" % __omero_config_file)) + config, 0, env.new_string("--Ice.Config=%s" % __omero_config_file)) script = """ var client = Packages.omero.client(config); client.createSession(); client.getSessionId(); """ __omero_session_id = jutil.run_script(script, dict(config=config)) - elif all([x is not None for x in - __omero_server, __omero_port, __omero_username, __omero_password]): - set_omero_credentials(__omero_server, __omero_port, __omero_username, + elif all([x is not None for x in + (__omero_server, __omero_port, __omero_username, __omero_password)]): + set_omero_credentials(__omero_server, __omero_port, __omero_username, __omero_password) else: __omero_login_fn() return __omero_session_id - + def omero_logout(): '''Abandon any current Omero session. @@ -463,7 +465,7 @@ def omero_logout(): def use_omero_credentials(credentials): '''Use the session ID from an existing login as credentials. - + :param credentials: credentials from get_omero_credentials. ''' @@ -479,7 +481,7 @@ def use_omero_credentials(credentials): __omero_session_id = credentials.get(K_OMERO_SESSION_ID, None) __omero_config_file = credentials.get(K_OMERO_CONFIG_FILE, None) __omero_password = credentials.get(K_OMERO_PASSWORD, None) - + __omero_login_fn = None def set_omero_login_hook(fn): '''Set the function to be called when a login to Omero is needed. @@ -487,7 +489,7 @@ def set_omero_login_hook(fn): ''' global __omero_login_fn __omero_login_fn = fn - + def get_omero_reader(): '''Return an ``loci.ome.io.OMEROReader`` instance, wrapped as a FormatReader. @@ -502,13 +504,13 @@ def get_omero_reader(): """ if __omero_session_id is None: omero_login() - + jrdr = jutil.run_script(script, dict( server = __omero_server, port = __omero_port, username = __omero_username, sessionID = __omero_session_id)) - + rdr = make_iformat_reader_class()() rdr.o = jrdr return rdr @@ -519,21 +521,21 @@ def load_using_bioformats_url(url, c=None, z=0, t=0, series=None, index=None, wants_max_intensity = False, channel_names = None): '''Load a file from Bio-formats via a URL - + ''' with ImageReader(url=url) as rdr: return rdr.read(c, z, t, series, index, rescale, wants_max_intensity, channel_names) - + class ImageReader(object): '''Find the appropriate reader for a file. - + This class is meant to be harnessed to a scope like this: - + >>> with GetImageReader(path) as reader: >>> .... - + It uses `__enter__` and `__exit__` to manage the random access stream that can be used to cache the file contents in memory. @@ -547,7 +549,7 @@ def __init__(self, path=None, url=None, perform_init=True): if url is not None and url.lower().startswith(file_scheme): utf8_url = urllib.url2pathname(url[len(file_scheme):]) if isinstance(utf8_url, str): - path = unicode(utf8_url, 'utf-8') + path = str(utf8_url, 'utf-8') else: path = utf8_url self.path = path @@ -564,11 +566,11 @@ def __init__(self, path=None, url=None, perform_init=True): if perform_init: self.init_reader() return - except jutil.JavaException, e: + except jutil.JavaException as e: je = e.throwable if jutil.is_instance_of( je, "loci/formats/FormatException"): - je = jutil.call(je, "getCause", + je = jutil.call(je, "getCause", "()Ljava/lang/Throwable;") if jutil.is_instance_of( je, "Glacier2/PermissionDeniedException"): @@ -616,11 +618,11 @@ def __init__(self, path=None, url=None, perform_init=True): errno.ENOENT, "The file, \"%s\", does not exist." % path, path) - + self.stream = jutil.make_instance('loci/common/RandomAccessInputStream', - '(Ljava/lang/String;)V', + '(Ljava/lang/String;)V', self.path) - + self.rdr = None class_list = get_class_list() find_rdr_script = """ @@ -668,13 +670,13 @@ def __init__(self, path=None, url=None, perform_init=True): self.rdr.o = jrdr if perform_init: self.init_reader() - + def __enter__(self): return self - + def __exit__(self, type_class, value, traceback): self.close() - + def close(self): if hasattr(self, "rdr"): self.rdr.close() @@ -690,7 +692,7 @@ def close(self): # Run the Java garbage collector here. # jutil.static_call("java/lang/System", "gc","()V") - + def init_reader(self): mdoptions = metadatatools.get_metadata_options(metadatatools.ALL) self.rdr.setMetadataOptions(mdoptions) @@ -699,7 +701,7 @@ def init_reader(self): self.rdr.setMetadataStore(self.metadata) try: self.rdr.setId(self.path) - except jutil.JavaException, e: + except jutil.JavaException as e: logger.warn(e.message) for line in traceback.format_exc().split("\n"): logger.warn(line) @@ -710,7 +712,7 @@ def init_reader(self): raise if jutil.is_instance_of( je, "loci/formats/FormatException"): - je = jutil.call(je, "getCause", + je = jutil.call(je, "getCause", "()Ljava/lang/Throwable;") if jutil.is_instance_of( je, "java/io/FileNotFoundException"): @@ -722,8 +724,8 @@ def init_reader(self): errno.EINVAL, "Could not load the file as an image (see log for details)", self.path.encode('utf-8')) raise e2 - - + + def read(self, c = None, z = 0, t = 0, series = None, index = None, rescale = True, wants_max_intensity = False, channel_names = None, XYWH=None): '''Read a single plane from the image reader file. @@ -829,7 +831,7 @@ def read(self, c = None, z = 0, t = 0, series = None, index = None, elif self.rdr.getSizeC() > 1: images = [ np.frombuffer(openBytes_func(self.rdr.getIndex(z,i,t)), dtype) - for i in range(self.rdr.getSizeC())] + for i in range(self.rdr.getSizeC())] image = np.dstack(images) image.shape = (height, width, self.rdr.getSizeC()) if not channel_names is None: @@ -870,7 +872,7 @@ def read(self, c = None, z = 0, t = 0, series = None, index = None, index = self.rdr.getIndex(z,0,t) image = np.frombuffer(openBytes_func(index),dtype) image.shape = (height,width) - + if rescale: image = image.astype(np.float32) / float(scale) if wants_max_intensity: @@ -898,9 +900,9 @@ def read(self, c = None, z = 0, t = 0, series = None, index = None, def get_image_reader(key, path=None, url=None): '''Make or find an image reader appropriate for the given path - + path - pathname to the reader on disk. - + key - use this key to keep only a single cache member associated with that key open at a time. ''' @@ -921,7 +923,7 @@ def get_image_reader(key, path=None, url=None): def release_image_reader(key): '''Tell the cache that it should flush the reference for the given key - + ''' if key in __image_reader_key_cache: path, url = __image_reader_key_cache[key] @@ -939,31 +941,31 @@ def clear_image_reader_cache(): rdr.close() __image_reader_cache.clear() __image_reader_key_cache.clear() - + def load_using_bioformats(path, c=None, z=0, t=0, series=None, index=None, rescale = True, wants_max_intensity = False, channel_names = None): '''Load the given image file using the Bioformats library. - + :param path: path to the file :param z: the frame index in the `z` (depth) dimension. :param t: the frame index in the time dimension. :param channel_names: `None` if you don't want them, a list which will be filled if you do. - + :returns: either a 2-d (grayscale) or 3-d (2-d + 3 RGB planes) image. ''' - + with ImageReader(path=path) as rdr: return rdr.read(c, z, t, series, index, rescale, wants_max_intensity, channel_names) - + def get_omexml_metadata(path=None, url=None): '''Read the OME metadata from a file using Bio-formats - + :param path: path to the file - + :param groupfiles: utilize the groupfiles option to take the directory structure into account. diff --git a/bioformats/formatwriter.py b/bioformats/formatwriter.py index 5c42b39..3483dc5 100644 --- a/bioformats/formatwriter.py +++ b/bioformats/formatwriter.py @@ -1,7 +1,7 @@ # Python-bioformats is distributed under the GNU General Public # License, but this file is licensed under the more permissive BSD # license. See the accompanying file LICENSE for details. -# +# # Copyright (c) 2009-2014 Broad Institute # All rights reserved. @@ -30,6 +30,8 @@ ''' +from __future__ import absolute_import, print_function, unicode_literals + __version__ = "$Revision$" import numpy as np @@ -41,30 +43,30 @@ import javabridge as javabridge import bioformats.omexml as ome -def write_image(pathname, pixels, pixel_type, +def write_image(pathname, pixels, pixel_type, c = 0, z = 0, t = 0, size_c = 1, size_z = 1, size_t = 1, channel_names = None): """Write the image using bioformats. - + :param filename: save to this filename - + :param pixels: the image to save - + :param pixel_type: save using this pixel type - + :param c: the image's channel index - + :param z: the image's `z` index - + :param t: the image's `t` index - + :param size_c: # of channels in the stack - + :param size_z: # of z stacks - + :param size_t: # of timepoints in the stack - + :param channel_names: names of the channels (make up names if not present). """ @@ -108,14 +110,14 @@ def write_image(pathname, pixels, pixel_type, xml=xml, index=index, buffer=pixel_buffer)) - + def convert_pixels_to_buffer(pixels, pixel_type): '''Convert the pixels in the image into a buffer of the right pixel type - + pixels - a 2d monochrome or color image - + pixel_type - one of the OME pixel types - + returns a 1-d byte array ''' if pixel_type in (ome.PT_UINT8, ome.PT_INT8, ome.PT_BIT): @@ -133,17 +135,17 @@ def convert_pixels_to_buffer(pixels, pixel_type): buf = np.frombuffer(np.ascontiguousarray(pixels, as_dtype).data, np.uint8) env = jutil.get_env() return env.make_byte_array(buf) - + def make_iformat_writer_class(class_name): '''Bind a Java class that implements IFormatWriter to a Python class - + Returns a class that implements IFormatWriter through calls to the implemented class passed in. The returned class can be subclassed to provide additional bindings. ''' class IFormatWriter(object): '''A wrapper for loci.formats.IFormatWriter - + See http://hudson.openmicroscopy.org.uk/job/LOCI/javadoc/loci/formats/ImageWriter.html ''' canDoStacks = jutil.make_method('canDoStacks', '()Z', @@ -154,37 +156,37 @@ class IFormatWriter(object): 'Gets the current compression type.') getCompressionTypes = jutil.make_method('getCompressionTypes', '()[Ljava/lang/String;', 'Gets the available compression types.') - getFramesPerSecond = jutil.make_method('getFramesPerSecond', '()I', + getFramesPerSecond = jutil.make_method('getFramesPerSecond', '()I', 'Gets the frames per second to use when writing.') getMetadataRetrieve = jutil.make_method('getMetadataRetrieve', '()Lloci/formats/meta/MetadataRetrieve;', 'Retrieves the current metadata retrieval object for this writer.') - getPixelTypes = jutil.make_method('getPixelTypes', '()[I', + getPixelTypes = jutil.make_method('getPixelTypes', '()[I', 'Gets the supported pixel types.') -# getPixelTypes = jutil.make_method('getPixelTypes', '(Ljava/lang/String;)[I', +# getPixelTypes = jutil.make_method('getPixelTypes', '(Ljava/lang/String;)[I', # 'Gets the supported pixel types for the given codec.') - isInterleaved = jutil.make_method('isInterleaved', '()Z', + isInterleaved = jutil.make_method('isInterleaved', '()Z', 'Gets whether or not the channels in an image are interleaved.') - isSupportedType = jutil.make_method('isSupportedType', '(I)Z', + isSupportedType = jutil.make_method('isSupportedType', '(I)Z', 'Checks if the given pixel type is supported.') - saveBytes = jutil.make_method('saveBytes', '([BZ)V', + saveBytes = jutil.make_method('saveBytes', '([BZ)V', 'Saves the given byte array to the current file.') saveBytesIB = jutil.make_method('saveBytes', '(I[B)V', 'Saves bytes, first arg is image #') -# saveBytes = jutil.make_method('saveBytes', '([BIZZ)V', +# saveBytes = jutil.make_method('saveBytes', '([BIZZ)V', # 'Saves the given byte array to the given series in the current file.') - savePlane = jutil.make_method('savePlane', '(Ljava/lang/Object;Z)V', + savePlane = jutil.make_method('savePlane', '(Ljava/lang/Object;Z)V', 'Saves the given image plane to the current file.') -# savePlane = jutil.make_method('savePlane', '(Ljava/lang/Object;IZZ)V', +# savePlane = jutil.make_method('savePlane', '(Ljava/lang/Object;IZZ)V', # 'Saves the given image plane to the given series in the current file.') - setColorModel = jutil.make_method('setColorModel', '(Ljava/awt/image/ColorModel;)V', + setColorModel = jutil.make_method('setColorModel', '(Ljava/awt/image/ColorModel;)V', 'Sets the color model.') - setCompression = jutil.make_method('setCompression', '(Ljava/lang/String;)V', + setCompression = jutil.make_method('setCompression', '(Ljava/lang/String;)V', 'Sets the current compression type.') - setFramesPerSecond = jutil.make_method('setFramesPerSecond', '(I)V', + setFramesPerSecond = jutil.make_method('setFramesPerSecond', '(I)V', 'Sets the frames per second to use when writing.') - setInterleaved = jutil.make_method('setInterleaved', '(Z)V', + setInterleaved = jutil.make_method('setInterleaved', '(Z)V', 'Sets whether or not the channels in an image are interleaved.') - setMetadataRetrieve = jutil.make_method('setMetadataRetrieve', '(Lloci/formats/meta/MetadataRetrieve;)V', + setMetadataRetrieve = jutil.make_method('setMetadataRetrieve', '(Lloci/formats/meta/MetadataRetrieve;)V', 'Sets the metadata retrieval object from which to retrieve standardized metadata.') setValidBitsPerPixel = jutil.make_method( 'setValidBitsPerPixel', '(I)V', @@ -192,12 +194,12 @@ class IFormatWriter(object): setSeries = jutil.make_method( 'setSeries', '(I)V', '''Set the series for the image file - + series - the zero-based index of the image stack in the file, for instance in a multi-image tif.''') - + return IFormatWriter - + def make_image_writer_class(): '''Return an image writer class for the given Java environment''' env = jutil.get_env() @@ -208,7 +210,7 @@ def make_image_writer_class(): # # This uses the writers.txt file from inside the loci_tools.jar # - class_list = jutil.make_instance("loci/formats/ClassList", + class_list = jutil.make_instance("loci/formats/ClassList", "(Ljava/lang/String;" "Ljava/lang/Class;" # base "Ljava/lang/Class;)V", # location in jar @@ -217,30 +219,30 @@ class ImageWriter(IFormatWriter): new_fn = jutil.make_new(class_name, '(Lloci/formats/ClassList;)V') def __init__(self): self.new_fn(class_list) - - setId = jutil.make_method('setId', '(Ljava/lang/String;)V', + + setId = jutil.make_method('setId', '(Ljava/lang/String;)V', 'Sets the current file name.') addStatusListener = jutil.make_method('addStatusListener', '()Lloci/formats/StatusListener;', 'Adds a listener for status update events.') close = jutil.make_method('close','()V', 'Closes currently open file(s) and frees allocated memory.') - getFormat = jutil.make_method('getFormat', '()Ljava/lang/String;', + getFormat = jutil.make_method('getFormat', '()Ljava/lang/String;', 'Gets the name of this file format.') getNativeDataType = jutil.make_method('getNativeDataType', '()Ljava/lang/Class;', 'Returns the native data type of image planes for this reader, as returned by IFormatReader.openPlane(int, int, int, int, int) or IFormatWriter#saveData.') getStatusListeners = jutil.make_method('getStatusListeners', '()[Lloci/formats/StatusListener;', 'Gets a list of all registered status update listeners.') - getSuffixes = jutil.make_method('getSuffixes', '()Ljava/lang/String;', + getSuffixes = jutil.make_method('getSuffixes', '()Ljava/lang/String;', 'Gets the default file suffixes for this file format.') - getWriter = jutil.make_method('getWriter', '()Lloci/formats/IFormatWriter;', + getWriter = jutil.make_method('getWriter', '()Lloci/formats/IFormatWriter;', 'Gets the writer used to save the current file.') -# getWriter = jutil.make_method('getWriter', '(Ljava/lang/Class)Lloci/formats/IFormatWriter;', +# getWriter = jutil.make_method('getWriter', '(Ljava/lang/Class)Lloci/formats/IFormatWriter;', # 'Gets the file format writer instance matching the given class.') -# getWriter = jutil.make_method('getWriter', '(Ljava/lang/String;)Lloci/formats/IFormatWriter;', +# getWriter = jutil.make_method('getWriter', '(Ljava/lang/String;)Lloci/formats/IFormatWriter;', # 'Gets the writer used to save the given file.') - getWriters = jutil.make_method('getWriters', '()[Lloci/formats/IFormatWriter;', + getWriters = jutil.make_method('getWriters', '()[Lloci/formats/IFormatWriter;', 'Gets all constituent file format writers.') - isThisType = jutil.make_method('isThisType', '(Ljava/lang/String;)Z', + isThisType = jutil.make_method('isThisType', '(Ljava/lang/String;)Z', 'Checks if the given string is a valid filename for this file format.') removeStatusListener = jutil.make_method('removeStatusListener', '(Lloci/formats/StatusListener;)V', 'Saves the given byte array to the current file.') @@ -252,10 +254,10 @@ def make_ome_tiff_writer_class(): IFormatWriter = make_iformat_writer_class(class_name) class OMETiffWriter(IFormatWriter): - + def __init__(self): self.new_fn = jutil.make_new(self.class_name, '()V') - self.setId = jutil.make_method('setId', '(Ljava/lang/String;)V', + self.setId = jutil.make_method('setId', '(Ljava/lang/String;)V', 'Sets the current file name.') self.close = jutil.make_method( 'close','()V', @@ -263,34 +265,34 @@ def __init__(self): self.saveBytesIFD = jutil.make_method( 'saveBytes', '(I[BLloci/formats/tiff/IFD;)V', '''save a byte array to an image channel - + index - image index bytes - byte array to save ifd - a loci.formats.tiff.IFD instance that gives all of the IFD values associated with the channel''') - + self.new_fn() return OMETiffWriter - + def make_writer_wrapper_class(class_name): '''Make an ImageWriter wrapper class - + class_name - the name of the wrapper class - + You can instantiate an instance of the wrapper class like this: writer = XXX(ImageWriter()) ''' IFormatWriter = make_iformat_writer_class(class_name) class WriterWrapper(IFormatWriter): __doc__ = '''A wrapper for %s - + See http://hudson.openmicroscopy.org.uk/job/LOCI/javadoc/loci/formats/ImageWriter.html '''%class_name new_fn = jutil.make_new(class_name, '(Lloci/formats/IFormatWriter;)V') def __init__(self, writer): self.new_fn(writer) - + setId = jutil.make_method('setId', '(Ljava/lang/String;)V', 'Sets the current file name.') return WriterWrapper @@ -298,21 +300,21 @@ def __init__(self, writer): def make_format_writer_class(class_name): '''Make a FormatWriter wrapper class - + class_name - the name of a class that implements loci.formats.FormatWriter Known names in the loci.formats.out package: APNGWriter, AVIWriter, EPSWriter, ICSWriter, ImageIOWriter, JPEG2000Writer, JPEGWriter, LegacyQTWriter, OMETiffWriter, OMEXMLWriter, QTWriter, TiffWriter ''' - new_fn = jutil.make_new(class_name, + new_fn = jutil.make_new(class_name, '(Ljava/lang/String;Ljava/lang/String;)V') class FormatWriter(object): __doc__ = '''A wrapper for %s implementing loci.formats.FormatWriter See http://hudson.openmicroscopy.org.uk/job/LOCI/javadoc/loci/formats/FormatWriter'''%class_name def __init__(self): self.new_fn() - + canDoStacks = jutil.make_method('canDoStacks','()Z', 'Reports whether the writer can save multiple images to a single file') getColorModel = jutil.make_method('getColorModel', @@ -329,7 +331,7 @@ def __init__(self): getMetadataRetrieve = jutil.make_method('getMetadataRetrieve', '()Lloci/formats/meta/MetadataRetrieve;', 'Retrieves the current metadata retrieval object for this writer.') - + getPixelTypes = jutil.make_method('getPixelTypes', '()[I') isInterleaved = jutil.make_method('isInterleaved','()Z', @@ -358,7 +360,7 @@ def __init__(self): def getRGBColorSpace(): '''Get a Java object that represents an RGB color space - + See java.awt.color.ColorSpace: this returns the linear RGB color space ''' cs_linear_rgb = jutil.get_static_field('java/awt/color/ColorSpace', @@ -369,7 +371,7 @@ def getRGBColorSpace(): def getGrayColorSpace(): '''Get a Java object that represents an RGB color space - + See java.awt.color.ColorSpace: this returns the linear RGB color space ''' cs_gray = jutil.get_static_field('java/awt/color/ColorSpace', @@ -391,24 +393,24 @@ def getGrayColorSpace(): '''Constant for color model transfer type indicating integer per pixel''' TYPE_INT = 'TYPE_INT' -def getColorModel(color_space, - has_alpha=False, +def getColorModel(color_space, + has_alpha=False, is_alpha_premultiplied = False, transparency = OPAQUE, transfer_type = TYPE_BYTE): '''Return a java.awt.image.ColorModel color model - + color_space - a java.awt.color.ColorSpace such as returned by getGrayColorSpace or getRGBColorSpace - + has_alpha - True if alpha channel is specified - + is_alpha_premultiplied - True if other channel values have already been reduced by the alpha multiplier, False if the channel values are independent of the multiplier. - + transparency - one of BITMASK, OPAQUE or TRANSPARENT. - + transfer_type - one of TYPE_BYTE, TYPE_USHORT, TYPE_INT ''' jtransparency = jutil.get_static_field('java/awt/Transparency', @@ -424,9 +426,9 @@ def getColorModel(color_space, import wx import matplotlib.backends.backend_wxagg as mmmm import bioformats - from formatreader import * - from metadatatools import * - + from .formatreader import * + from .metadatatools import * + app = wx.PySimpleApp() # dlg = wx.FileDialog(None) @@ -442,10 +444,10 @@ def getColorModel(color_space, out_file = '/Users/afraser/Desktop/test_output.avi' try: os.remove(out_file) - print 'previous output file deleted' + print('previous output file deleted') except: - print 'no output file to delete' - + print('no output file to delete') + env = jutil.attach() ImageReader = make_image_reader_class() ChannelSeparator = make_reader_wrapper_class("loci/formats/ChannelSeparator") @@ -454,7 +456,7 @@ def getColorModel(color_space, # writer testing ImageWriter = make_image_writer_class() writer = ImageWriter() - + w = 400 h = 400 c = 3 @@ -463,7 +465,7 @@ def getColorModel(color_space, images = [] for tt in range(t): images += [(np.random.rand(w, h, c) * 255).astype('uint8')] - + imeta = createOMEXMLMetadata() meta = wrap_imetadata_object(imeta) meta.createRoot() @@ -476,33 +478,33 @@ def getColorModel(color_space, meta.setPixelsSizeZ(z, 0, 0) meta.setPixelsSizeT(t, 0, 0) meta.setLogicalChannelSamplesPerPixel(c, 0, 0) - - print 'big endian:', meta.getPixelsBigEndian(0, 0) - print 'dim order:', meta.getPixelsDimensionOrder(0, 0) - print 'pixel type:', meta.getPixelsPixelType(0, 0) - print 'size x:', meta.getPixelsSizeX(0, 0) - print 'size y:', meta.getPixelsSizeY(0, 0) - print 'size c:', meta.getPixelsSizeC(0, 0) - print 'size z:', meta.getPixelsSizeZ(0, 0) - print 'size t:', meta.getPixelsSizeT(0, 0) - print 'samples per pixel:', meta.getLogicalChannelSamplesPerPixel(0, 0) + + print('big endian:', meta.getPixelsBigEndian(0, 0)) + print('dim order:', meta.getPixelsDimensionOrder(0, 0)) + print('pixel type:', meta.getPixelsPixelType(0, 0)) + print('size x:', meta.getPixelsSizeX(0, 0)) + print('size y:', meta.getPixelsSizeY(0, 0)) + print('size c:', meta.getPixelsSizeC(0, 0)) + print('size z:', meta.getPixelsSizeZ(0, 0)) + print('size t:', meta.getPixelsSizeT(0, 0)) + print('samples per pixel:', meta.getLogicalChannelSamplesPerPixel(0, 0)) writer.setMetadataRetrieve(meta) writer.setId(out_file) for image in images: - if len(image.shape)==3 and image.shape[2] == 3: + if len(image.shape)==3 and image.shape[2] == 3: save_im = np.array([image[:,:,0], image[:,:,1], image[:,:,2]]).astype(np.uint8).flatten() else: save_im = image.astype(np.uint8).flatten() writer.saveBytes(env.make_byte_array(save_im), (image is images[-1])) writer.close() - - print 'Done writing image :)' + + print('Done writing image :)') # import PIL.Image as Image # im = Image.open(out_file, 'r') # im.show() - + jutil.detach() app.MainLoop() - - + + diff --git a/bioformats/metadatatools.py b/bioformats/metadatatools.py index 5b84a15..553228e 100644 --- a/bioformats/metadatatools.py +++ b/bioformats/metadatatools.py @@ -1,7 +1,7 @@ # Python-bioformats is distributed under the GNU General Public # License, but this file is licensed under the more permissive BSD # license. See the accompanying file LICENSE for details. -# +# # Copyright (c) 2009-2014 Broad Institute # All rights reserved. @@ -9,13 +9,15 @@ ''' +from __future__ import absolute_import, unicode_literals + __version__ = "$Revision$" from javabridge import jutil import bioformats def createOMEXMLMetadata(): - '''Creates an OME-XML metadata object using reflection, to avoid direct + '''Creates an OME-XML metadata object using reflection, to avoid direct dependencies on the optional loci.formats.ome package. ''' return jutil.static_call('loci/formats/MetadataTools', 'createOMEXMLMetadata', '()Lloci/formats/meta/IMetadata;') @@ -25,11 +27,11 @@ class MetadataStore(object): ''' ''' def __init__(self, o): self.o = o - + createRoot = jutil.make_method('createRoot', '()V', '') def setPixelsBigEndian(self, bigEndian, imageIndex, binDataIndex): '''Set the endianness for a particular image - + bigEndian - True for big-endian, False for little-endian imageIndex - index of the image in question from IFormatReader.get_index? binDataIndex - ??? @@ -58,34 +60,34 @@ def setPixelsDimensionOrder(self, dimension_order, imageIndex, binDataIndex): jutil.call(self.o, 'setPixelsDimensionOrder', '(Ljava/lang/String;II)V', dimension_order, imageIndex, binDataIndex) - + setPixelsPixelType = jutil.make_method( - 'setPixelsPixelType', '(Ljava/lang/String;II)V', + 'setPixelsPixelType', '(Ljava/lang/String;II)V', '''Sets the pixel storage type pixel_type - text representation of the type, e.g. "uint8" imageIndex - ? binDataIndex - ? - + WARNING: only available in BioFormats < 4.2 ''') setPixelsType = jutil.make_method( 'setPixelsType', '(Lome/xml/model/enums/PixelType;I)V', '''Set the pixel storage type - + pixel_type - one of the enumerated values from PixelType. imageIndex - ? - + See the ome.xml.model.enums.PixelType and make_pixel_type_class's PixelType for possible values. ''') - + def setPixelsSizeX(self, x, imageIndex, binDataIndex): try: jutil.call(self.o, 'setPixelsSizeX', '(Lome/xml/model/primitives/PositiveInteger;I)V', PositiveInteger(x), imageIndex) except jutil.JavaException: - jutil.call(self.o, 'setPixelsSizeX', + jutil.call(self.o, 'setPixelsSizeX', '(Ljava/lang/Integer;II)V', x, imageIndex, binDataIndex) def setPixelsSizeY(self, y, imageIndex, binDataIndex): @@ -94,16 +96,16 @@ def setPixelsSizeY(self, y, imageIndex, binDataIndex): '(Lome/xml/model/primitives/PositiveInteger;I)V', PositiveInteger(y), imageIndex) except jutil.JavaException: - jutil.call(self.o, 'setPixelsSizeY', + jutil.call(self.o, 'setPixelsSizeY', '(Ljava/lang/Integer;II)V', y, imageIndex, binDataIndex) - + def setPixelsSizeZ(self, z, imageIndex, binDataIndex): try: jutil.call(self.o, 'setPixelsSizeZ', '(Lome/xml/model/primitives/PositiveInteger;I)V', PositiveInteger(z), imageIndex) except jutil.JavaException: - jutil.call(self.o, 'setPixelsSizeZ', + jutil.call(self.o, 'setPixelsSizeZ', '(Ljava/lang/Integer;II)V', z, imageIndex, binDataIndex) def setPixelsSizeC(self, c, imageIndex, binDataIndex): @@ -112,7 +114,7 @@ def setPixelsSizeC(self, c, imageIndex, binDataIndex): '(Lome/xml/model/primitives/PositiveInteger;I)V', PositiveInteger(c), imageIndex) except jutil.JavaException: - jutil.call(self.o, 'setPixelsSizeC', + jutil.call(self.o, 'setPixelsSizeC', '(Ljava/lang/Integer;II)V', c, imageIndex, binDataIndex) def setPixelsSizeT(self, t, imageIndex, binDataIndex): @@ -121,9 +123,9 @@ def setPixelsSizeT(self, t, imageIndex, binDataIndex): '(Lome/xml/model/primitives/PositiveInteger;I)V', PositiveInteger(t), imageIndex) except jutil.JavaException: - jutil.call(self.o, 'setPixelsSizeT', + jutil.call(self.o, 'setPixelsSizeT', '(Ljava/lang/Integer;II)V', t, imageIndex, binDataIndex) - + def setLogicalChannelSamplesPerPixel(self, samplesPerPixel, imageIndex, channelIndex): 'For a particular LogicalChannel, sets number of channel components in the logical channel.' try: @@ -138,21 +140,21 @@ def setLogicalChannelSamplesPerPixel(self, samplesPerPixel, imageIndex, channelI setImageID = jutil.make_method( 'setImageID', '(Ljava/lang/String;I)V', '''Tag the indexed image with a name - + id - the name, for instance Image:0 imageIndex - the index of the image (series???) ''') setPixelsID = jutil.make_method( 'setPixelsID', '(Ljava/lang/String;I)V', '''Tag the pixels with a name (???) - + id - the name, for instance Pixels:0 imageIndex - the index of the image (???) ''') setChannelID = jutil.make_method( 'setChannelID', '(Ljava/lang/String;II)V', '''Give an ID name to the given channel - + id - the name of the channel imageIndex - (???) channelIndex - index of the channel to be ID'ed''') @@ -161,35 +163,35 @@ class MetadataRetrieve(object): ''' ''' def __init__(self, o): self.o = o - + getPixelsBigEndian = jutil.make_method('getPixelsBigEndian', '(II)Ljava/lang/Boolean;', 'For a particular Pixels, gets endianness of the pixels set.') - getPixelsDimensionOrder = jutil.make_method('getPixelsDimensionOrder', '(II)Ljava/lang/String;', + getPixelsDimensionOrder = jutil.make_method('getPixelsDimensionOrder', '(II)Ljava/lang/String;', 'For a particular Pixels, gets the dimension order of the pixels set.') - getPixelsPixelType = jutil.make_method('getPixelsPixelType', '(II)Ljava/lang/String;', + getPixelsPixelType = jutil.make_method('getPixelsPixelType', '(II)Ljava/lang/String;', 'For a particular Pixels, gets the pixel type.') - getPixelsSizeX = jutil.make_method('getPixelsSizeX', '(II)Ljava/lang/Integer;', + getPixelsSizeX = jutil.make_method('getPixelsSizeX', '(II)Ljava/lang/Integer;', 'For a particular Pixels, gets The size of an individual plane or section\'s X axis (width).') - getPixelsSizeY = jutil.make_method('getPixelsSizeY', '(II)Ljava/lang/Integer;', + getPixelsSizeY = jutil.make_method('getPixelsSizeY', '(II)Ljava/lang/Integer;', 'For a particular Pixels, gets The size of an individual plane or section\'s Y axis (height).') - getPixelsSizeZ = jutil.make_method('getPixelsSizeZ', '(II)Ljava/lang/Integer;', + getPixelsSizeZ = jutil.make_method('getPixelsSizeZ', '(II)Ljava/lang/Integer;', 'For a particular Pixels, gets number of optical sections per stack.') - getPixelsSizeC = jutil.make_method('getPixelsSizeC', '(II)Ljava/lang/Integer;', + getPixelsSizeC = jutil.make_method('getPixelsSizeC', '(II)Ljava/lang/Integer;', 'For a particular Pixels, gets number of channels per timepoint.') - getPixelsSizeT = jutil.make_method('getPixelsSizeT', '(II)Ljava/lang/Integer;', + getPixelsSizeT = jutil.make_method('getPixelsSizeT', '(II)Ljava/lang/Integer;', 'For a particular Pixels, gets number of timepoints.') getLogicalChannelSamplesPerPixel = jutil.make_method('getLogicalChannelSamplesPerPixel', '(II)Ljava/lang/Integer;', 'For a particular LogicalChannel, gets number of channel components in the logical channel.') getChannelName = jutil.make_method('getChannelName', '(II)Ljava/lang/String;', '''Get the name for a particular channel. - + imageIndex - image # to query (use C = 0) channelIndex - channel # to query''') getChannelID = jutil.make_method('getChannelID', '(II)Ljava/lang/String;', '''Get the OME channel ID for a particular channel. - + imageIndex - image # to query (use C = 0) channelIndex - channel # to query''') @@ -203,13 +205,13 @@ def __init__(self, o): MetadataStore.__init__(self, o) MetadataRetrieve.__init__(self, o) self.o = o - + return IMetadata(o) __pixel_type_class = None def make_pixel_type_class(): '''The class, ome.xml.model.enums.PixelType - + The Java class has enumerations for the various image data types such as UINT8 or DOUBLE ''' @@ -239,9 +241,9 @@ def __init__(self): def get_metadata_options(level): '''Get an instance of the MetadataOptions interface - + level - MINIMUM, NO_OVERLAYS or ALL to set the metadata retrieval level - + The object returned can be used in setMetadataOptions in a format reader. ''' jlevel = jutil.get_static_field('loci/formats/in/MetadataLevel', level, @@ -249,11 +251,11 @@ def get_metadata_options(level): return jutil.make_instance('loci/formats/in/DefaultMetadataOptions', '(Lloci/formats/in/MetadataLevel;)V', jlevel) - + def PositiveInteger(some_number): '''Return an instance of ome.xml.model.primitives.PositiveInteger - + some_number - the number to be wrapped up in the class ''' return jutil.make_instance('ome/xml/model/primitives/PositiveInteger', diff --git a/bioformats/noseplugin.py b/bioformats/noseplugin.py index aaa0d34..29680e8 100644 --- a/bioformats/noseplugin.py +++ b/bioformats/noseplugin.py @@ -1,10 +1,12 @@ # Python-bioformats is distributed under the GNU General Public # License, but this file is licensed under the more permissive BSD # license. See the accompanying file LICENSE for details. -# +# # Copyright (c) 2009-2014 Broad Institute # All rights reserved. +from __future__ import absolute_import, unicode_literals + import logging from nose.plugins import Plugin @@ -32,5 +34,5 @@ def begin(self): "()Lorg/apache/log4j/Logger;") warn_level = javabridge.get_static_field("org/apache/log4j/Level","WARN", "Lorg/apache/log4j/Level;") - javabridge.call(log4j_logger, "setLevel", "(Lorg/apache/log4j/Level;)V", + javabridge.call(log4j_logger, "setLevel", "(Lorg/apache/log4j/Level;)V", warn_level) diff --git a/bioformats/omexml.py b/bioformats/omexml.py index 996ea10..43506e8 100644 --- a/bioformats/omexml.py +++ b/bioformats/omexml.py @@ -1,7 +1,7 @@ # Python-bioformats is distributed under the GNU General Public # License, but this file is licensed under the more permissive BSD # license. See the accompanying file LICENSE for details. -# +# # Copyright (c) 2009-2014 Broad Institute # All rights reserved. @@ -9,11 +9,14 @@ """ +from __future__ import absolute_import, unicode_literals + import xml.etree.ElementTree from xml.etree import cElementTree as ElementTree from cStringIO import StringIO import datetime import logging +from functools import reduce logger = logging.getLogger(__file__) import re import uuid @@ -32,23 +35,23 @@ def xsd_now(): NS_RE = r"http://www.openmicroscopy.org/Schemas/(?P.*)/[0-9/-]" default_xml = """ - %(DEFAULT_NOW)s - - @@ -80,7 +83,7 @@ def xsd_now(): DO_XYTZC = "XYTZC" # # Original metadata corresponding to TIFF tags -# The text for these can be found in +# The text for these can be found in # loci.formats.in.BaseTiffReader.initStandardMetadata # '''IFD # 254''' @@ -196,9 +199,9 @@ def xsd_now(): def page_name_original_metadata(index): '''Get the key name for the page name metadata data for the indexed tiff page - + These are TIFF IFD #'s 285+ - + index - zero-based index of the page ''' return "PageName #%d" % index @@ -213,7 +216,7 @@ def set_text(node, text): def qn(namespace, tag_name): '''Return the qualified name for a given namespace and tag name - + This is the ElementTree representation of a qualified name ''' return "{%s}%s" % (namespace, tag_name) @@ -246,7 +249,7 @@ def get_int_attr(node, attribute): def make_text_node(parent, namespace, tag_name, text): '''Either make a new node and add the given text or replace the text - + parent - the parent node to the node to be created or found namespace - the namespace of the node's qualified name tag_name - the tag name of the node's qualified name @@ -260,51 +263,51 @@ def make_text_node(parent, namespace, tag_name, text): class OMEXML(object): '''Reads and writes OME-XML with methods to get and set it. - + The OMEXML class has four main purposes: to parse OME-XML, to output OME-XML, to provide a structured mechanism for inspecting OME-XML and to let the caller create and modify OME-XML. - + There are two ways to invoke the constructor. If you supply XML as a string or unicode string, the constructor will parse it and will use it as the base for any inspection and modification. If you don't supply XML, you'll get a bland OME-XML object which has a one-channel image. You can modify it programatically and get the modified OME-XML back out by calling to_xml. - + There are two ways to get at the XML. The arduous way is to get the root_node of the DOM and explore it yourself using the DOM API (http://docs.python.org/library/xml.dom.html#module-xml.dom). The easy way, where it's supported is to use properties on OMEXML and on some of its derived objects. For instance: - + >>> o = OMEXML() >>> print o.image().AcquisitionDate - + will get you the date that image # 0 was acquired. - + >>> o = OMEXML() >>> o.image().Name = "MyImage" - + will set the image name to "MyImage". - + You can add and remove objects using the "count" properties. Each of these handles hooking up and removing orphaned elements for you and should be less error prone than creating orphaned elements and attaching them. For instance, to create a three-color image: - + >>> o = OMEXML() >>> o.image().Pixels.channel_count = 3 >>> o.image().Pixels.Channel(0).Name = "Red" >>> o.image().Pixels.Channel(1).Name = "Green" >>> o.image().Pixels.Channel(2).Name = "Blue" - + See the `OME-XML schema documentation `_. ''' def __init__(self, xml=None): if xml is None: xml = default_xml - if isinstance(xml, unicode): + if isinstance(xml, str): xml = xml.encode("utf-8") self.dom = ElementTree.ElementTree(ElementTree.fromstring(xml)) @@ -323,11 +326,11 @@ def __str__(self): ElementTree.register_namespace(ns_key, ns) ElementTree.register_namespace("om", NS_ORIGINAL_METADATA) result = StringIO() - ElementTree.ElementTree(self.root_node).write(result, - encoding = "utf-8", + ElementTree.ElementTree(self.root_node).write(result, + encoding = "utf-8", method = "xml") return result.getvalue() - + def to_xml(self, indent="\t", newline="\n", encoding = "utf-8"): return str(self) @@ -337,11 +340,11 @@ def get_ns(self, key): @property def root_node(self): return self.dom.getroot() - + def get_image_count(self): '''The number of images (= series) specified by the XML''' return len(self.root_node.findall(qn(self.ns['ome'], "Image"))) - + def set_image_count(self, value): '''Add or remove image nodes as needed''' assert value > 0 @@ -370,17 +373,17 @@ def set_image_count(self, value): new_channel.ID = "Channel%d:0" % self.image_count new_channel.Name = new_channel.ID new_channel.SamplesPerPixel = 1 - + image_count = property(get_image_count, set_image_count) - + @property def plates(self): return self.PlatesDucktype(self.root_node) - + @property def structured_annotations(self): '''Return the structured annotations container - + returns a wrapping of OME/StructuredAnnotations. It creates the element if it doesn't exist. ''' @@ -389,7 +392,7 @@ def structured_annotations(self): node = ElementTree.SubElement( self.root_node, qn(self.ns['sa'], "StructuredAnnotations")) return self.StructuredAnnotations(node) - + class Image(object): '''Representation of the OME/Image element''' def __init__(self, node): @@ -399,10 +402,10 @@ def __init__(self, node): def get_ID(self): return self.node.get("ID") - + def set_ID(self, value): self.node.set("ID", value) - + ID = property(get_ID, set_ID) def get_Name(self): @@ -410,14 +413,14 @@ def get_Name(self): def set_Name(self, value): self.node.set("Name", value) Name = property(get_Name, set_Name) - + def get_AcquisitionDate(self): '''The date in ISO-8601 format''' acquired_date = self.node.find(qn(self.ns["ome"], "AcquisitionDate")) if acquired_date is None: return None return get_text(acquired_date) - + def set_AcquisitionDate(self, date): acquired_date = self.node.find(qn(self.ns["ome"], "AcquisitionDate")) if acquired_date is None: @@ -426,7 +429,7 @@ def set_AcquisitionDate(self, date): set_text(acquired_date, date) AcquisitionDate = property(get_AcquisitionDate, set_AcquisitionDate) - + @property def Pixels(self): '''The OME/Image/Pixels element. @@ -440,39 +443,39 @@ def Pixels(self): ''' return OMEXML.Pixels(self.node.find(qn(self.ns['ome'], "Pixels"))) - + def image(self, index=0): '''Return an image node by index''' return self.Image(self.root_node.findall(qn(self.ns['ome'], "Image"))[index]) - + class Channel(object): '''The OME/Image/Pixels/Channel element''' def __init__(self, node): self.node = node self.ns = get_namespaces(node) - + def get_ID(self): return self.node.get("ID") def set_ID(self, value): self.node.set("ID", value) ID = property(get_ID, set_ID) - + def get_Name(self): return self.node.get("Name") def set_Name(self, value): self.node.set("Name", value) Name = property(get_Name, set_Name) - + def get_SamplesPerPixel(self): return get_int_attr(self.node, "SamplesPerPixel") - + def set_SamplesPerPixel(self, value): self.node.set("SamplesPerPixel", str(value)) SamplesPerPixel = property(get_SamplesPerPixel, set_SamplesPerPixel) class Plane(object): '''The OME/Image/Pixels/Plane element - + The Plane element represents one 2-dimensional image plane. It has the Z, C and T indices of the plane and optionally has the X, Y, Z, exposure time and a relative time delta. @@ -484,39 +487,39 @@ def __init__(self, node): def get_TheZ(self): '''The Z index of the plane''' return get_int_attr(self.node, "TheZ") - + def set_TheZ(self, value): self.node.set("TheZ", str(value)) - + TheZ = property(get_TheZ, set_TheZ) - + def get_TheC(self): '''The channel index of the plane''' return get_int_attr(self.node, "TheC") - + def set_TheC(self, value): self.node.set("TheC", str(value)) - + TheC = property(get_TheC, set_TheC) - + def get_TheT(self): '''The T index of the plane''' return get_int_attr(self.node, "TheT") - + def set_TheT(self, value): self.node.set("TheT", str(value)) - + TheT = property(get_TheT, set_TheT) - + def get_DeltaT(self): '''# of seconds since the beginning of the experiment''' return get_float_attr(self.node, "DeltaT") - + def set_DeltaT(self, value): self.node.set("DeltaT", str(value)) - + DeltaT = property(get_DeltaT, set_DeltaT) - + @property def ExposureTime(self): '''Units are seconds. Duration of acquisition????''' @@ -524,40 +527,40 @@ def ExposureTime(self): if exposure_time is not None: return float(exposure_time) return None - + def get_PositionX(self): '''X position of stage''' position_x = self.node.get("PositionX") if position_x is not None: return float(position_x) return None - + def set_PositionX(self, value): self.node.set("PositionX", str(value)) - + PositionX = property(get_PositionX, set_PositionX) - + def get_PositionY(self): '''Y position of stage''' return get_float_attr(self.node, "PositionY") - + def set_PositionY(self, value): self.node.set("PositionY", str(value)) - + PositionY = property(get_PositionY, set_PositionY) - + def get_PositionZ(self): '''Z position of stage''' return get_float_attr(self.node, "PositionZ") - + def set_PositionZ(self, value): self.node.set("PositionZ", str(value)) - + PositionZ = property(get_PositionZ, set_PositionZ) - + class Pixels(object): '''The OME/Image/Pixels element - + The Pixels element represents the pixels in an OME image and, for an OME-XML encoded image, will actually contain the base-64 encoded pixel data. It has the X, Y, Z, C, and T extents of the image @@ -566,13 +569,13 @@ class Pixels(object): def __init__(self, node): self.node = node self.ns = get_namespaces(self.node) - + def get_ID(self): return self.node.get("ID") def set_ID(self, value): self.node.set("ID", value) ID = property(get_ID, set_ID) - + def get_DimensionOrder(self): '''The ordering of image planes in the file @@ -584,10 +587,10 @@ def get_DimensionOrder(self): def set_DimensionOrder(self, value): self.node.set("DimensionOrder", value) DimensionOrder = property(get_DimensionOrder, set_DimensionOrder) - + def get_PixelType(self): '''The pixel bit type, for instance PT_UINT8 - + The pixel type specifies the datatype used to encode pixels in the image data. You can use the PT_* constants to compare and set the pixel type. @@ -596,56 +599,56 @@ def get_PixelType(self): def set_PixelType(self, value): self.node.set("Type", value) PixelType = property(get_PixelType, set_PixelType) - + def get_SizeX(self): '''The dimensions of the image in the X direction in pixels''' return get_int_attr(self.node, "SizeX") def set_SizeX(self, value): self.node.set("SizeX", str(value)) SizeX = property(get_SizeX, set_SizeX) - + def get_SizeY(self): '''The dimensions of the image in the Y direction in pixels''' return get_int_attr(self.node, "SizeY") def set_SizeY(self, value): self.node.set("SizeY", str(value)) SizeY = property(get_SizeY, set_SizeY) - + def get_SizeZ(self): '''The dimensions of the image in the Z direction in pixels''' return get_int_attr(self.node, "SizeZ") - + def set_SizeZ(self, value): self.node.set("SizeZ", str(value)) SizeZ = property(get_SizeZ, set_SizeZ) - + def get_SizeT(self): '''The dimensions of the image in the T direction in pixels''' return get_int_attr(self.node, "SizeT") - + def set_SizeT(self, value): self.node.set("SizeT", str(value)) SizeT = property(get_SizeT, set_SizeT) - + def get_SizeC(self): '''The dimensions of the image in the C direction in pixels''' return get_int_attr(self.node, "SizeC") def set_SizeC(self, value): self.node.set("SizeC", str(value)) SizeC = property(get_SizeC, set_SizeC) - + def get_channel_count(self): '''The number of channels in the image - + You can change the number of channels in the image by setting the channel_count: - + pixels.channel_count = 3 pixels.Channel(0).Name = "Red" ... ''' return len(self.node.findall(qn(self.ns['ome'], "Channel"))) - + def set_channel_count(self, value): assert value > 0 channel_count = self.channel_count @@ -660,29 +663,29 @@ def set_channel_count(self, value): new_channel.ID = str(uuid.uuid4()) new_channel.Name = new_channel.ID new_channel.SamplesPerPixel = 1 - + channel_count = property(get_channel_count, set_channel_count) - + def Channel(self, index=0): '''Get the indexed channel from the Pixels element''' channel = self.node.findall(qn(self.ns['ome'], "Channel"))[index] return OMEXML.Channel(channel) - + def get_plane_count(self): '''The number of planes in the image - + An image with only one plane or an interleaved color plane will often not have any planes. - + You can change the number of planes in the image by setting the plane_count: - + pixels.plane_count = 3 pixels.Plane(0).TheZ=pixels.Plane(0).TheC=pixels.Plane(0).TheT=0 ... ''' return len(self.node.findall(qn(self.ns['ome'], "Plane"))) - + def set_plane_count(self, value): assert value >= 0 plane_count = self.plane_count @@ -694,61 +697,61 @@ def set_plane_count(self, value): for _ in range(plane_count, value): new_plane = OMEXML.Plane( ElementTree.SubElement(self.node, qn(self.ns['ome'], "Plane"))) - + plane_count = property(get_plane_count, set_plane_count) - + def Plane(self, index=0): '''Get the indexed plane from the Pixels element''' plane = self.node.findall(qn(self.ns['ome'], "Plane"))[index] return OMEXML.Plane(plane) - + class StructuredAnnotations(dict): '''The OME/StructuredAnnotations element - + Structured annotations let OME-XML represent metadata from other file formats, for example the tag metadata in TIFF files. The StructuredAnnotations element is a container for the structured annotations. - + Images can have structured annotation references. These match to the IDs of structured annotations in the StructuredAnnotations element. You can get the structured annotations in an OME-XML document using a dictionary interface to StructuredAnnotations. - + Pragmatically, TIFF tag metadata is stored as key/value pairs in OriginalMetadata annotations - in the context of CellProfiler, callers will be using these to read tag data that's not represented in OME-XML such as the bits per sample and min and max sample values. - + ''' - + def __init__(self, node): self.node = node self.ns = get_namespaces(self.node) - + def __getitem__(self, key): for child in self.node: if child.get("ID") == key: return child raise IndexError('ID "%s" not found' % key) - + def keys(self): return filter(lambda x: x is not None, [child.get("ID") for child in self.node]) - + def has_key(self, key): for child in self.node: if child.get("ID") == key: return True return False - + def add_original_metadata(self, key, value): '''Create an original data key/value pair - + key - the original metadata's key name, for instance OM_PHOTOMETRIC_INTERPRETATION - + value - the value, for instance, "RGB" - + returns the ID for the structured annotation. ''' xml_annotation = ElementTree.SubElement( @@ -767,12 +770,12 @@ def add_original_metadata(self, key, value): def iter_original_metadata(self): '''An iterator over the original metadata in structured annotations - + returns (, ()) - + where is the ID attribute of the annotation (which can be used to tie an annotation to an image) - + is the original metadata key, typically one of the OM_* names of a TIFF tag is the value for the metadata @@ -809,16 +812,16 @@ def iter_original_metadata(self): else: logger.warn("Original metadata was missing key or value:" + om_node.toxml()) return - + def has_original_metadata(self, key): '''True if there is an original metadata item with the given key''' - return any([k == key - for annotation_id, (k, v) + return any([k == key + for annotation_id, (k, v) in self.iter_original_metadata()]) - + def get_original_metadata_value(self, key, default=None): '''Return the value for a particular original metadata key - + key - key to search for default - default value to return if not found ''' @@ -826,12 +829,12 @@ def get_original_metadata_value(self, key, default=None): if k == key: return v return default - + def get_original_metadata_refs(self, ids): '''For a given ID, get the matching original metadata references - + ids - collection of IDs to match - + returns a dictionary of key to value ''' d = {} @@ -839,39 +842,39 @@ def get_original_metadata_refs(self, ids): if annotation_id in ids: d[k] = v return d - + @property def OriginalMetadata(self): return OMEXML.OriginalMetadata(self) - + class OriginalMetadata(dict): '''View original metadata as a dictionary - + Original metadata holds "vendor-specific" metadata including TIFF tag values. ''' def __init__(self, sa): '''Initialized with the structured_annotations class instance''' self.sa = sa - + def __getitem__(self, key): return self.sa.get_original_metadata_value(key) - + def __setitem__(self, key, value): self.sa.add_original_metadata(key, value) - + def __iter__(self): for annotation_id, (key, value) in self.sa.iter_original_metadata(): yield key - + def __len__(self): return len(list(self.sa_iter_original_metadata())) - + def keys(self): - return [key - for annotation_id, (key, value) + return [key + for annotation_id, (key, value) in self.sa.iter_original_metadata()] - + def has_key(self, key): for annotation_id, (k, value) in self.sa.iter_original_metadata(): if k == key: @@ -881,7 +884,7 @@ def has_key(self, key): def iteritems(self): for annotation_id, (key, value) in self.sa.iter_original_metadata(): yield key, value - + class PlatesDucktype(object): '''It looks like a list of plates''' def __init__(self, root): @@ -893,14 +896,14 @@ def __getitem__(self, key): if isinstance(key, slice): return [OMEXML.Plate(plate) for plate in plates[key]] return OMEXML.Plate(plates[key]) - + def __len__(self): return len(self.root.findall(qn(self.ns['spw'], "Plate"))) - + def __iter__(self): for plate in self.root.iterfind(qn(self.ns['spw'], "Plate")): yield OMEXML.Plate(plate) - + def newPlate(self, name, plate_id = str(uuid.uuid4())): new_plate_node = ElementTree.SubElement( self.root, qn(self.ns['spw'], "Plate")) @@ -908,114 +911,114 @@ def newPlate(self, name, plate_id = str(uuid.uuid4())): new_plate.ID = plate_id new_plate.Name = name return new_plate - + class Plate(object): '''The SPW:Plate element - + This represents the plate element of the SPW schema: http://www.openmicroscopy.org/Schemas/SPW/2007-06/ ''' def __init__(self, node): self.node = node self.ns = get_namespaces(self.node) - + def get_ID(self): return self.node.get("ID") - + def set_ID(self, value): self.node.set("ID", value) - + ID = property(get_ID, set_ID) - + def get_Name(self): return self.node.get("Name") - + def set_Name(self, value): self.node.set("Name", value) - + Name = property(get_Name, set_Name) - + def get_Status(self): return self.node.get("Status") - + def set_Status(self, value): self.node.set("Status", value) - + Status = property(get_Status, set_Status) - + def get_ExternalIdentifier(self): return self.node.get("ExternalIdentifier") - + def set_ExternalIdentifier(self, value): return self.node.set("ExternalIdentifier", value) - + ExternalIdentifier = property(get_ExternalIdentifier, set_ExternalIdentifier) - + def get_ColumnNamingConvention(self): # Consider a default if not defined of NC_NUMBER return self.node.get("ColumnNamingConvention") - + def set_ColumnNamingConvention(self, value): assert value in (NC_LETTER, NC_NUMBER) self.node.set("ColumnNamingConvention", value) - ColumnNamingConvention = property(get_ColumnNamingConvention, + ColumnNamingConvention = property(get_ColumnNamingConvention, set_ColumnNamingConvention) - + def get_RowNamingConvention(self): # Consider a default if not defined of NC_LETTER return self.node.get("RowNamingConvention") - + def set_RowNamingConvention(self, value): assert value in (NC_LETTER, NC_NUMBER) self.node.set("RowNamingConvention", value) RowNamingConvention = property(get_RowNamingConvention, set_RowNamingConvention) - + def get_WellOriginX(self): return get_float_attr(self.node, "WellOriginX") - + def set_WellOriginX(self, value): self.node.set("WellOriginX", str(value)) WellOriginX = property(get_WellOriginX, set_WellOriginX) - + def get_WellOriginY(self): return get_float_attr(self.node, "WellOriginY") - + def set_WellOriginY(self, value): self.node.set("WellOriginY", str(value)) WellOriginY = property(get_WellOriginY, set_WellOriginY) - + def get_Rows(self): return get_int_attr(self.node, "Rows") - + def set_Rows(self, value): self.node.set("Rows", str(value)) - + Rows = property(get_Rows, set_Rows) - + def get_Columns(self): return get_int_attr(self.node, "Columns") - + def set_Columns(self, value): self.node.set("Columns", str(value)) - + Columns = property(get_Columns, set_Columns) - + def get_Description(self): description = self.node.find(qn(self.ns['spw'], "Description")) if description is None: return None return get_text(description) - + def set_Description(self, text): make_text_node(self.node, NS_SPW, "Description", test) Description = property(get_Description, set_Description) - + def get_Well(self): '''The well dictionary / list''' return OMEXML.WellsDucktype(self) Well = property(get_Well) - + def get_well_name(self, well): '''Get a well's name, using the row and column convention''' result = "".join([ @@ -1025,13 +1028,13 @@ def get_well_name(self, well): in ((well.Row, self.RowNamingConvention or NC_LETTER), (well.Column, self.ColumnNamingConvention or NC_NUMBER))]) return result - + class WellsDucktype(dict): '''The WellsDucktype lets you retrieve and create wells - + The WellsDucktype looks like a dictionary but lets you reference the wells in a plate using indexing. Types of indexes: - + list indexing: e.g. plate.Well[14] gets the 14th well as it appears in the XML dictionary_indexing: @@ -1045,10 +1048,10 @@ def __init__(self, plate): self.plate_node = plate.node self.plate = plate self.ns = get_namespaces(self.plate_node) - + def __len__(self): return len(self.plate_node.findall(qn(self.ns['spw'], "Well"))) - + def __getitem__(self, key): all_wells = self.plate_node.findall(qn(self.ns['spw'], "Well")) if isinstance(key, slice): @@ -1069,10 +1072,10 @@ def __getitem__(self, key): if well.ID == key: return well return None - + def __iter__(self): '''Return the standard name for all wells on the plate - + for instance, 'B03' for a well with Row=1, Column=2 for a plate with the standard row and column naming convention ''' @@ -1081,10 +1084,10 @@ def __iter__(self): for w in all_wells: well.node = w yield self.plate.get_well_name(well) - + def new(self, row, column, well_id = str(uuid.uuid4())): '''Create a new well at the given row and column - + row - index of well's row column - index of well's column well_id - the ID attribute for the well @@ -1096,58 +1099,58 @@ def new(self, row, column, well_id = str(uuid.uuid4())): well.Column = column well.ID = well_id return well - + class Well(object): def __init__(self, node): self.node = node - + def get_Column(self): return get_int_attr(self.node, "Column") def set_Column(self, value): self.node.set("Column", str(value)) Column = property(get_Column, set_Column) - + def get_Row(self): return get_int_attr(self.node, "Row") def set_Row(self, value): self.node.set("Row", str(value)) Row = property(get_Row, set_Row) - + def get_ID(self): return self.node.get("ID") def set_ID(self, value): self.node.set("ID", value) ID = property(get_ID, set_ID) - + def get_Sample(self): return OMEXML.WellSampleDucktype(self.node) Sample = property(get_Sample) - + def get_ExternalDescription(self): return self.node.get("ExternalDescription") - + def set_ExternalDescription(self, value): return self.node.set("ExternalDescription", value) - + ExternalDescription = property(get_ExternalDescription, set_ExternalDescription) - + def get_ExternalIdentifier(self): return self.node.get("ExternalIdentifier") - + def set_ExternalIdentifier(self, value): return self.node.set("ExternalIdentifier", value) - + ExternalIdentifier = property(get_ExternalIdentifier, set_ExternalIdentifier) - + def get_Color(self): return int(self.node.get("Color")) - + def set_Color(self, value): self.node.set("Color", str(value)) - + class WellSampleDucktype(list): '''The WellSample elements in a well - + This is made to look like an indexable list so that you can do things like: wellsamples[0:2] @@ -1155,23 +1158,23 @@ class WellSampleDucktype(list): def __init__(self, well_node): self.well_node = well_node self.ns = get_namespaces(self.well_node) - + def __len__(self): return len(self.well_node.findall(qn(self.ns['spw'], "WellSample"))) - + def __getitem__(self, key): all_samples = self.well_node.findall(qn(self.ns['spw'], "WellSample")) if isinstance(key, slice): - return [OMEXML.WellSample(s) + return [OMEXML.WellSample(s) for s in all_samples[key]] return OMEXML.WellSample(all_samples[int(key)]) - + def __iter__(self): '''Iterate through the well samples.''' all_samples = self.well_node.findall(qn(self.ns['spw'], "WellSample")) for s in all_samples: yield OMEXML.WellSample(s) - + def new(self, wellsample_id = str(uuid.uuid4()), index = None): '''Create a new well sample ''' @@ -1182,13 +1185,13 @@ def new(self, wellsample_id = str(uuid.uuid4()), index = None): s = OMEXML.WellSample(new_node) s.ID = wellsample_id s.Index = index - + class WellSample(object): '''The WellSample is a location within a well''' def __init__(self, node): self.node = node self.ns = get_namespaces(self.node) - + def get_ID(self): return self.node.get("ID") def set_ID(self, value): @@ -1200,38 +1203,38 @@ def get_PositionX(self): def set_PositionX(self, value): self.node.set("PositionX", str(value)) PositionX = property(get_PositionX, set_PositionX) - + def get_PositionY(self): return get_float_attr(self.node, "PositionY") def set_PositionY(self, value): self.node.set("PositionY", str(value)) PositionY = property(get_PositionY, set_PositionY) - + def get_Timepoint(self): return self.node.get("Timepoint") - + def set_Timepoint(self, value): if isinstance(value, datetime.datetime): value = value.isoformat() self.node.set("Timepoint", value) Timepoint = property(get_Timepoint, set_Timepoint) - + def get_Index(self): return get_int_attr(self.node, "Index") def set_Index(self, value): self.node.set("Index", str(value)) - + Index = property(get_Index, set_Index) - + def get_ImageRef(self): '''Get the ID of the image of this site''' ref = self.node.find(qn(self.ns['spw'], "ImageRef")) if ref is None: return None return ref.get("ID") - + def set_ImageRef(self, value): '''Add a reference to the image of this site''' ref = self.node.find(qn(self.ns['spw'], "ImageRef")) @@ -1239,4 +1242,4 @@ def set_ImageRef(self, value): ref = ElementTree.SubElement(self.node, qn(self.ns['spw'], "ImageRef")) ref.set("ID", value) ImageRef = property(get_ImageRef, set_ImageRef) - + diff --git a/bioformats/tests/test_formatreader.py b/bioformats/tests/test_formatreader.py index 43109bb..d198d8e 100644 --- a/bioformats/tests/test_formatreader.py +++ b/bioformats/tests/test_formatreader.py @@ -1,7 +1,7 @@ # Python-bioformats is distributed under the GNU General Public # License, but this file is licensed under the more permissive BSD # license. See the accompanying file LICENSE for details. -# +# # Copyright (c) 2009-2014 Broad Institute # All rights reserved. @@ -9,6 +9,8 @@ ''' +from __future__ import absolute_import, unicode_literals + import numpy as np import os import re @@ -23,10 +25,10 @@ def setUp(self): J.start_vm(class_path=bioformats.JARS) J.attach() bioformats.init_logger() - + def tearDown(self): J.detach() - + def test_01_01_make_format_tools_class(self): FormatTools = F.make_format_tools_class() self.assertEqual(FormatTools.CAN_GROUP, 1) @@ -56,7 +58,7 @@ def test_02_01_make_image_reader(self): self.assertEqual(reader.getSizeZ(), 1) self.assertEqual(reader.getPixelType(), FormatTools.UINT8) self.assertEqual(reader.getRGBChannelCount(), 1) - + def test_03_01_read_tif(self): path = os.path.join(os.path.dirname(__file__), 'Channel1-01-A-01.tif') ImageReader = F.make_image_reader_class() @@ -92,7 +94,7 @@ def test_03_01_read_tif(self): [5, 2, 3, 3, 2, 2, 2, 3, 2, 2]], dtype=np.uint8) self.assertTrue(np.all(expected_0_10_0_10 == data[:10,:10])) self.assertTrue(np.all(expected_n10_n10 == data[-10:,-10:])) - + def test_03_02_load_using_bioformats(self): path = os.path.join(os.path.dirname(__file__), 'Channel1-01-A-01.tif') data = F.load_using_bioformats(path, rescale=False) @@ -153,7 +155,7 @@ def test_03_03_read_subimage_tif(self): [5, 2, 3, 3, 2, 2, 2, 3, 2, 2]], dtype=np.uint8) self.assertTrue(np.all(expected_0_10_0_10 == data_0_10_0_10)) # self.assertTrue(np.all(expected_n10_n10 == data[-10:,-10:])) - + # def test_03_03_load_using_bioformats_url(self): # data = F.load_using_bioformats_url( # "http://www.cellprofiler.org/linked_files/broad-logo.gif", @@ -172,11 +174,11 @@ def test_03_03_read_subimage_tif(self): # [ 23, 6, 1, 1, 0, 1, 55, 166, 100, 12]], # dtype=np.uint8) # self.assertTrue(np.all(expected_0_10_0_10 == data[:10,:10, 0])) - + def test_04_01_read_omexml_metadata(self): path = os.path.join(os.path.dirname(__file__), 'Channel1-01-A-01.tif') xml = F.get_omexml_metadata(path) pattern = r'<\s*Image\s+ID\s*=\s*"Image:0"\s+Name\s*=\s*"Channel1-01-A-01.tif"\s*>' self.assertTrue(re.search(pattern, xml)) - - + + diff --git a/bioformats/tests/test_formatwriter.py b/bioformats/tests/test_formatwriter.py index ffd470d..51df7e8 100644 --- a/bioformats/tests/test_formatwriter.py +++ b/bioformats/tests/test_formatwriter.py @@ -1,7 +1,7 @@ # Python-bioformats is distributed under the GNU General Public # License, but this file is licensed under the more permissive BSD # license. See the accompanying file LICENSE for details. -# +# # Copyright (c) 2009-2014 Broad Institute # All rights reserved. @@ -9,6 +9,8 @@ ''' +from __future__ import absolute_import, unicode_literals + import numpy as np import os import tempfile @@ -22,18 +24,18 @@ class TestFormatWriter(unittest.TestCase): def setUp(self): self.path = tempfile.mkdtemp() self.files = [] - + def get_tempfilename(self, suffix): fd, name = tempfile.mkstemp(suffix, self.path) self.files.append(name) os.close(fd) return name - + def tearDown(self): for filename in self.files: os.remove(filename) os.rmdir(self.path) - + def test_01_01_write_monochrome_8_bit_tif(self): r = np.random.RandomState() r.seed(101) @@ -42,7 +44,7 @@ def test_01_01_write_monochrome_8_bit_tif(self): W.write_image(path, img, OME.PT_UINT8) result = load_using_bioformats(path, rescale=False) np.testing.assert_array_equal(img, result) - + def test_01_02_write_monchrome_16_bit__tiff(self): r = np.random.RandomState() r.seed(102) @@ -51,7 +53,7 @@ def test_01_02_write_monchrome_16_bit__tiff(self): W.write_image(path, img, OME.PT_UINT16) result = load_using_bioformats(path, rescale=False) np.testing.assert_array_equal(img, result) - + def test_01_03_write_color_tiff(self): r = np.random.RandomState() r.seed(103) @@ -60,7 +62,7 @@ def test_01_03_write_color_tiff(self): W.write_image(path, img, OME.PT_UINT8) result = load_using_bioformats(path, rescale = False) np.testing.assert_array_equal(img, result) - + def test_02_01_write_movie(self): r = np.random.RandomState() r.seed(103) @@ -71,4 +73,4 @@ def test_02_01_write_movie(self): for i in range(img.shape[0]): result = load_using_bioformats(path, t=i, rescale = False) np.testing.assert_array_equal(img[i], result) - + diff --git a/bioformats/tests/test_load_using_bioformats.py b/bioformats/tests/test_load_using_bioformats.py index d1d72b2..208a467 100644 --- a/bioformats/tests/test_load_using_bioformats.py +++ b/bioformats/tests/test_load_using_bioformats.py @@ -1,10 +1,12 @@ # Python-bioformats is distributed under the GNU General Public # License, but this file is licensed under the more permissive BSD # license. See the accompanying file LICENSE for details. -# +# # Copyright (c) 2009-2014 Broad Institute # All rights reserved. +from __future__ import absolute_import, print_function, unicode_literals + import exceptions import os import unittest @@ -22,7 +24,7 @@ class TestLoadUsingBioformats(unittest.TestCase): def setUp(self): javabridge.attach() bioformats.init_logger() - + def tearDown(self): javabridge.detach() @@ -30,19 +32,19 @@ def test_load_using_bioformats(self): path = os.path.join(os.path.dirname(__file__), 'Channel1-01-A-01.tif') image, scale = load_image(path, rescale=False, wants_max_intensity=True) - print image.shape - + print(image.shape) + def test_file_not_found(self): # Regression test of issue #6 path = os.path.join(os.path.dirname(__file__), 'Channel5-01-A-01.tif') - self.assertRaises(exceptions.IOError, + self.assertRaises(exceptions.IOError, lambda :load_image(path)) class TestLoadUsingBioformatsURL(unittest.TestCase): def setUp(self): javabridge.attach() bioformats.init_logger() - + def tearDown(self): javabridge.detach() @@ -52,7 +54,7 @@ def test_01_01_open_file(self): image, scale = load_image_url( url, rescale=False, wants_max_intensity=True) self.assertEqual(image.shape[0], 640) - + def test_01_02_open_http(self): url = "https://github.com/CellProfiler/python-bioformats"+\ "/raw/master/bioformats/tests/Channel1-01-A-01.tif" @@ -66,9 +68,9 @@ def test_01_03_unicode_url(self): # raise an exception when converting URL to string # path = os.path.join(os.path.dirname(__file__), 'Channel1-01-A-01.tif') - url = u"file:" + urllib.pathname2url(path).encode("utf-8") + url = "file:" + urllib.pathname2url(path).encode("utf-8") image, scale = load_image_url( url, rescale=False, wants_max_intensity=True) self.assertEqual(image.shape[0], 640) - - + + diff --git a/bioformats/tests/test_omexml.py b/bioformats/tests/test_omexml.py index 63a8c13..2ca402d 100644 --- a/bioformats/tests/test_omexml.py +++ b/bioformats/tests/test_omexml.py @@ -1,7 +1,7 @@ # Python-bioformats is distributed under the GNU General Public # License, but this file is licensed under the more permissive BSD # license. See the accompanying file LICENSE for details. -# +# # Copyright (c) 2009-2014 Broad Institute # All rights reserved. @@ -9,6 +9,8 @@ """ +from __future__ import absolute_import, unicode_literals + import datetime import os import unittest @@ -26,29 +28,29 @@ class TestOMEXML(unittest.TestCase): @classmethod def setUpClass(cls): cls.GROUPFILES_XML = read_fully("groupfiles.xml") - + def test_00_00_init(self): o = O.OMEXML() self.assertEquals(o.root_node.tag, O.qn(o.get_ns("ome"), "OME")) self.assertEquals(o.image_count, 1) - + def test_01_01_read(self): for xml in (self.GROUPFILES_XML, TIFF_XML): o = O.OMEXML(xml) - + def test_02_01_iter_children(self): o = O.OMEXML(TIFF_XML) for node, expected_tag in zip( - o.root_node, + o.root_node, (O.qn(o.get_ns("ome"), "Image"), O.qn(o.get_ns("sa"), "StructuredAnnotations"))): self.assertEqual(node.tag, expected_tag) - + def test_02_02_get_text(self): o = O.OMEXML(TIFF_XML) ad = o.root_node.find( "/".join([O.qn(o.get_ns('ome'), x) for x in ("Image", "AcquisitionDate")])) self.assertEqual(O.get_text(ad), "2008-02-05T17:24:46") - + def test_02_04_set_text(self): o = O.OMEXML(TIFF_XML) ad = o.root_node.find("/".join( @@ -58,56 +60,56 @@ def test_02_04_set_text(self): self.assertEqual(O.get_text(im), "Foo") O.set_text(ad, "Bar") self.assertEqual(O.get_text(ad), "Bar") - + def test_03_01_get_image_count(self): for xml, count in ((self.GROUPFILES_XML, 576), (TIFF_XML,1)): o = O.OMEXML(xml) self.assertEqual(o.image_count, count) - + def test_03_02_set_image_count(self): o = O.OMEXML(TIFF_XML) o.image_count = 2 self.assertEqual(len(o.root_node.findall(O.qn(o.get_ns("ome"), "Image"))), 2) - + def test_03_03_image(self): o = O.OMEXML(self.GROUPFILES_XML) self.assertEquals(o.image_count, 576) for i in range(576): im = o.image(i) self.assertEqual(im.node.get("ID"), "Image:%d" % i) - + def test_03_04_structured_annotations(self): o = O.OMEXML(TIFF_XML) - self.assertEqual(o.structured_annotations.node.tag, + self.assertEqual(o.structured_annotations.node.tag, O.qn(o.get_ns("sa"), "StructuredAnnotations")) - + def test_04_01_image_get_id(self): o = O.OMEXML(TIFF_XML) self.assertEquals(o.image(0).ID, "Image:0") - + def test_04_02_image_set_id(self): o = O.OMEXML(TIFF_XML) o.image(0).ID = "Foo" self.assertEquals(o.image(0).node.get("ID"), "Foo") - + def test_04_03_image_get_name(self): o = O.OMEXML(TIFF_XML) self.assertEquals(o.image(0).Name, "Channel1-01-A-01.tif") - + def test_04_04_image_set_name(self): o = O.OMEXML(TIFF_XML) o.image(0).Name = "Foo" self.assertEquals(o.image(0).node.get("Name"), "Foo") - + def test_04_05_image_get_acquisition_date(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).AcquisitionDate, "2008-02-05T17:24:46") - + def test_04_06_image_set_acquisition_date(self): o = O.OMEXML(TIFF_XML) o.image(0).AcquisitionDate = "2011-12-21T11:04:14.903000" self.assertEqual(o.image(0).AcquisitionDate, "2011-12-21T11:04:14.903000") - + def test_04_07_image_1_acquisition_date(self): # regression test of #38 o = O.OMEXML() @@ -118,116 +120,116 @@ def test_04_07_image_1_acquisition_date(self): o.image(1).AcquisitionDate = date_2 self.assertEqual(o.image(0).AcquisitionDate, date_1) self.assertEqual(o.image(1).AcquisitionDate, date_2) - + def test_05_01_pixels_get_id(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).Pixels.ID, "Pixels:0") - + def test_05_02_pixels_set_id(self): o = O.OMEXML(TIFF_XML) o.image(0).Pixels.ID = "Foo" self.assertEqual(o.image(0).Pixels.ID, "Foo") - + def test_05_03_pixels_get_dimension_order(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).Pixels.DimensionOrder, O.DO_XYCZT) - + def test_05_04_pixels_set_dimension_order(self): o = O.OMEXML(TIFF_XML) o.image(0).Pixels.DimensionOrder = O.DO_XYZCT self.assertEqual(o.image(0).Pixels.DimensionOrder, O.DO_XYZCT) - + def test_05_05_pixels_get_pixel_type(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).Pixels.PixelType, O.PT_UINT8) - + def test_05_06_pixels_set_pixel_type(self): o = O.OMEXML(TIFF_XML) o.image(0).Pixels.PixelType = O.PT_FLOAT self.assertEqual(o.image(0).Pixels.PixelType, O.PT_FLOAT) - + def test_05_07_pixels_get_size_x(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).Pixels.SizeX, 640) - + def test_05_08_pixels_set_size_x(self): o = O.OMEXML(TIFF_XML) o.image(0).Pixels.SizeX = 480 self.assertEqual(o.image(0).Pixels.SizeX, 480) - + def test_05_09_pixels_get_size_y(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).Pixels.SizeY, 512) - + def test_05_10_pixels_set_size_y(self): o = O.OMEXML(TIFF_XML) o.image(0).Pixels.SizeY = 480 self.assertEqual(o.image(0).Pixels.SizeY, 480) - + def test_05_11_pixels_get_size_z(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).Pixels.SizeZ, 1) - + def test_05_12_pixels_set_size_z(self): o = O.OMEXML(TIFF_XML) o.image(0).Pixels.SizeZ = 2 self.assertEqual(o.image(0).Pixels.SizeZ, 2) - + def test_05_13_pixels_get_size_c(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).Pixels.SizeC, 2) - + def test_05_14_pixels_set_size_c(self): o = O.OMEXML(TIFF_XML) o.image(0).Pixels.SizeC = 3 self.assertEqual(o.image(0).Pixels.SizeC, 3) - + def test_05_15_pixels_get_size_t(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).Pixels.SizeT, 3) - + def test_05_16_pixels_set_size_t(self): o = O.OMEXML(TIFF_XML) o.image(0).Pixels.SizeT = 1 self.assertEqual(o.image(0).Pixels.SizeT, 1) - + def test_05_17_pixels_get_channel_count(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).Pixels.channel_count, 1) - + def test_05_18_pixels_set_channel_count(self): o = O.OMEXML(TIFF_XML) o.image(0).Pixels.channel_count = 2 self.assertEqual( len(o.image(0).Pixels.node.findall(O.qn(o.get_ns("ome"), "Channel"))), 2) - + def test_06_01_channel_get_id(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).Pixels.Channel(0).ID, "Channel:0:0") - + def test_06_02_channel_set_id(self): o = O.OMEXML(TIFF_XML) o.image(0).Pixels.Channel(0).ID = "Red" self.assertEqual(o.image(0).Pixels.Channel(0).ID, "Red") - + def test_06_03_channel_get_name(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).Pixels.Channel(0).Name, "Actin") - + def test_06_04_channel_set_Name(self): o = O.OMEXML(TIFF_XML) o.image(0).Pixels.Channel(0).Name = "PI" self.assertEqual(o.image(0).Pixels.Channel(0).Name, "PI") - + def test_06_04_channel_get_samples_per_pixel(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).Pixels.Channel(0).SamplesPerPixel, 1) - + def test_06_04_channel_set_samples_per_pixel(self): o = O.OMEXML(TIFF_XML) o.image(0).Pixels.Channel(0).SamplesPerPixel = 3 self.assertEqual(o.image(0).Pixels.Channel(0).SamplesPerPixel, 3) - + def test_07_01_sa_get_item(self): o = O.OMEXML(TIFF_XML) a = o.structured_annotations["Annotation:4"] @@ -242,18 +244,18 @@ def test_07_01_sa_get_item(self): values = oms[0].findall(O.qn(O.NS_ORIGINAL_METADATA, "Value")) self.assertEqual(len(values), 1) self.assertEqual(O.get_text(values[0]), "72") - + def test_07_02_01_sa_keys(self): keys = O.OMEXML(TIFF_XML).structured_annotations.keys() for i in range(21): self.assertTrue("Annotation:%d" %i in keys) - + def test_07_02_02_sa_has_key(self): o = O.OMEXML(TIFF_XML) for i in range(20): - self.assertTrue(o.structured_annotations.has_key("Annotation:%d" %i)) - self.assertFalse(o.structured_annotations.has_key("Foo")) - + self.assertTrue("Annotation:%d" %i in o.structured_annotations) + self.assertFalse("Foo" in o.structured_annotations) + def test_07_03_om_getitem(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.structured_annotations.OriginalMetadata["MetaMorph"], "no") @@ -269,9 +271,9 @@ def test_07_04_02_om_has_key(self): o = O.OMEXML(TIFF_XML) om = o.structured_annotations.OriginalMetadata for k in ("DateTime", "Software", "YResolution"): - self.assertTrue(om.has_key(k)) - self.assertFalse(om.has_key("Foo")) - + self.assertTrue(k in om) + self.assertFalse("Foo" in om) + def test_07_05_om_setitem(self): o = O.OMEXML() o.structured_annotations.OriginalMetadata["Foo"] = "Bar" @@ -288,22 +290,22 @@ def test_07_05_om_setitem(self): v = om[0].findall(O.qn(O.NS_ORIGINAL_METADATA, "Value")) self.assertEqual(len(v), 1) self.assertEqual(O.get_text(v[0]), "Bar") - + def test_08_01_get_plate(self): o = O.OMEXML(self.GROUPFILES_XML) plate = o.plates[0] self.assertEqual(plate.ID, "Plate:0") - + def test_08_02_get_plate_count(self): o = O.OMEXML(self.GROUPFILES_XML) self.assertEqual(len(o.plates), 1) - + def test_08_02_new_plate(self): o = O.OMEXML(self.GROUPFILES_XML) o.plates.newPlate("MyPlate", "Plate:1") self.assertEqual(o.plates[1].ID, "Plate:1") self.assertEqual(o.plates[1].Name, "MyPlate") - + def test_08_03_plate_iter(self): o = O.OMEXML(self.GROUPFILES_XML) nplates = 5 @@ -311,7 +313,7 @@ def test_08_03_plate_iter(self): o.plates.newPlate("MyPlate%d" %i, "Plate:%d" % i) for i, plate in enumerate(o.plates): self.assertEqual(plate.ID, "Plate:%d" %i) - + def test_08_04_plate_slice(self): o = O.OMEXML(self.GROUPFILES_XML) for i in range(1, 5): @@ -320,70 +322,70 @@ def test_08_04_plate_slice(self): self.assertEqual(len(plates), 2) self.assertTrue(all([plate.ID == "Plate:%d" % (i+2) for i, plate in enumerate(plates)])) - + plates = o.plates[-4:4] self.assertEqual(len(plates), 3) self.assertTrue(all([plate.ID == "Plate:%d" % (i+1) for i, plate in enumerate(plates)])) - + def test_09_01_plate_get_name(self): o = O.OMEXML(self.GROUPFILES_XML) self.assertEqual(o.plates[0].Name, "TimePoint_1") - + def test_09_02_plate_set_status(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.Status = "Gronked" self.assertEqual(plate.node.get("Status"),"Gronked") - + def test_09_03_plate_get_status(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.node.set("Status", "Gronked") self.assertEqual(plate.Status,"Gronked") - + def test_09_04_plate_get_external_identifier(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.node.set("ExternalIdentifier", "xyz") self.assertEqual(plate.ExternalIdentifier, "xyz") - + def test_09_05_plate_set_external_identifier(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.ExternalIdentifier = "xyz" self.assertEqual(plate.node.get("ExternalIdentifier"), "xyz") - + def test_09_06_plate_get_column_naming_convention(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.node.set("ColumnNamingConvention", O.NC_LETTER) self.assertEqual(plate.ColumnNamingConvention, O.NC_LETTER) - + def test_09_07_plate_set_column_naming_convention(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.ColumnNamingConvention = O.NC_NUMBER self.assertEqual(plate.ColumnNamingConvention, O.NC_NUMBER) - + def test_09_08_plate_get_row_naming_convention(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.node.set("RowNamingConvention", O.NC_LETTER) self.assertEqual(plate.RowNamingConvention, O.NC_LETTER) - + def test_09_09_plate_set_row_naming_convention(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.RowNamingConvention = O.NC_NUMBER self.assertEqual(plate.RowNamingConvention, O.NC_NUMBER) - + def test_09_10_plate_get_well_origin_x(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.node.set("WellOriginX", "4.8") self.assertEqual(plate.WellOriginX, 4.8) - + def test_09_11_plate_set_well_origin_x(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") @@ -395,37 +397,37 @@ def test_09_12_plate_get_well_origin_y(self): plate = o.plates.newPlate("Foo", "Bar") plate.node.set("WellOriginY", "5.8") self.assertEqual(plate.WellOriginY, 5.8) - + def test_09_13_plate_set_well_origin_y(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.WellOriginY = 3.5 self.assertEqual(plate.node.get("WellOriginY"), "3.5") - + def test_09_14_plate_get_rows(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.node.set("Rows", "8") self.assertEqual(plate.Rows, 8) - + def test_09_15_plate_set_rows(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.Rows = 16 self.assertEqual(plate.node.get("Rows"), "16") - + def test_09_16_plate_get_columns(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.node.set("Columns", "12") self.assertEqual(plate.Columns, 12) - + def test_09_15_plate_set_columns(self): o = O.OMEXML() plate = o.plates.newPlate("Foo", "Bar") plate.Columns = 24 self.assertEqual(plate.node.get("Columns"), "24") - + def test_10_01_wells_len(self): o = O.OMEXML(self.GROUPFILES_XML) self.assertEqual(len(o.plates[0].Well), 96) @@ -434,30 +436,30 @@ def test_10_02_wells_by_row_and_column(self): o = O.OMEXML(self.GROUPFILES_XML) w = o.plates[0].Well[1,3] self.assertEqual(w.ID, "Well:0:15") - + def test_10_03_wells_by_index(self): o = O.OMEXML(self.GROUPFILES_XML) w = o.plates[0].Well[2] self.assertEqual(w.ID, "Well:0:2") - + def test_10_04_wells_by_name(self): o = O.OMEXML(self.GROUPFILES_XML) w = o.plates[0].Well["C05"] self.assertEqual(w.Row, 2) self.assertEqual(w.Column, 4) - + def test_10_05_wells_by_id(self): o = O.OMEXML(self.GROUPFILES_XML) w = o.plates[0].Well["Well:0:3"] self.assertEqual(w.Row, 0) self.assertEqual(w.Column, 3) - + def test_10_06_wells_by_slice(self): o = O.OMEXML(self.GROUPFILES_XML) for i, w in enumerate(o.plates[0].Well[1::12]): self.assertEqual(w.Column, 1) self.assertEqual(w.Row, i) - + def test_10_07_iter_wells(self): o = O.OMEXML(self.GROUPFILES_XML) for i, name in enumerate(o.plates[0].Well): @@ -465,7 +467,7 @@ def test_10_07_iter_wells(self): column = i % 12 self.assertEqual(name, "ABCDEFGH"[row] + "%02d" % (column+1)) self.assertEqual(name, "H12") - + def test_10_08_new_well(self): o = O.OMEXML() plate = o.plates.newPlate("Foo","Bar") @@ -474,22 +476,22 @@ def test_10_08_new_well(self): self.assertEqual(w.node.get("Row"), "4") self.assertEqual(w.node.get("Column"), "5") self.assertEqual(w.node.get("ID"), "xyz") - + def test_11_01_get_Column(self): o = O.OMEXML(self.GROUPFILES_XML) self.assertEqual(o.plates[0].Well["B05"].Column, 4) - + def test_11_02_get_Row(self): o = O.OMEXML(self.GROUPFILES_XML) self.assertEqual(o.plates[0].Well["B05"].Row, 1) - + def test_11_03_get_external_description(self): o = O.OMEXML() plate = o.plates.newPlate("foo","bar") w = plate.Well.new(4,5, "xyz") w.node.set("ExternalDescription", "ijk") self.assertEqual(w.ExternalDescription, "ijk") - + def test_11_04_set_external_description(self): o = O.OMEXML() plate = o.plates.newPlate("foo","bar") @@ -503,33 +505,33 @@ def test_11_05_get_external_identifier(self): w = plate.Well.new(4,5, "xyz") w.node.set("ExternalIdentifier", "ijk") self.assertEqual(w.ExternalIdentifier, "ijk") - + def test_11_06_set_external_identifier(self): o = O.OMEXML() plate = o.plates.newPlate("foo","bar") w = plate.Well.new(4,5, "xyz") w.ExternalIdentifier = "LMO" self.assertEqual(w.node.get("ExternalIdentifier"), "LMO") - + def test_12_01_get_sample_len(self): o = O.OMEXML(self.GROUPFILES_XML) self.assertEqual(len(o.plates[0].Well[0].Sample), 6) - + def test_12_02_get_sample_item(self): o = O.OMEXML(self.GROUPFILES_XML) s = o.plates[0].Well[0].Sample[2] self.assertEqual(s.node.get("ID"), "WellSample:0:0:2") - + def test_12_03_get_sample_item_slice(self): o = O.OMEXML(self.GROUPFILES_XML) for i, s in enumerate(o.plates[0].Well[0].Sample[1::2]): self.assertEqual(s.node.get("ID"), "WellSample:0:0:%d" % (i * 2 + 1)) - + def test_12_04_iter_sample_item(self): o = O.OMEXML(self.GROUPFILES_XML) for i, s in enumerate(o.plates[0].Well[0].Sample): self.assertEqual(s.node.get("ID"), "WellSample:0:0:%d" % i) - + def test_12_05_new_sample_item(self): o = O.OMEXML() plate = o.plates.newPlate("foo","bar") @@ -542,37 +544,37 @@ def test_12_05_new_sample_item(self): self.assertEqual(sample_nodes[1].get("ID"), "ppp") self.assertEqual(sample_nodes[0].get("Index"), "0") self.assertEqual(sample_nodes[1].get("Index"), "1") - + def test_13_01_get_sample_id(self): o = O.OMEXML(self.GROUPFILES_XML) self.assertEqual(o.plates[0].Well['A02'].Sample[3].ID, "WellSample:0:1:3") - + def test_13_02_set_sample_id(self): o = O.OMEXML(self.GROUPFILES_XML) ws = o.plates[0].Well['A02'].Sample[3] ws.ID = "Foo" self.assertEqual(ws.node.get("ID"), "Foo") - + def test_13_03_get_position_x(self): o = O.OMEXML(self.GROUPFILES_XML) self.assertEqual(o.plates[0].Well['A01'].Sample[4].PositionX, 402.5) - + def test_13_04_set_position_x(self): o = O.OMEXML(self.GROUPFILES_XML) ws = o.plates[0].Well['A02'].Sample[3] ws.PositionX = 201.75 self.assertEqual(ws.node.get("PositionX"), "201.75") - + def test_13_05_get_position_y(self): o = O.OMEXML(self.GROUPFILES_XML) self.assertEqual(o.plates[0].Well['A01'].Sample[4].PositionY, 204.25) - + def test_13_06_set_position_y(self): o = O.OMEXML(self.GROUPFILES_XML) ws = o.plates[0].Well['A02'].Sample[3] ws.PositionY = 14.5 self.assertEqual(ws.node.get("PositionY"), "14.5") - + def test_13_07_get_timepoint(self): o = O.OMEXML(self.GROUPFILES_XML) self.assertEqual(o.plates[0].Well['A01'].Sample[1].Timepoint, '2011-12-27T08:24:29.960000') @@ -587,18 +589,18 @@ def test_13_08_set_timepoint(self): ws = o.plates[0].Well['A03'].Sample[4] ws.Timepoint = now_string self.assertEqual(ws.node.get("Timepoint"), now_string) - + def test_13_09_get_index(self): o = O.OMEXML(self.GROUPFILES_XML) ws = o.plates[0].Well['A02'].Sample[3] self.assertEqual(ws.Index, 9) - + def test_13_10_set_index(self): o = O.OMEXML(self.GROUPFILES_XML) ws = o.plates[0].Well['A02'].Sample[3] ws.Index = 301 self.assertEqual(ws.Index, 301) - + def test_13_11_get_image_ref(self): o = O.OMEXML(self.GROUPFILES_XML) ws = o.plates[0].Well['A02'].Sample[3] @@ -606,24 +608,24 @@ def test_13_11_get_image_ref(self): ref = ws.node.find(O.qn(o.get_ns("spw"), "ImageRef")) ws.node.remove(ref) self.assertTrue(ws.ImageRef is None) - + def test_13_12_set_image_ref(self): o = O.OMEXML(self.GROUPFILES_XML) ws = o.plates[0].Well['A02'].Sample[3] ws.ImageRef = "Foo" self.assertEqual(ws.node.find(O.qn(o.get_ns("spw"), "ImageRef")).get("ID"), "Foo") - + def test_14_01_get_plane_count(self): o = O.OMEXML(TIFF_XML) self.assertEqual(o.image(0).Pixels.plane_count, 1) - + def test_14_02_set_plane_count(self): o = O.OMEXML() pixels = o.image(0).Pixels self.assertTrue(isinstance(pixels, O.OMEXML.Pixels)) pixels.plane_count = 2 self.assertEqual(len(pixels.node.findall(O.qn(o.get_ns('ome'), "Plane"))), 2) - + def test_14_03_get_the_c(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels @@ -632,7 +634,7 @@ def test_14_03_get_the_c(self): self.assertTrue(isinstance(plane, O.OMEXML.Plane)) plane.node.set("TheC", "15") self.assertEqual(plane.TheC, 15) - + def test_14_04_get_the_z(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels @@ -641,7 +643,7 @@ def test_14_04_get_the_z(self): self.assertTrue(isinstance(plane, O.OMEXML.Plane)) plane.node.set("TheZ", "10") self.assertEqual(plane.TheZ, 10) - + def test_14_05_get_the_t(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels @@ -650,7 +652,7 @@ def test_14_05_get_the_t(self): self.assertTrue(isinstance(plane, O.OMEXML.Plane)) plane.node.set("TheT", "9") self.assertEqual(plane.TheT, 9) - + def test_14_06_set_the_c(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels @@ -658,7 +660,7 @@ def test_14_06_set_the_c(self): plane = pixels.Plane(0) plane.TheC = 5 self.assertEqual(int(plane.node.get("TheC")), 5) - + def test_14_07_set_the_z(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels @@ -666,7 +668,7 @@ def test_14_07_set_the_z(self): plane = pixels.Plane(0) plane.TheZ = 6 self.assertEqual(int(plane.node.get("TheZ")), 6) - + def test_14_08_set_the_t(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels @@ -674,42 +676,42 @@ def test_14_08_set_the_t(self): plane = pixels.Plane(0) plane.TheC = 7 self.assertEqual(int(plane.node.get("TheC")), 7) - + def test_14_09_get_delta_t(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels self.assertTrue(isinstance(pixels, O.OMEXML.Pixels)) plane = pixels.Plane(0) self.assertEqual(plane.DeltaT, 1.25) - + def test_14_10_get_exposure_time(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels self.assertTrue(isinstance(pixels, O.OMEXML.Pixels)) plane = pixels.Plane(0) self.assertEqual(plane.ExposureTime, 0.25) - + def test_14_11_get_position_x(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels self.assertTrue(isinstance(pixels, O.OMEXML.Pixels)) plane = pixels.Plane(0) self.assertEqual(plane.PositionX, 3.5) - + def test_14_12_get_position_y(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels self.assertTrue(isinstance(pixels, O.OMEXML.Pixels)) plane = pixels.Plane(0) self.assertEqual(plane.PositionY, 4.75) - + def test_14_13_get_position_z(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels self.assertTrue(isinstance(pixels, O.OMEXML.Pixels)) plane = pixels.Plane(0) self.assertEqual(plane.PositionZ, 2.25) - + def test_14_14_set_delta_t(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels @@ -717,7 +719,7 @@ def test_14_14_set_delta_t(self): plane = pixels.Plane(0) plane.DeltaT = 1.25 self.assertEqual(float(plane.node.get("DeltaT")), 1.25) - + def test_14_15_set_position_x(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels @@ -725,7 +727,7 @@ def test_14_15_set_position_x(self): plane = pixels.Plane(0) plane.PositionX = 5.5 self.assertEqual(float(plane.node.get("PositionX")), 5.5) - + def test_14_16_set_position_y(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels @@ -733,7 +735,7 @@ def test_14_16_set_position_y(self): plane = pixels.Plane(0) plane.PositionY = 6.5 self.assertEqual(float(plane.node.get("PositionY")), 6.5) - + def test_14_17_set_position_z(self): o = O.OMEXML(TIFF_XML) pixels = o.image(0).Pixels @@ -741,7 +743,7 @@ def test_14_17_set_position_z(self): plane = pixels.Plane(0) plane.PositionZ = 7.5 self.assertEqual(float(plane.node.get("PositionZ")), 7.5) - + TIFF_XML = """ >f, '__version__ = "%s"' % git_version + print('__version__ = "%s"' % git_version, file=f) return git_version or cached_version setup( name="python-bioformats", - version=get_version(), + version=get_version().decode("utf-8"), description="Read and write life sciences file formats", long_description='''Python-bioformats is a Python wrapper for Bio-Formats, a standalone Java library for reading and writing life sciences image file From eac252f52d86b1c4f085d60390b570ed3a1b7d34 Mon Sep 17 00:00:00 2001 From: Alistair Muldal Date: Tue, 29 Mar 2016 19:32:43 +0100 Subject: [PATCH 02/10] remove `import exceptions` --- bioformats/formatreader.py | 17 ++++++++--------- bioformats/tests/test_load_using_bioformats.py | 4 +--- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/bioformats/formatreader.py b/bioformats/formatreader.py index 37f2b11..eb73775 100644 --- a/bioformats/formatreader.py +++ b/bioformats/formatreader.py @@ -29,7 +29,6 @@ import logging logger = logging.getLogger(__name__) import errno -import exceptions import numpy as np import os import sys @@ -582,11 +581,11 @@ def __init__(self, path=None, url=None, perform_init=True): logger.warn(line) if jutil.is_instance_of( je, "java/io/FileNotFoundException"): - raise exceptions.IOError( - errno.ENOENT, + raise IOError( + errno.ENOENT, "The file, \"%s\", does not exist." % path, path) - e2 = exceptions.IOError( + e2 = IOError( errno.EINVAL, "Could not load the file as an image (see log for details)", path.encode('utf-8')) raise e2 else: @@ -614,8 +613,8 @@ def __init__(self, path=None, url=None, perform_init=True): filename = os.path.split(path)[1] if not os.path.isfile(self.path): - raise exceptions.IOError( - errno.ENOENT, + raise IOError( + errno.ENOENT, "The file, \"%s\", does not exist." % path, path) @@ -716,11 +715,11 @@ def init_reader(self): "()Ljava/lang/Throwable;") if jutil.is_instance_of( je, "java/io/FileNotFoundException"): - raise exceptions.IOError( - errno.ENOENT, + raise IOError( + errno.ENOENT, "The file, \"%s\", does not exist." % path, path) - e2 = exceptions.IOError( + e2 = IOError( errno.EINVAL, "Could not load the file as an image (see log for details)", self.path.encode('utf-8')) raise e2 diff --git a/bioformats/tests/test_load_using_bioformats.py b/bioformats/tests/test_load_using_bioformats.py index 208a467..551388e 100644 --- a/bioformats/tests/test_load_using_bioformats.py +++ b/bioformats/tests/test_load_using_bioformats.py @@ -7,7 +7,6 @@ from __future__ import absolute_import, print_function, unicode_literals -import exceptions import os import unittest @@ -37,8 +36,7 @@ def test_load_using_bioformats(self): def test_file_not_found(self): # Regression test of issue #6 path = os.path.join(os.path.dirname(__file__), 'Channel5-01-A-01.tif') - self.assertRaises(exceptions.IOError, - lambda :load_image(path)) + self.assertRaises(IOError, lambda :load_image(path)) class TestLoadUsingBioformatsURL(unittest.TestCase): def setUp(self): From 8f974cb11735b306cafa6d09a3dfe03346f32848 Mon Sep 17 00:00:00 2001 From: Alistair Muldal Date: Tue, 29 Mar 2016 19:33:05 +0100 Subject: [PATCH 03/10] fix urllib imports --- bioformats/formatreader.py | 19 +++++++++++++------ .../tests/test_load_using_bioformats.py | 11 ++++++++--- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/bioformats/formatreader.py b/bioformats/formatreader.py index eb73775..80f5157 100644 --- a/bioformats/formatreader.py +++ b/bioformats/formatreader.py @@ -32,8 +32,15 @@ import numpy as np import os import sys -import urllib -import urllib2 + +if sys.version_info.major == 3: + from urllib.request import urlopen, urlparse, url2pathname + from urllib.parse import unquote +else: + from urllib import url2pathname + from urllib2 import urlopen, urlparse, unquote + urlparse = urlparse.urlparse + import shutil import tempfile import traceback @@ -546,7 +553,7 @@ def __init__(self, path=None, url=None, perform_init=True): self.url = url self.using_temp_file = False if url is not None and url.lower().startswith(file_scheme): - utf8_url = urllib.url2pathname(url[len(file_scheme):]) + utf8_url = url2pathname(url[len(file_scheme):]) if isinstance(utf8_url, str): path = str(utf8_url, 'utf-8') else: @@ -593,7 +600,7 @@ def __init__(self, path=None, url=None, perform_init=True): # Other URLS, copy them to a tempfile location # ext = url[url.rfind("."):] - src = urllib2.urlopen(url) + src = urlopen(url) dest_fd, self.path = tempfile.mkstemp(suffix=ext) try: dest = os.fdopen(dest_fd, 'wb') @@ -605,8 +612,8 @@ def __init__(self, path=None, url=None, perform_init=True): self.using_temp_file = True src.close() dest.close() - urlpath = urllib2.urlparse.urlparse(url)[2] - filename = urllib2.unquote(urlpath.split("/")[-1]) + urlpath = urlparse(url)[2] + filename = unquote(urlpath.split("/")[-1]) else: if sys.platform.startswith("win"): self.path = self.path.replace("/", os.path.sep) diff --git a/bioformats/tests/test_load_using_bioformats.py b/bioformats/tests/test_load_using_bioformats.py index 551388e..ff6090b 100644 --- a/bioformats/tests/test_load_using_bioformats.py +++ b/bioformats/tests/test_load_using_bioformats.py @@ -16,7 +16,12 @@ import bioformats.formatreader as formatreader import bioformats.metadatatools as metadatatools from bioformats import load_image, load_image_url -import urllib + +import sys +if sys.version_info.major == 3: + from urllib.request import pathname2url +else: + from urllib import pathname2url class TestLoadUsingBioformats(unittest.TestCase): @@ -48,7 +53,7 @@ def tearDown(self): def test_01_01_open_file(self): path = os.path.join(os.path.dirname(__file__), 'Channel1-01-A-01.tif') - url = "file:" + urllib.pathname2url(path).encode("utf-8") + url = "file:" + pathname2url(path).encode("utf-8") image, scale = load_image_url( url, rescale=False, wants_max_intensity=True) self.assertEqual(image.shape[0], 640) @@ -66,7 +71,7 @@ def test_01_03_unicode_url(self): # raise an exception when converting URL to string # path = os.path.join(os.path.dirname(__file__), 'Channel1-01-A-01.tif') - url = "file:" + urllib.pathname2url(path).encode("utf-8") + url = "file:" + pathname2url(path).encode("utf-8") image, scale = load_image_url( url, rescale=False, wants_max_intensity=True) self.assertEqual(image.shape[0], 640) From d50ad1f6b0949c02e883d84262efd530547b4671 Mon Sep 17 00:00:00 2001 From: Alistair Muldal Date: Tue, 29 Mar 2016 19:33:29 +0100 Subject: [PATCH 04/10] fix StringIO import --- bioformats/omexml.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/bioformats/omexml.py b/bioformats/omexml.py index 43506e8..32a11d9 100644 --- a/bioformats/omexml.py +++ b/bioformats/omexml.py @@ -13,7 +13,13 @@ import xml.etree.ElementTree from xml.etree import cElementTree as ElementTree -from cStringIO import StringIO + +import sys +if sys.version_info.major == 3: + from io import StringIO +else: + from cStringIO import StringIO + import datetime import logging from functools import reduce From 5202367394c1795ca3f2e2c53a7bb9cdfbe7cb10 Mon Sep 17 00:00:00 2001 From: Alistair Muldal Date: Tue, 29 Mar 2016 19:50:39 +0100 Subject: [PATCH 05/10] fix encoding= argument for ElementTree.write --- bioformats/omexml.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bioformats/omexml.py b/bioformats/omexml.py index 32a11d9..2e58c68 100644 --- a/bioformats/omexml.py +++ b/bioformats/omexml.py @@ -17,8 +17,10 @@ import sys if sys.version_info.major == 3: from io import StringIO + uenc = 'unicode' else: from cStringIO import StringIO + uenc = 'utf-8' import datetime import logging @@ -333,11 +335,11 @@ def __str__(self): ElementTree.register_namespace("om", NS_ORIGINAL_METADATA) result = StringIO() ElementTree.ElementTree(self.root_node).write(result, - encoding = "utf-8", - method = "xml") + encoding=uenc, + method="xml") return result.getvalue() - def to_xml(self, indent="\t", newline="\n", encoding = "utf-8"): + def to_xml(self, indent="\t", newline="\n", encoding=uenc): return str(self) def get_ns(self, key): From 99614aea838696aaafc6918ca4063cfbaaf349cd Mon Sep 17 00:00:00 2001 From: Alistair Muldal Date: Tue, 29 Mar 2016 20:50:19 +0100 Subject: [PATCH 06/10] don't force encoding of urls to be utf-8 (we will fix this in formatreader instead) --- bioformats/tests/test_load_using_bioformats.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bioformats/tests/test_load_using_bioformats.py b/bioformats/tests/test_load_using_bioformats.py index ff6090b..5cc9b0c 100644 --- a/bioformats/tests/test_load_using_bioformats.py +++ b/bioformats/tests/test_load_using_bioformats.py @@ -53,7 +53,7 @@ def tearDown(self): def test_01_01_open_file(self): path = os.path.join(os.path.dirname(__file__), 'Channel1-01-A-01.tif') - url = "file:" + pathname2url(path).encode("utf-8") + url = "file:" + pathname2url(path) image, scale = load_image_url( url, rescale=False, wants_max_intensity=True) self.assertEqual(image.shape[0], 640) @@ -71,7 +71,7 @@ def test_01_03_unicode_url(self): # raise an exception when converting URL to string # path = os.path.join(os.path.dirname(__file__), 'Channel1-01-A-01.tif') - url = "file:" + pathname2url(path).encode("utf-8") + url = "file:" + pathname2url(path) image, scale = load_image_url( url, rescale=False, wants_max_intensity=True) self.assertEqual(image.shape[0], 640) From d879023a561b322e5782d4c43d2bda362f70d328 Mon Sep 17 00:00:00 2001 From: Alistair Muldal Date: Wed, 30 Mar 2016 11:45:52 +0100 Subject: [PATCH 07/10] fix URL string handling --- bioformats/formatreader.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bioformats/formatreader.py b/bioformats/formatreader.py index 80f5157..49885b9 100644 --- a/bioformats/formatreader.py +++ b/bioformats/formatreader.py @@ -550,14 +550,14 @@ class ImageReader(object): def __init__(self, path=None, url=None, perform_init=True): self.stream = None file_scheme = "file:" - self.url = url self.using_temp_file = False - if url is not None and url.lower().startswith(file_scheme): - utf8_url = url2pathname(url[len(file_scheme):]) - if isinstance(utf8_url, str): - path = str(utf8_url, 'utf-8') - else: - path = utf8_url + + if url is not None: + url = str(url) + if url.lower().startswith(file_scheme): + url = url2pathname(url[len(file_scheme):]) + path = url + self.path = path if path is None: if url.lower().startswith("omero:"): From 03eab800eefd45e8af420629ce4ec579d6ce36e9 Mon Sep 17 00:00:00 2001 From: Alistair Muldal Date: Wed, 30 Mar 2016 12:09:12 +0100 Subject: [PATCH 08/10] add __contains__ method to StructuredAnnotations and OriginalMetadata classes (fixes errors in test_omexml) --- bioformats/omexml.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bioformats/omexml.py b/bioformats/omexml.py index 2e58c68..b500b59 100644 --- a/bioformats/omexml.py +++ b/bioformats/omexml.py @@ -743,6 +743,9 @@ def __getitem__(self, key): return child raise IndexError('ID "%s" not found' % key) + def __contains__(self, key): + return self.has_key(key) + def keys(self): return filter(lambda x: x is not None, [child.get("ID") for child in self.node]) @@ -871,6 +874,9 @@ def __getitem__(self, key): def __setitem__(self, key, value): self.sa.add_original_metadata(key, value) + def __contains__(self, key): + return self.has_key(key) + def __iter__(self): for annotation_id, (key, value) in self.sa.iter_original_metadata(): yield key From 226ed20e172a7e057649649d083bd3b15536b798 Mon Sep 17 00:00:00 2001 From: Alistair Muldal Date: Wed, 30 Mar 2016 12:43:18 +0100 Subject: [PATCH 09/10] remove unicode_literals from setup.py (unnecessary and causes installation problems in Python2) --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6613978..a21ce17 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, print_function, unicode_literals +from __future__ import absolute_import, print_function import os.path import re From 9e19c32a1aa1a90d9acad951297c31a4badeeab3 Mon Sep 17 00:00:00 2001 From: Alistair Muldal Date: Wed, 30 Mar 2016 13:35:18 +0100 Subject: [PATCH 10/10] Travis build for Python 3.5 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 311ecb9..ea14cb2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: java env: - PYTHON_VERSION="2.7" + - PYTHON_VERSION="3.5" before_install: # Get the tag if it wasn't provided. Travis doesn't provide this if it isn't a tagged build. - if [ -z $TRAVIS_TAG ]; then TRAVIS_TAG=`git tag --contains` ; fi