1

Background:

  1. I am writing a GUI-based data analysis tool with PyQt5.
  2. I use numpy.genfromtxt to bring in the x/y data.
  3. I view the x/y data with matplotlib.
  4. I use a qt5agg NavigationToolbar2QT to navigate my data.
  5. I have a working solution (below) using a SpanSelector from matplotlib.widgets to store subsets of my plot's visible data in self.sel_x and self.sel_y.
  6. Apologies in advance if this has a painfully obvious solution (I've not been able to ferret it out of the docs after several hours of searching) and/or it already has an SO answer (if so, I'm not capable of guessing the proper search term).

Question:

When I zoom into the plot using the NavigationToolbar2QT, what matplotlib objects/methods do I use to identify the subset of data that the plot is currently displaying?

I think that get_data_interval() will work, but I can't determine how to return the X/YAxis objects of my plot (because I used figure.add_subplot(111))?

from PyQt5 import QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import matplotlib.widgets as mwidgets
import numpy as np


class PlotWin(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(PlotWin, self).__init__(parent)
        QtWidgets.QMainWindow.__init__(self, parent)

        self.win = QtWidgets.QWidget(self)
        self.setCentralWidget(self.win)
        layout = QtWidgets.QVBoxLayout(self.win)

        self.canvas = FigureCanvas(Figure())
        layout.addWidget(self.canvas)
        self.addToolBar(NavigationToolbar(self.canvas, self))
        self.ax1 = self.canvas.figure.add_subplot(111)
        self.x = np.linspace(1, 100, 100)
        self.y = np.random.rand(100, 1)
        self.ax1.plot(self.x, self.y)
        self.span = mwidgets.SpanSelector(self.ax1, self.on_select, 'horizontal', useblit=True,
                                          rectprops=dict(alpha=0.5, facecolor='red'), button=[1])

    def on_select(self, xmin, xmax):
        indmin, indmax = np.searchsorted(self.x, (xmin, xmax))
        indmax = min(len(self.x) - 1, indmax)
        sel_x = self.x[indmin:indmax]
        sel_y = self.y[indmin:indmax]
        self.ax1.plot(sel_x, sel_y, "o")
        self.canvas.draw()


if __name__ == '__main__':
    import sys

    if not QtWidgets.QApplication.instance():
        app = QtWidgets.QApplication(sys.argv)
    else:
        app = QtWidgets.QApplication.instance()
    window = PlotWin()
    window.show()
    app.exec_()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
dondsmith2
  • 23
  • 6
  • Have you tried to work out the details with separate, *toy* code that just makes a plot to play with? - kinda like a [mcve]? – wwii Feb 24 '18 at 04:00
  • It's not really clear what you are trying to achieve. What is the problem you face? In how far does the code not do what you want? – ImportanceOfBeingErnest Feb 24 '18 at 10:04
  • Thanks everyone for the help...I completely missed the "briefly noted" Axes events mention in the matplotlib documentation - that is *exactly* what I needed! – dondsmith2 Feb 26 '18 at 02:08

0 Answers0