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.

135 lines
3.7 KiB

  1. # -*- coding: utf-8 -*-
  2. import numpy as np
  3. class Image(np.ndarray):
  4. """
  5. Holds the raw pixel data of an image and provides access to some metadata.
  6. """
  7. def __new__(cls, array):
  8. return np.asarray(array).view(cls)
  9. def __init__(self, array):
  10. self._index = None
  11. self._timestamp = None
  12. self._frame_number = None
  13. self._field_of_view = None
  14. self._channel = None
  15. self._z_level = None
  16. def __array_wrap__(self, obj):
  17. if len(obj.shape) == 0:
  18. return obj[()]
  19. else:
  20. return np.ndarray.__array_wrap__(obj)
  21. def add_params(self, index, timestamp, frame_number, field_of_view, channel, z_level):
  22. """
  23. :param index: The integer that can be used to directly index this image
  24. :type index: int
  25. :param timestamp: The number of milliseconds after the beginning of the acquisition that this image was taken.
  26. :type timestamp: float
  27. :param frame_number: The order in which this image was taken, with images of different channels/z-levels
  28. at the same field of view treated as being in the same frame.
  29. :type frame_number: int
  30. :param field_of_view: The label for the place in the XY-plane where this image was taken.
  31. :type field_of_view: int
  32. :param channel: The name of the color of this image
  33. :type channel: str
  34. :param z_level: The label for the location in the Z-plane where this image was taken.
  35. :type z_level: int
  36. """
  37. self._index = index
  38. self._timestamp = timestamp
  39. self._frame_number = int(frame_number)
  40. self._field_of_view = field_of_view
  41. self._channel = channel
  42. self._z_level = z_level
  43. @property
  44. def index(self):
  45. return self._index
  46. @property
  47. def height(self):
  48. """
  49. The height in pixels.
  50. :rtype: int
  51. """
  52. return self.shape[0]
  53. @property
  54. def width(self):
  55. """
  56. The width in pixels.
  57. :rtype: int
  58. """
  59. return self.shape[1]
  60. @property
  61. def field_of_view(self):
  62. """
  63. The index of the stage location where this image was acquired.
  64. :rtype: int
  65. """
  66. return self._field_of_view
  67. @property
  68. def timestamp(self):
  69. """
  70. The number of seconds after the beginning of the acquisition that the image was taken. Note that for a given
  71. field of view and z-level offset, if you have images of multiple channels, they will all be given the same
  72. timestamp. That's just how ND2s are structured, so if your experiment depends on millisecond accuracy,
  73. you need to find an alternative imaging system.
  74. :rtype: float
  75. """
  76. # data is actually stored in milliseconds
  77. return self._timestamp / 1000.0
  78. @property
  79. def frame_number(self):
  80. """
  81. The index of the group of images taken sequentially that all have the same group number and field of view.
  82. :rtype: int
  83. """
  84. return self._frame_number
  85. @property
  86. def channel(self):
  87. """
  88. The name of the filter used to acquire this image. These are user-supplied in NIS Elements.
  89. :rtype: str
  90. """
  91. return self._channel
  92. @property
  93. def z_level(self):
  94. """
  95. The vertical offset of the image. These are simple integers starting from 0, where the 0 is the lowest
  96. z-level and each subsequent level incremented by 1.
  97. For example, if you acquired images at -3 µm, 0 µm, and +3 µm, your z-levels would be:
  98. -3 µm: 0
  99. 0 µm: 1
  100. +3 µm: 2
  101. :rtype: int
  102. """
  103. return self._z_level