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.

81 lines
3.0 KiB

  1. import six
  2. import numpy as np
  3. class Roi(object):
  4. """
  5. A ND2 ROI representation.
  6. Coordinates are the center coordinates of the ROI in (x, y, z) order in micron.
  7. Sizes are the sizes of the ROI in (x, y, z) order in micron.
  8. Shapes are represented by numbers, defined by constants in this class.
  9. All these properties can be set for multiple time points (in ms).
  10. """
  11. SHAPE_RECTANGLE = 3
  12. SHAPE_CIRCLE = 9
  13. TYPE_BACKGROUND = 2
  14. def __init__(self, raw_roi_dict, metadata):
  15. """
  16. :param raw_roi_dict:
  17. :param metadata
  18. """
  19. self.timepoints = []
  20. self.positions = []
  21. self.sizes = []
  22. self.shape = self.SHAPE_CIRCLE
  23. self.type = self.TYPE_BACKGROUND
  24. self._img_width_micron = metadata.width * metadata.pixel_microns
  25. self._img_height_micron = metadata.height * metadata.pixel_microns
  26. self._pixel_microns = metadata.pixel_microns
  27. self._extract_vect_anims(raw_roi_dict)
  28. def _extract_vect_anims(self, raw_roi_dict):
  29. """
  30. Extract the vector animation parameters from the ROI.
  31. This includes the position and size at the given timepoints.
  32. :param raw_roi_dict:
  33. :return:
  34. """
  35. number_of_timepoints = raw_roi_dict[six.b('m_vectAnimParams_Size')]
  36. for i in range(number_of_timepoints):
  37. self._parse_vect_anim(raw_roi_dict[six.b('m_vectAnimParams_%d') % i])
  38. self.shape = raw_roi_dict[six.b('m_sInfo')][six.b('m_uiShapeType')]
  39. self.type = raw_roi_dict[six.b('m_sInfo')][six.b('m_uiInterpType')]
  40. # convert to NumPy arrays
  41. self.timepoints = np.array(self.timepoints, dtype=np.float)
  42. self.positions = np.array(self.positions, dtype=np.float)
  43. self.sizes = np.array(self.sizes, dtype=np.float)
  44. def _parse_vect_anim(self, animation_dict):
  45. """
  46. Parses a ROI vector animation object and adds it to the global list of timepoints and positions.
  47. :param animation_dict:
  48. :return:
  49. """
  50. self.timepoints.append(animation_dict[six.b('m_dTimeMs')])
  51. # positions are taken from the center of the image as a fraction of the half width/height of the image
  52. position = np.array((0.5 * self._img_width_micron * (1 + animation_dict[six.b('m_dCenterX')]),
  53. 0.5 * self._img_height_micron * (1 + animation_dict[six.b('m_dCenterY')]),
  54. animation_dict[six.b('m_dCenterZ')]))
  55. self.positions.append(position)
  56. size_dict = animation_dict[six.b('m_sBoxShape')]
  57. # sizes are fractions of the half width/height of the image
  58. self.sizes.append((size_dict[six.b('m_dSizeX')] * 0.25 * self._img_width_micron,
  59. size_dict[six.b('m_dSizeY')] * 0.25 * self._img_height_micron,
  60. size_dict[six.b('m_dSizeZ')]))
  61. def is_circle(self):
  62. return self.shape == self.SHAPE_CIRCLE
  63. def is_rectangle(self):
  64. return self.shape == self.SHAPE_RECTANGLE