gdm_visualization.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. from PyQt5.QtWidgets import QMainWindow, QVBoxLayout, QWidget, QComboBox, QHBoxLayout, QFormLayout, QPushButton
  2. from PyQt5.QtCore import pyqtSignal, pyqtSlot
  3. from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
  4. from matplotlib import pyplot as plt
  5. import numpy as np
  6. from view.python_core.gdm_generation import get_roi_gdm_traces_dict
  7. from view.python_core.overviews import generate_overview_image, prep_overview_for_output, \
  8. colorize_overview_add_border_etc
  9. from view.python_core.rois.roi_io import get_roi_io_class
  10. class MplCanvas(FigureCanvasQTAgg):
  11. def __init__(self, parent=None, width=5.0, height=4.0, dpi=100):
  12. fig = plt.Figure(figsize=(width, height), dpi=dpi, constrained_layout=True)
  13. self.axes = fig.add_subplot(111)
  14. super(MplCanvas, self).__init__(fig)
  15. class GDMViz(QMainWindow):
  16. def __init__(self, p1, flags):
  17. super().__init__()
  18. flags_copy = flags.copy()
  19. flags_copy.update_flags({
  20. "SO_xgap": 0,
  21. "CTV_Method": 300, "SO_Method": 0, "SO_individualScale": 3,
  22. "SO_MV_colortable": "gray",
  23. "SO_showROIs": f"3{flags['RM_ROITrace']}",
  24. "SO_withinArea": True,
  25. "SO_bgColor": "k",
  26. "SO_thresholdShowImage": "bgColor"
  27. })
  28. self.stimuli_frames = p1.pulsed_stimuli_handler.get_pulse_start_end_frames(allow_fractional_frames=True)
  29. # data is in X, Y, color format
  30. self.overview_frame_clean, data_limits, overview_generator_used = \
  31. colorize_overview_add_border_etc(overview_frame=p1.foto1, flags=flags_copy, p1=None)
  32. roi_mask_color_label_tuples = overview_generator_used.roi_marker.roi_mask_color_label_tuples
  33. # if the original size along a dimension is odd, it gets padded by one pixel to make it even.
  34. # E.g.: if the original data is 153x106, overview generated is 154x106
  35. # so need to resize masks
  36. self.roi_mask_dict = {}
  37. for x, y, z in roi_mask_color_label_tuples:
  38. if x.shape[0] < self.overview_frame_clean.shape[0] or \
  39. x.shape[1] < self.overview_frame_clean.shape[1]:
  40. enlarged_mask = np.zeros(self.overview_frame_clean.shape[:2], dtype=bool)
  41. enlarged_mask[:x.shape[0], :x.shape[1]] = x
  42. else:
  43. enlarged_mask = x
  44. self.roi_mask_dict[z] = (enlarged_mask, y)
  45. roi_data_dict = overview_generator_used.roi_marker.roi_data_dict
  46. self.roi_label_trace_dict = get_roi_gdm_traces_dict(p1=p1, flags=flags, roi_data_dict=roi_data_dict)
  47. self.overview_canvas = MplCanvas(self, width=5, height=4, dpi=300)
  48. self.overview_canvas.figure.suptitle(
  49. "Pixels outside the area mask are black. "
  50. "Pixels inside indicates \nvalues of the morphological image (foto1). "
  51. "Each ROI has a different color,\n and selected ROIs a slightly brighter", size=4)
  52. overview_for_output = prep_overview_for_output(self.overview_frame_clean)
  53. self.overview_canvas.axes.imshow(np.flip(overview_for_output, axis=0), origin="lower")
  54. self.overview_canvas.axes.tick_params(labelsize=4)
  55. # fake points for label
  56. for label, (_, color) in self.roi_mask_dict.items():
  57. self.overview_canvas.axes.plot([0], [0], color=color, ls="-", label=label)
  58. self.overview_canvas.axes.legend(
  59. bbox_to_anchor=(1.05, 1), loc="upper left",
  60. ncol=3, markerscale=0.5, title_fontsize=6, fontsize=4, title="ROI label"
  61. )
  62. self.overview_canvas.draw_idle()
  63. centralWidget = QWidget(self)
  64. main_vbox = QVBoxLayout(centralWidget)
  65. top_hbox = QHBoxLayout()
  66. choosers_formlayout = QFormLayout()
  67. self.roi_choosers = []
  68. for i in range(3):
  69. roi_chooser = QComboBox(parent=centralWidget)
  70. roi_chooser.addItems(list(roi_data_dict.keys()) + ["---Choose a ROI to visualize---"])
  71. roi_chooser.setCurrentText("---Choose a ROI to visualize---")
  72. self.roi_choosers.append(roi_chooser)
  73. choosers_formlayout.addRow(f"ROI {i}", roi_chooser)
  74. refresh_button = QPushButton("Refresh overview and traces")
  75. refresh_button.clicked.connect(self.refresh)
  76. choosers_formlayout.addWidget(refresh_button)
  77. top_hbox.addLayout(choosers_formlayout)
  78. top_hbox.addWidget(self.overview_canvas)
  79. main_vbox.addLayout(top_hbox)
  80. self.trace_canvas = MplCanvas(self, width=5, height=4, dpi=300)
  81. main_vbox.addWidget(self.trace_canvas)
  82. self.setCentralWidget(centralWidget)
  83. # set one the choice of one of the chooser as an example
  84. self.roi_choosers[0].setCurrentText(roi_mask_color_label_tuples[0][-1])
  85. self.refresh()
  86. self.setWindowTitle("GDM Visualizer")
  87. @pyqtSlot(name="refresh signal")
  88. def refresh(self):
  89. self.trace_canvas.axes.cla()
  90. chosen_labels = [x.currentText() for x in self.roi_choosers
  91. if x.currentText() != "---Choose a ROI to visualize---"]
  92. for chosen_label in chosen_labels:
  93. chosen_mask, chosen_roi_color = self.roi_mask_dict[chosen_label]
  94. trace = self.roi_label_trace_dict[chosen_label]
  95. self.trace_canvas.axes.plot(
  96. trace,
  97. ls="-", marker=None, color=chosen_roi_color
  98. )
  99. for this_stimulus_frames in self.stimuli_frames:
  100. self.trace_canvas.axes.axvspan(*this_stimulus_frames, color="gray", alpha=0.5, edgecolor=None)
  101. self.trace_canvas.axes.set_ylabel("deltaF/F (a.u.)", size=4)
  102. self.trace_canvas.axes.set_xlabel("Frame number (0, 1, 2...)", size=4)
  103. self.trace_canvas.axes.grid(True)
  104. self.trace_canvas.axes.tick_params(labelsize=4, grid_color="k", grid_linestyle="--", grid_alpha=0.1)
  105. x_end = self.trace_canvas.axes.get_xlim()[1]
  106. self.trace_canvas.axes.set_xticks(np.linspace(0, x_end, 10).astype(int))
  107. self.trace_canvas.draw_idle()