def testXMLParsing(): samples = [{ 'xml': """<?xml version='1.0' encoding='utf-8'?> <OME xmlns="http://www.openmicroscopy.org/Schemas/OME/2016-06" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" UUID="urn:uuid:1ae9b229-162c-4431-8be0-1833b52302e5" xsi:schemaLocation="http://www.openmicroscopy.org/Schemas/OME/2016-06 http://www.openmicroscopy.org/Schemas/OME/2016-06/ome.xsd"><Image ID="Image:0"><Pixels BigEndian="false" DimensionOrder="XYZCT" ID="Pixels:0" PhysicalSizeX="0.32499998807907104" PhysicalSizeXUnit="µm" PhysicalSizeY="0.32499998807907104" PhysicalSizeYUnit="µm" SizeC="3" SizeT="1" SizeX="57346" SizeY="54325" SizeZ="1" Type="uint8"><Channel ID="Channel:0:0" Name="Red" SamplesPerPixel="1"><LightPath /></Channel><Channel ID="Channel:0:1" Name="Green" SamplesPerPixel="1"><LightPath /></Channel><Channel ID="Channel:0:2" Name="Blue" SamplesPerPixel="1"><LightPath /></Channel><TiffData IFD="0" PlaneCount="3" /><Plane TheC="0" TheT="0" TheZ="0" /><Plane TheC="1" TheT="0" TheZ="0" /><Plane TheC="2" TheT="0" TheZ="0" /></Pixels></Image></OME>""", # noqa 'checks': { 'frames': 3, 'IndexRange': { 'IndexC': 3 }, 'IndexStride': { 'IndexC': 1 }, 'channelmap': { 'Blue': 2, 'Green': 1, 'Red': 0 }, 'channels': ['Red', 'Green', 'Blue'], } }] # Create a source so we can use internal functions for testing imagePath = datastore.fetch('sample.ome.tif') source = large_image_source_ometiff.open(imagePath) for sample in samples: xml = ElementTree.fromstring(sample['xml']) info = etreeToDict(xml) assert etreeToDict(dictToEtree(info)) == info source._omeinfo = info['OME'] source._parseOMEInfo() metadata = source.getMetadata() for key, value in sample['checks'].items(): if key in {'frames'}: assert len(metadata[key]) == value else: assert metadata[key] == value
def parse_image_description(self, meta=None): # noqa self._pixelInfo = {} self._embeddedImages = {} if not meta: return if not isinstance(meta, six.string_types): meta = meta.decode('utf8', 'ignore') try: xml = ElementTree.fromstring(meta) except Exception: if 'AppMag = ' in meta: try: self._pixelInfo = { 'magnification': float( meta.split('AppMag = ')[1].split('|')[0].strip()) } except Exception: pass return try: image = xml.find(".//DataObject[@ObjectType='DPScannedImage']") columns = int( image.find(".//*[@Name='PIM_DP_IMAGE_COLUMNS']").text) rows = int(image.find(".//*[@Name='PIM_DP_IMAGE_ROWS']").text) spacing = [ float(val.strip('"')) for val in image.find( ".//*[@Name='DICOM_PIXEL_SPACING']").text.split() ] self._pixelInfo = { 'width': columns, 'height': rows, 'mm_x': spacing[0], 'mm_y': spacing[1] } except Exception: pass # Extract macro and label images for image in xml.findall(".//*[@ObjectType='DPScannedImage']"): try: typestr = image.find(".//*[@Name='PIM_DP_IMAGE_TYPE']").text datastr = image.find(".//*[@Name='PIM_DP_IMAGE_DATA']").text except Exception: continue if not typestr or not datastr: continue typemap = { 'LABELIMAGE': 'label', 'MACROIMAGE': 'macro', 'WSI': 'thumbnail', } self._embeddedImages[typemap.get(typestr, typestr.lower())] = datastr try: self._description_record = etreeToDict(xml) except Exception: pass return True
def _parseMetadataXml(self, meta): if not isinstance(meta, six.string_types): meta = meta.decode('utf8', 'ignore') try: xml = ElementTree.fromstring(meta) except Exception: return self._description_record = etreeToDict(xml) xml = self._description_record try: # Optrascan metadata scanDetails = xml.get('ScanInfo', xml.get('EncodeInfo'))['ScanDetails'] mag = float(scanDetails['Magnification']) # In microns; convert to mm scale = float(scanDetails['PixelResolution']) * 1e-3 self._pixelInfo = { 'magnification': mag, 'mm_x': scale, 'mm_y': scale, } except Exception: pass
def __init__(self, path, **kwargs): """ Initialize the tile class. See the base class for other available parameters. :param path: a filesystem path for the tile source. """ super().__init__(path, **kwargs) self._largeImagePath = self._getLargeImagePath() # Read the root dzi file and check that the expected image files exist try: with builtins.open(self._largeImagePath) as fptr: if fptr.read(1024).strip()[:5] != '<?xml': raise TileSourceError( 'File cannot be opened via deepzoom reader.') fptr.seek(0) xml = ElementTree.parse(self._largeImagePath).getroot() self._info = etreeToDict(xml)['Image'] except (ElementTree.ParseError, KeyError, UnicodeDecodeError): raise TileSourceError('File cannot be opened via Deepzoom reader.') except FileNotFoundError: if not os.path.isfile(self._largeImagePath): raise TileSourceFileNotFoundError( self._largeImagePath) from None raise # We should now have a dictionary like # {'Format': 'png', # or 'jpeg' # 'Overlap': '1', # 'Size': {'Height': '41784', 'Width': '44998'}, # 'TileSize': '254'} # and a file structure like # <rootname>_files/<level>/<x>_<y>.<format> # images will be TileSize+Overlap square; final images will be # truncated. Base level is either 0 or probably 8 (level 0 is a 1x1 # pixel tile) self.sizeX = int(self._info['Size']['Width']) self.sizeY = int(self._info['Size']['Height']) self.tileWidth = self.tileHeight = int(self._info['TileSize']) maxXY = max(self.sizeX, self.sizeY) self.levels = int( math.ceil(math.log(maxXY / self.tileWidth) / math.log(2))) + 1 tiledirName = os.path.splitext(os.path.basename( self._largeImagePath))[0] + '_files' rootdir = os.path.dirname(self._largeImagePath) self._tiledir = os.path.join(rootdir, tiledirName) if not os.path.isdir(self._tiledir): rootdir = os.path.dirname(rootdir) self._tiledir = os.path.join(rootdir, tiledirName) zeroname = '0_0.%s' % self._info['Format'] self._nested = os.path.isdir(os.path.join(self._tiledir, '0', zeroname)) zeroimg = PIL.Image.open( os.path.join(self._tiledir, '0', zeroname) if not self._nested else os.path.join(self._tiledir, '0', zeroname, zeroname)) if zeroimg.size == (1, 1): self._baselevel = int( math.ceil(math.log(maxXY) / math.log(2)) - math.ceil(math.log(maxXY / self.tileWidth) / math.log(2))) else: self._baselevel = 0