Source code for impy.utils.io

from __future__ import annotations
from tifffile import TiffFile, imwrite, memmap
import json
import re
import os
import numpy as np
from dask import array as da
from .._cupy import xp
from ..utils.axesop import switch_slice

__all__ = ["imwrite", 
           "memmap",
           "open_tif", 
           "open_mrc",
           "open_img",
           "open_as_dask",
           "get_scale_from_meta", 
           "get_imsave_meta_from_img"]

def load_json(s:str):
    return json.loads(re.sub("'", '"', s))

[docs]def open_tif(path:str, return_img:bool=False, memmap:bool=False): with TiffFile(path) as tif: ijmeta = tif.imagej_metadata series0 = tif.series[0] pagetag = series0.pages[0].tags hist = [] if ijmeta is None: ijmeta = {} ijmeta.pop("ROI", None) if "Info" in ijmeta.keys(): try: infodict = load_json(ijmeta["Info"]) except: infodict = {} if "impyhist" in infodict.keys(): hist = infodict["impyhist"].split("->") try: axes = series0.axes.lower() except: axes = None tags = {v.name: v.value for v in pagetag.values()} out = {"axes": axes, "ijmeta": ijmeta, "history": hist, "tags": tags} if return_img: if memmap: out["image"] = tif.asarray(out="memmap") else: out["image"] = tif.asarray() return out
[docs]def open_mrc(path:str, return_img:bool=False, memmap:bool=False): import mrcfile if memmap: open_func = mrcfile.mmap else: open_func = mrcfile.open # By default mrcfile functions returns non-writeable array, which is incompatible # with some functions in ImgArray. We need to specify mode="r+". with open_func(path, mode="r+") as mrc: ijmeta = {"unit": "nm"} ndim = len(mrc.voxel_size.item()) if ndim == 3: axes = "zyx" ijmeta["spacing"] = mrc.voxel_size.z/10 elif ndim == 2: axes = "yx" else: raise RuntimeError(f"ndim = {ndim} not supported") tags = {} tags["XResolution"] = [1, mrc.voxel_size.x/10] tags["YResolution"] = [1, mrc.voxel_size.y/10] out = {"axes": axes, "ijmeta": ijmeta, "history": [], "tags": tags} if return_img: out["image"] = mrc.data return out
[docs]def open_as_dask(path: str, chunks): meta, img = open_img(path, memmap=True) axes = meta["axes"] if chunks == "default": chunks = switch_slice("yx", axes, ifin=img.shape, ifnot=("auto",)*img.ndim) if img.dtype == ">u2": img = img.astype(np.uint16) img = da.from_array(img, chunks=chunks).map_blocks( np.array, meta=np.array([], dtype=img.dtype) ) return meta, img
[docs]def open_img(path, memmap: bool = False): _, fext = os.path.splitext(os.path.basename(path)) if fext in (".tif", ".tiff"): meta = open_tif(path, True, memmap=memmap) img = meta.pop("image") elif fext in (".mrc", ".rec"): meta = open_mrc(path, True, memmap=memmap) img = meta.pop("image") else: from skimage import io img = io.imread(path) if fext in (".png", ".jpg") and img.ndim == 3 and img.shape[-1] <= 4: meta = {"axes":"yxc", "ijmeta":{}, "history":[]} else: meta = {"axes":None, "ijmeta":{}, "history":[]} return meta, img
[docs]def get_scale_from_meta(meta:dict): scale = dict() dz = meta["ijmeta"].get("spacing", 1.0) try: # For MicroManager info = load_json(meta["ijmeta"]["Info"]) dx = dy = info["PixelSize_um"] except Exception: try: tags = meta["tags"] xres = tags["XResolution"] yres = tags["YResolution"] dx = xres[1]/xres[0] dy = yres[1]/yres[0] except KeyError: dx = dy = dz scale["x"] = dx scale["y"] = dy # read z scale if needed if "z" in meta["axes"]: scale["z"] = dz return scale
[docs]def get_imsave_meta_from_img(img, update_lut=True): metadata = img.metadata.copy() if update_lut: lut_min, lut_max = np.percentile(img, [1, 99]) metadata.update({"min": lut_min, "max": lut_max}) # set lateral scale try: res = (1/img.scale["x"], 1/img.scale["y"]) except Exception: res = None # set z-scale if "z" in img.axes: metadata["spacing"] = img.scale["z"] else: metadata["spacing"] = img.scale["x"] # add history to Info try: info = load_json(metadata["Info"]) except: info = {} info["impyhist"] = "->".join([img.name] + img.history) metadata["Info"] = str(info) # set axes in tiff metadata metadata["axes"] = str(img.axes).upper() if img.ndim > 3: metadata["hyperstack"] = True return dict(imagej=True, resolution=res, metadata=metadata)