| """ |
| Copyright © 2025 Howard Hughes Medical Institute, Authored by Carsen Stringer , Michael Rariden and Marius Pachitariu. |
| """ |
| import os |
| import numpy as np |
| import cv2 |
| import tifffile |
| import logging |
| from tqdm import tqdm |
| import re |
|
|
| try: |
| import nd2 |
| ND2 = True |
| except: |
| ND2 = False |
|
|
| try: |
| import nrrd |
| NRRD = True |
| except: |
| NRRD = False |
|
|
|
|
| io_logger = logging.getLogger(__name__) |
|
|
| def load_dax(filename): |
| |
| |
|
|
| inf_filename = os.path.splitext(filename)[0] + ".inf" |
| if not os.path.exists(inf_filename): |
| io_logger.critical( |
| f"ERROR: no inf file found for dax file {filename}, cannot load dax without it" |
| ) |
| return None |
|
|
| |
| image_height, image_width = None, None |
| |
| size_re = re.compile(r"frame dimensions = ([\d]+) x ([\d]+)") |
| length_re = re.compile(r"number of frames = ([\d]+)") |
| endian_re = re.compile(r" (big|little) endian") |
|
|
| with open(inf_filename, "r") as inf_file: |
| lines = inf_file.read().split("\n") |
| for line in lines: |
| m = size_re.match(line) |
| if m: |
| image_height = int(m.group(2)) |
| image_width = int(m.group(1)) |
| m = length_re.match(line) |
| if m: |
| number_frames = int(m.group(1)) |
| m = endian_re.search(line) |
| if m: |
| if m.group(1) == "big": |
| bigendian = 1 |
| else: |
| bigendian = 0 |
| |
| if not image_height: |
| io_logger.warning("could not determine dax image size, assuming 256x256") |
| image_height = 256 |
| image_width = 256 |
|
|
| |
| img = np.memmap(filename, dtype="uint16", |
| shape=(number_frames, image_height, image_width)) |
| if bigendian: |
| img = img.byteswap() |
| img = np.array(img) |
|
|
| return img |
|
|
|
|
| def imread(filename): |
| """ |
| Read in an image file with tif or image file type supported by cv2. |
| |
| Args: |
| filename (str): The path to the image file. |
| |
| Returns: |
| numpy.ndarray: The image data as a NumPy array. |
| |
| Raises: |
| None |
| |
| Raises an error if the image file format is not supported. |
| |
| Examples: |
| >>> img = imread("image.tif") |
| """ |
| |
| ext = os.path.splitext(filename)[-1].lower() |
| if ext == ".tif" or ext == ".tiff" or ext == ".flex": |
| with tifffile.TiffFile(filename) as tif: |
| ltif = len(tif.pages) |
| try: |
| full_shape = tif.shaped_metadata[0]["shape"] |
| except: |
| try: |
| page = tif.series[0][0] |
| full_shape = tif.series[0].shape |
| except: |
| ltif = 0 |
| if ltif < 10: |
| img = tif.asarray() |
| else: |
| page = tif.series[0][0] |
| shape, dtype = page.shape, page.dtype |
| ltif = int(np.prod(full_shape) / np.prod(shape)) |
| io_logger.info(f"reading tiff with {ltif} planes") |
| img = np.zeros((ltif, *shape), dtype=dtype) |
| for i, page in enumerate(tqdm(tif.series[0])): |
| img[i] = page.asarray() |
| img = img.reshape(full_shape) |
| return img |
| elif ext == ".dax": |
| img = load_dax(filename) |
| return img |
| elif ext == ".nd2": |
| if not ND2: |
| io_logger.critical("ERROR: need to 'pip install nd2' to load in .nd2 file") |
| return None |
| elif ext == ".nrrd": |
| if not NRRD: |
| io_logger.critical( |
| "ERROR: need to 'pip install pynrrd' to load in .nrrd file") |
| return None |
| else: |
| img, metadata = nrrd.read(filename) |
| if img.ndim == 3: |
| img = img.transpose(2, 0, 1) |
| return img |
| elif ext != ".npy": |
| try: |
| img = cv2.imread(filename, -1) |
| if img.ndim > 2: |
| img = img[..., [2, 1, 0]] |
| return img |
| except Exception as e: |
| io_logger.critical("ERROR: could not read file, %s" % e) |
| return None |
| else: |
| try: |
| dat = np.load(filename, allow_pickle=True).item() |
| masks = dat["masks"] |
| return masks |
| except Exception as e: |
| io_logger.critical("ERROR: could not read masks from file, %s" % e) |
| return None |
|
|
|
|
| def imsave(filename, arr): |
| """ |
| Saves an image array to a file. |
| |
| Args: |
| filename (str): The name of the file to save the image to. |
| arr (numpy.ndarray): The image array to be saved. |
| |
| Returns: |
| None |
| """ |
| ext = os.path.splitext(filename)[-1].lower() |
| if ext == ".tif" or ext == ".tiff": |
| tifffile.imwrite(filename, data=arr, compression="zlib") |
| else: |
| if len(arr.shape) > 2: |
| arr = cv2.cvtColor(arr, cv2.COLOR_BGR2RGB) |
| cv2.imwrite(filename, arr) |
|
|
|
|