def tf_get_largest_series(image_filepath): """ Determine largest series for .scn files by examining metadata For other multi-series files, find the one with the most pixels Parameters ---------- image_filepath: str path to the image file Returns ------- largest_series:int index of the largest series in the image data """ fp_ext = Path(image_filepath).suffix.lower() tf_im = TiffFile(image_filepath) if fp_ext == ".scn": scn_meta = xml2dict(tf_im.scn_metadata) image_meta = scn_meta.get("scn").get("collection").get("image") largest_series = np.argmax([ im.get("scanSettings").get("objectiveSettings").get("objective") for im in image_meta ]) else: largest_series = np.argmax([ np.prod(np.asarray(series.shape), dtype=np.int64) for series in tf_im.series ]) return largest_series
def convert_nd2_to_ome_tiff(path, outpath): """ Convert an nd2 file to an .ome.tif by saving each tile under a separate series. Uses the BigTIFF format to write the new .ome.tiff file. """ path_to_nd2 = str(path) omexml = get_editable_omexml(path_to_nd2) limit = omexml.image_count xml_dict = tifffile.xml2dict(omexml.to_xml()) with ND2Reader(path_to_nd2) as images: print(images.sizes) images.iter_axes = 'v' images.bundle_axes = "zcyx" with tifffile.TiffWriter(outpath, bigtiff=True) as tif: for series, tile in enumerate(images): # TODO: seems like, for some weird reason, the tiles are rotated incorrectly? Why? # Maybe it has to do with the order of the bundle axes rotated_tile = np.rot90(tile, k=1, axes=(2, 3)) series_metadata = xml_dict["OME"]["Image"][series] tif.save(rotated_tile.astype(np.uint16), contiguous=False, metadata=series_metadata)
def ome_tifffile_to_arraylike(image_filepath): ome_metadata = xml2dict(TiffFile(image_filepath).ome_metadata) im_dims, im_dtype = get_tifffile_info(image_filepath) largest_series_idx = tf_get_largest_series(image_filepath) series_metadata = ome_metadata.get("OME").get("Image") if isinstance(series_metadata, list): series_metadata = series_metadata[largest_series_idx] if isinstance(series_metadata.get("Pixels").get("Channel"), list): samples_per_pixel = (series_metadata.get("Pixels").get("Channel") [0].get("SamplesPerPixel")) else: samples_per_pixel = (series_metadata.get("Pixels").get("Channel").get( "SamplesPerPixel")) is_rgb = guess_rgb(im_dims) image = zarr.open( imread(image_filepath, aszarr=True, series=largest_series_idx)) if isinstance(image, zarr.Group): image = image[0] image = da.from_zarr(image) if samples_per_pixel: if is_rgb is False and samples_per_pixel >= 3: image = image.transpose(1, 2, 0) return image, image_filepath
def test_ome_save(tmp_path, bundle_test_dir, ome_xml, z_size): data = np.zeros((z_size, 20, 20, 2), dtype=np.uint8) image = Image( data, image_spacing=(27 * 10 ** -6, 6 * 10 ** -6, 6 * 10 ** -6), axes_order="ZYXC", channel_names=["a", "b"], shift=(10, 9, 8), name="Test", ) ImageWriter.save(image, tmp_path / "test.tif") with tifffile.TiffFile(tmp_path / "test.tif") as tiff: assert tiff.is_ome assert isinstance(tiff.ome_metadata, str) meta_data = tifffile.xml2dict(tiff.ome_metadata)["OME"]["Image"] assert "PhysicalSizeX" in meta_data["Pixels"] assert meta_data["Pixels"]["PhysicalSizeX"] == 6 assert "PhysicalSizeXUnit" in meta_data["Pixels"] assert meta_data["Pixels"]["PhysicalSizeXUnit"] == "µm" assert len(meta_data["Pixels"]["Channel"]) == 2 assert meta_data["Pixels"]["Channel"][0]["Name"] == "a" assert meta_data["Pixels"]["Channel"][1]["Name"] == "b" assert meta_data["Name"] == "Test" xml_file = etree.fromstring(tiff.ome_metadata.encode("utf8")) # nosec ome_xml.assert_(xml_file) read_image = TiffImageReader.read_image(tmp_path / "test.tif") assert np.allclose(read_image.spacing, image.spacing) assert np.allclose(read_image.shift, image.shift) assert read_image.channel_names == ["a", "b"] assert read_image.name == "Test"
def test_xml2dict(): sample_text = """ <level1> <level2>3.5322</level2> </level1> """ data = tifffile.xml2dict(sample_text) assert math.isclose(data["level1"]["level2"], 3.5322)
def metadata(self, raw=False): """Read metadata from file and return as dict (default) or XML.""" if self.metadata_size <= 0: return u'' if raw else None fh = self._fh with fh.lock: fh.seek(self.data_offset - self.metadata_size) metadata = fh.read(self.metadata_size) if raw: return unicode(metadata, 'utf-8') try: return xml2dict(metadata)['METADATA'] except Exception: return unicode(metadata, 'utf-8')
def parse_dispim_meta(impath): # parse TiffFile.ome_metadata to extract diSPIM info with tf.TiffFile(impath) as t: meta = t.ome_metadata # tifffile version > 2019.2.22 if isinstance(meta, str): meta = tf.xml2dict(meta)["OME"] im0 = meta["Image"][0] if isinstance(meta["Image"], list) else meta["Image"] out = {"channels": [], "nS": len(meta["Image"])} for x in "XYZCT": out["n" + x] = im0["Pixels"]["Size" + x] for x in "XYZ": out["d" + x] = im0["Pixels"]["PhysicalSize" + x] for chan in im0["Pixels"]["Channel"]: out["channels"].append(chan["Name"]) out["dzRatio"] = out["dZ"] / out["dX"] return out
def __init__( self, image_fp, image_res, mask=None, pre_reg_transforms=None, preprocessing=None, channel_names=None, channel_colors=None, ): self.image_filepath = image_fp self.image_res = image_res self.image = None self.tf = TiffFile(self.image_filepath) self.reader = "tifffile" self.ome_metadata = xml2dict(self.tf.ome_metadata) ( self.im_dims, self.im_dtype, ) = self._get_image_info() self.im_dims = tuple(self.im_dims) # self.n_ch = self.im_dims[2] if self.is_rgb else self.im_dims[0] self.mask = self.read_mask(mask) if preprocessing is None: self.preprocessing = std_prepro() else: self.preprocessing = std_prepro() self.preprocessing.update(preprocessing) self.pre_reg_transforms = pre_reg_transforms self.channel_names = channel_names self.channel_colors = channel_colors self.original_size_transform = None
def slice_ome_tiff(input_filepath, output_filepath, start, end, use_bigtiff=False): """ Build a new .ome.tiff with only the series that fall in the range start:end included (+ metadata). """ # TODO: Add an IndexError or whatever later input_ome_tiff = tifffile.TiffFile(input_filepath) xml = input_ome_tiff.ome_metadata xml_dict = tifffile.xml2dict(xml) print(input_filepath) with tifffile.TiffWriter(output_filepath, bigtiff=use_bigtiff) as tif: for index in range(start, end): print(index) tile = input_ome_tiff.series[index].asarray() tile_metadata = xml_dict["OME"]["Image"][index] tif.save(tile.astype(np.uint16), contiguous=False, metadata=tile_metadata)
def data(self, raw=True): """Read metadata from file and return as XML (default) or dict.""" self._fh.seek(self.xml_offset) xml = self._fh.read(self.xml_size) xml = xml.replace(b'\r\n', b'\n').replace(b'\r', b'\n') # ??? return unicode(xml, 'utf-8') if raw else xml2dict(xml)
def read_xml(fh, filesize, raw=True): """Read XML from file and return as unicode string (default) or dict.""" xml = stripnull(fh.read(filesize)) return unicode(xml, 'utf-8') if raw else xml2dict(xml)
def find_ome_magnification(ome_xml): metadata = tifffile.xml2dict(ome_xml)