You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
2.7 KiB

  1. from pims import FramesSequenceND, Frame
  2. import numpy as np
  3. from nd2reader.exc import NoImageError
  4. from nd2reader.parser import get_parser
  5. import six
  6. class ND2Reader(FramesSequenceND):
  7. """
  8. PIMS wrapper for the ND2 reader
  9. """
  10. def __init__(self, filename):
  11. self.filename = filename
  12. # first use the parser to parse the file
  13. self._fh = open(filename, "rb")
  14. self._parser = get_parser(self._fh)
  15. self._metadata = self._parser.metadata
  16. self._roi_metadata = self._parser.roi_metadata
  17. # Set data type
  18. self._dtype = self._get_dtype_from_metadata()
  19. # Setup the axes
  20. self._init_axis('x', self._metadata.width)
  21. self._init_axis('y', self._metadata.height)
  22. self._init_axis('c', len(self._metadata.channels))
  23. self._init_axis('t', len(self._metadata.frames))
  24. self._init_axis('z', len(self._metadata.z_levels))
  25. # provide the default
  26. self.iter_axes = 't'
  27. def _get_dtype_from_metadata(self):
  28. """
  29. Determine the data type from the metadata.
  30. :return:
  31. """
  32. bit_depth = self._parser.raw_metadata.image_attributes[six.b('SLxImageAttributes')][six.b('uiBpcInMemory')]
  33. if bit_depth <= 16:
  34. self._dtype = np.float16
  35. elif bit_depth <= 32:
  36. self._dtype = np.float32
  37. else:
  38. self._dtype = np.float64
  39. return self._dtype
  40. @classmethod
  41. def class_exts(cls):
  42. return {'nd2'} | super(ND2Reader, cls).class_exts()
  43. def close(self):
  44. if self._fh is not None:
  45. self._fh.close()
  46. def get_frame_2D(self, c, t, z):
  47. """
  48. Gets a given frame using the parser
  49. :param c:
  50. :param t:
  51. :param z:
  52. :return:
  53. """
  54. c_name = self._metadata.channels[c]
  55. try:
  56. image = self._parser.driver.get_image_by_attributes(t, 0, c_name, z, self._metadata.width,
  57. self._metadata.height)
  58. except (TypeError, NoImageError):
  59. return Frame([])
  60. else:
  61. return Frame(image, frame_no=image.frame_number, metadata=self._get_frame_metadata())
  62. def _get_frame_metadata(self):
  63. """
  64. Get the metadata for one frame
  65. :return:
  66. """
  67. frame_metadata = {
  68. "height": self._metadata.height,
  69. "width": self._metadata.width,
  70. "date": self._metadata.date,
  71. "pixel_microns": self._metadata.pixel_microns,
  72. "rois": self._roi_metadata
  73. }
  74. return frame_metadata
  75. @property
  76. def pixel_type(self):
  77. return self._dtype