Search code examples
pythonmatplotlibpyqt5imshowroi

Why can't I successfully draw the region of interest in a matplotlib color map embedded in a pyqt5 gui?


I'm trying to draw a region of interest on a color map that is embedded in a pyqt5 gui. This is an example of what I want.

import sys
from PyQt5.QtWidgets import (QWidget, QPushButton,
                             QHBoxLayout, QVBoxLayout, QApplication)
from PyQt5 import QtCore
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas

import ROI_class as roi # ROI_class.py

class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()
        self.drawButton.clicked.connect(self.draw_map_Callback)
        self.roiButton.clicked.connect(self.choose_roi)

    def initUI(self):
        self.drawButton = QPushButton("draw map")
        self.roiButton = QPushButton("roi")

        self.hbox = QHBoxLayout()
        self.hbox.addStretch(1)
        self.hbox.addWidget(self.drawButton)
        self.hbox.addWidget(self.roiButton)

        self.vbox = QVBoxLayout()
        self.vbox.addStretch(1)
        self.vbox.addLayout(self.hbox)

        self.setLayout(self.vbox)
        self.setGeometry(500, 500, 500, 500)
        self.setWindowTitle('ROI')
        self.show()
        
    def draw_map_Callback(self):        
        img = np.ones((100, 100)) * range(0, 100)
        fig, ax1 = plt.subplots()
        
        self.con_canvas = FigureCanvas(plt.figure(tight_layout=True))
        self.con_canvas.setFocusPolicy(QtCore.Qt.ClickFocus)
        self.con_canvas.setFocus()
        self.con_toolbar = NavigationToolbar(self.con_canvas, self)
        self.vbox.addWidget(self.con_toolbar)
        self.vbox.addWidget(self.con_canvas)
        self._con_ax = self.con_canvas.figure.subplots()
        self.con_img = self._con_ax.imshow(img, cmap ='jet')
        self._con_ax.set_xlabel('xlabel')
        self._con_ax.set_ylabel('ylabel')
        self.con_cbar = self.con_canvas.figure.colorbar(self.con_img)
        self._con_ax.set_aspect('equal')
        
        
    def choose_roi(self):
        y = roi.new_ROI(self.con_img)

        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

It will draw a colormap when I click "draw map". Then I want it to allow me to draw a region of interest with my mouse and get a mask using the code on this link below.

https://github.com/martindurant/misc/blob/master/ROI.py

The "ROI_class" that is imported is just a copy and paste of the code in the link above.

I can successfully draw the plot on the GUI but when I click "roi", it doesn't allow me to draw the region of interest.

When I mad a new file and paste the code in the link above with something like

fig, ax1 = plt.subplots()
s = ax1.imshow(img, cmap ='jet')
ax1.set_xlabel('subcolor')
ax1.set_ylabel('ylabel')
y = new_ROI(s)

at the end of the code, it worked just fine and I was able to draw the region of interest and get the mask of it.

But when I try to do this in the GUI, it wouldn't let me draw the region of interest. I'm very confused why this isn't working.


Solution

  • The problem is that picker (the variable "y") is a local variable that gets destroyed instantly causing the desired behavior not to be executed. The solution is to make it an attribute of the class:

    self.y = roi.new_ROI(self.con_img)