from pims import FramesSequenceND, Frame import numpy as np from nd2reader.exc import NoImageError from nd2reader.parser import get_parser import six class ND2Reader(FramesSequenceND): """ PIMS wrapper for the ND2 reader """ def __init__(self, filename): self.filename = filename # first use the parser to parse the file self._fh = open(filename, "rb") self._parser = get_parser(self._fh) self._metadata = self._parser.metadata self._roi_metadata = self._parser.roi_metadata # Set data type self._dtype = self._get_dtype_from_metadata() # Setup the axes self._init_axis('x', self._metadata.width) self._init_axis('y', self._metadata.height) self._init_axis('c', len(self._metadata.channels)) self._init_axis('t', len(self._metadata.frames)) self._init_axis('z', len(self._metadata.z_levels)) # provide the default self.iter_axes = 't' def _get_dtype_from_metadata(self): """ Determine the data type from the metadata. :return: """ bit_depth = self._parser.raw_metadata.image_attributes[six.b('SLxImageAttributes')][six.b('uiBpcInMemory')] if bit_depth <= 16: self._dtype = np.float16 elif bit_depth <= 32: self._dtype = np.float32 else: self._dtype = np.float64 return self._dtype @classmethod def class_exts(cls): return {'nd2'} | super(ND2Reader, cls).class_exts() def close(self): if self._fh is not None: self._fh.close() def get_frame_2D(self, c, t, z): """ Gets a given frame using the parser :param c: :param t: :param z: :return: """ c_name = self._metadata.channels[c] try: image = self._parser.driver.get_image_by_attributes(t, 0, c_name, z, self._metadata.width, self._metadata.height) except (TypeError, NoImageError): return Frame([]) else: return Frame(image, frame_no=image.frame_number, metadata=self._get_frame_metadata()) def _get_frame_metadata(self): """ Get the metadata for one frame :return: """ frame_metadata = { "height": self._metadata.height, "width": self._metadata.width, "date": self._metadata.date, "pixel_microns": self._metadata.pixel_microns, "rois": self._roi_metadata } return frame_metadata @property def pixel_type(self): return self._dtype