I'm making a GUI which is to have a couple user input boxes and a plot which will use factors in the input boxes to scale data. The GUI will need an apply button and an export button. I am using PyQt5 for the GUI and Matplotlib for the plotting. My approach has been to create separate QWidgets for the plot and the input boxes and tie them together in a third QMainWindow.
I have the GUI appearing correctly
How can I get the apply button to send the 3 variables across to the main class and to the plotting class? Would it be possible to have all of this happen within one class to simplify how my variables will work?
import sys
import matplotlib
matplotlib.use("Qt5Agg")
from PyQt5 import QtCore
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
from PyQt5.QtWidgets import *
from numpy import arange, sin, pi
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class AppForm(QWidget):
def __init__(self):
# Initialize the object as a QWidget and
# set its title and minimum width
QWidget.__init__(self)
self.setWindowTitle('Input')
self.setMinimumWidth(400)
# Create the QVBoxLayout that lays out the whole form
self.layout = QVBoxLayout()
# Create the form layout that manages the labeled controls
self.form_layout = QFormLayout()
self.aFactor = QLineEdit(self)
self.mFactor = QLineEdit(self)
self.cZone = QLineEdit(self)
self.form_layout.addRow('AFactor', self.aFactor)
self.form_layout.addRow('MFactor', self.mFactor)
self.form_layout.addRow('CZone', self.cZone)
self.layout.addLayout(self.form_layout)
self.button_box = QHBoxLayout()
self.button_box.addStretch(1)
self.apply_button = QPushButton("Apply", self)
self.output_button = QPushButton("Output", self)
self.button_box.addWidget(self.apply_button)
self.button_box.addWidget(self.output_button)
self.layout.addLayout(self.button_box)
self.setLayout(self.layout)
self.apply_button.clicked.connect(self.applyButton)
def applyButton(self):
self.af = self.aFactor
self.mf = self.mFactor
self.cz = self.cZone
print self.af.text(), self.mf.text(), self.cz.text()
class MyMplCanvas(FigureCanvas):
"""Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
def __init__(self, parent=None, width=5, height=4, dpi=100, title='title'):
self.title = title
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
fig.suptitle(title)
# We want the axes cleared every time plot() is called
self.axes.hold(False)
self.compute_initial_figure()
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self,
QSizePolicy.Expanding,
QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
def compute_initial_figure(self):
pass
class MyStaticMplCanvas(MyMplCanvas):
"""Simple canvas with a sine plot."""
def compute_initial_figure(self):
t = arange(0.0, 3.0, 0.01)
s = sin(2*pi*t)
self.axes.plot(t, s)
self.axes.set_ylabel('label1')
self.axes.set_xlabel('label')
self.axes.grid(True)
class ApplicationWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.setWindowTitle("application main window")
self.setMinimumWidth(800)
self.setMinimumHeight(600)
self.file_menu = QMenu('&File', self)
self.file_menu.addAction('&Quit', self.fileQuit,
QtCore.Qt.CTRL + QtCore.Qt.Key_Q)
self.menuBar().addMenu(self.file_menu)
self.help_menu = QMenu('&Help', self)
self.menuBar().addSeparator()
self.menuBar().addMenu(self.help_menu)
self.help_menu.addAction('&About', self.about)
self.main_widget = QWidget(self)
l = QVBoxLayout(self.main_widget)
form = AppForm()
sc = MyStaticMplCanvas(self.main_widget, width=5, height=4, dpi=100, title='Title 1')
l.addWidget(form)
l.addWidget(sc)
self.main_widget.setFocus()
self.setCentralWidget(self.main_widget)
#self.statusBar().showMessage("Cool", 2000
def fileQuit(self):
self.close()
def closeEvent(self, ce):
self.fileQuit()
def about(self):
QMessageBox.about(self, "About",)
if __name__ == '__main__':
app = QApplication(sys.argv)
aw = ApplicationWindow()
aw.setWindowTitle("PyQt5 Matplot Example")
aw.show()
#sys.exit(qApp.exec_())
app.exec_()
There are several options here:
(a) Peform the work in the main class:
Instead of connecting the button in the AppForm to a method in AppForm, do the same in the ApplicationWindow.
self.form = AppForm()
self.sc = MyStaticMplCanvas(....)
self.form.apply_button.clicked.connect(self.applyButton)
def applyButton(self):
tx = self.form.aFactor.text()
# do something with tx
# e.g. call a method from MplCanvas
self.sc.someMethod(tx)
(b) Use signals and slots:
Create a signla in AppForm. Once the button is clicked, applyButton may emit this signal with the relevant content. In ApplicationWindow connect that signal to a method which can use the supplied data in some way. You can also connect it directly to a method of MplCanvas.
class AppForm(QWidget):
mysignal = pyqtSignal(object)
def __init__(self):
....
self.apply_button.clicked.connect(self.applyButton)
def applyButton(self):
self.mysignalemit((self.aFactor.text(),self.mFactor.text(), self.cZone()) )
class ApplicationWindow(QMainWindow):
def __init__(self):
....
self.form = AppForm()
self.sc = MyStaticMplCanvas(....)
self.form.mysignal.connect(self.useButtonResults)
self.form.mysignal.connect(self.sc.someMethod)
def useButtonResults(self, obj):
a,b,c = obj
# do something with a, b, c
(c) Use a single class to do everything:
Just put everything in a single class and do whatever you like.
Related
I'm trying to do something pretty straight forward in Matplotlib, but hitting a ton of hurdles; after googling for hours, I'm thinking this takes some very specific magic. I just want my GUI to start on a blank screen and then import a file that needs a colorbar - if the file is good, a colorbar is added. If the file is added again (or a different one), the colorbar is removed and a new one is plotted. If the file is bad, we reset to initial conditions (no colorbars or plot). I really hope the below code makes sense for what I'm getting at here, thank you so much for your help and time in advance:
import sys
import os
import random
import matplotlib
matplotlib.use('Qt5Agg')
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QGridLayout, QFileDialog, QPushButton
import numpy as np
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class MyMplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
MyMplCanvas.fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = MyMplCanvas.fig.add_subplot(111)
self.compute_initial_figure()
FigureCanvas.__init__(self, MyMplCanvas.fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self,
QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
def compute_initial_figure(self):
pass
class MyDynamicMplCanvas(MyMplCanvas):
def __init__(self, *args, **kwargs):
MyMplCanvas.__init__(self, *args, **kwargs)
def compute_initial_figure(self):
C=np.random.rand(500).reshape((20,25))
S=np.random.rand(500).reshape((20,25))
dc = self.function(S,C)
im = self.axes.imshow(dc, alpha = 0)
MyMplCanvas.fig.patch.set_facecolor('k')
self.axes.patch.set_facecolor('k')
# don't want to show the cb initially (imagine GUI starts on a blank screen)
#cb = MyMplCanvas.fig.colorbar(im, ax=self.axes,
#orientation='vertical')#,use_gridspec=True)??
def update_figure(self):
# need something like the below to delete subsequent colorbars if they exist:
#if MyMplCanvas.fig.axes[1] is not None:
# MyMplCanvas.fig.delaxes(MyMplCanvas.fig.axes[1]) #remove colorbar
self.axes.cla()
if P1.df: #datafile is good
MyMplCanvas.fig.patch.set_facecolor('w')
self.axes.patch.set_facecolor('w')
C=np.random.rand(500).reshape((20,25))
S=np.random.rand(500).reshape((20,25))
dc = self.function(S,C)
im = self.axes.imshow(dc)
cb = MyMplCanvas.fig.colorbar(im, ax=self.axes,
orientation='vertical')#,use_gridspec=True)??
else: #datafile was bad, or they pressed cancel
C=np.random.rand(500).reshape((20,25))
S=np.random.rand(500).reshape((20,25))
dc = self.function(S,C)
im = self.axes.imshow(dc, alpha = 0)
MyMplCanvas.fig.patch.set_facecolor('k')
self.axes.patch.set_facecolor('k')
self.show()
self.draw()
def function(self,s,c):
return s*2+c
class P1(QtWidgets.QWidget):
df = False
def __init__(self, parent=None):
super(P1, self).__init__(parent)
layout = QGridLayout(self)
self.button_browse1 = QPushButton('Browse Good', self)
self.button_browse1.clicked.connect(self.browseFile1)
layout.addWidget(self.button_browse1, 1, 1, 1, 1)
self.button_browse1.show()
self.button_browse2 = QPushButton('Browse Bad', self)
self.button_browse2.clicked.connect(self.browseFile2)
layout.addWidget(self.button_browse2, 2, 1, 1, 1)
self.button_browse2.show()
self.dc = MyDynamicMplCanvas(self, width=5, height=4, dpi=100)
layout.addWidget(self.dc, 3, 1, 1, 1)
def browseFile1(self):
P1.df = True
self.dc.update_figure()
def browseFile2(self):
P1.df = False
self.dc.update_figure()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.stack = QtWidgets.QStackedWidget(self)
P1f = P1(self)
self.stack.addWidget(P1f)
self.setCentralWidget(self.stack)
if __name__ == '__main__':
qApp = QtWidgets.QApplication(sys.argv)
aw = MainWindow()
aw.show()
sys.exit(qApp.exec_())
Okay, so for anyone else stumbling on this, the trick is to first define your colorbar the very first time you plot (initial figure) via the top Class its in, i.e., MyMplCanvas.cbar = MyMplCanvas.fig.colorbar(im). Its very important to define it up front even if you didn't want to even use it yet.
Then at the top of the update plot function, simply call MyMplCanvas.cbar.remove().
I'm trying to use matplotlib in a Qt5 app, to do some live plots. Focusing on speeding up the drawing of the graph, based on what Basti wrote on his blog (http://bastibe.de/2013-05-30-speeding-up-matplotlib.html).
The example is based on the matplotlib example: embedding_in_qt5.py
I'm a big fan of ggplot, and problem is that the grid disappear, when i update the graph. Does not matter if ggplot is used or not. This is where the code problems exist:
#### FAST UPDATE VERSION - MISSING GRID ####
# Basti version
# self.axes.draw_artist(self.axes.patch)
# self.axes.draw_artist(lines[0])
# My version
# redraw_in_frame seems to do the same, but not much on the documentation
# https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.redraw_in_frame.html
self.axes.redraw_in_frame()
self.figure.canvas.update()
self.figure.canvas.flush_events()
#### SLOW VERSION - EVERYTHING (else) LOOKS GOOD ####
# self.draw()
The entire code for the problem is
# embedding_in_qt5.py --- Simple Qt5 application embedding matplotlib canvases
#
# Copyright (C) 2005 Florent Rougon
# 2006 Darren Dale
# 2015 Jens H Nielsen
#
# This file is an example program for matplotlib. It may be used and
# modified with no restriction; raw copies as well as modified versions
# may be distributed without limitation.
import sys
import os
import matplotlib as plt
import matplotlib.pyplot as plty
import numpy as np
import time
plty.style.use('ggplot')
# Make sure that we are using QT5
plt.use('Qt5Agg')
from PyQt5 import QtCore, QtWidgets
# from numpy import arange, sin, pi
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
progname = os.path.basename(sys.argv[0])
progversion = "0.1"
class MyMplCanvas(FigureCanvas):
"""Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
def __init__(self, parent=None, width=5, height=4, dpi=100):
self.fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = self.fig.add_subplot(111)
self.step = 0.05
self.xaxis = np.arange(0, np.pi*2, self.step)
self.yaxis = self.xaxis
self.compute_initial_figure()
# Time skip variable
self.time_skip = 0
FigureCanvas.__init__(self, self.fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self,
QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
def compute_initial_figure(self):
pass
class MyStaticMplCanvas(MyMplCanvas):
"""Simple canvas with a sine plot."""
def compute_initial_figure(self):
self.yaxis = np.sin(self.xaxis)
self.axes.plot(self.xaxis, self.yaxis)
self.axes.grid(True)
class MyDynamicMplCanvas(MyMplCanvas):
"""A canvas that updates itself every second with a new plot."""
def __init__(self, *args, **kwargs):
MyMplCanvas.__init__(self, *args, **kwargs)
timer = QtCore.QTimer(self)
timer.timeout.connect(self.update_figure)
timer.start(25)
def compute_initial_figure(self):
self.axes.plot(self.xaxis, np.sin(self.yaxis))
self.axes.grid(True)
def update_figure(self):
# skip a few timer events
self.time_skip += 1
if self.time_skip > 10:
# Update the axis parameters to generate the sine
self.yaxis += self.step
# get the line
lines = self.axes.get_lines()
# and update it
lines[0].set_ydata(np.sin(self.yaxis))
#### FAST UPDATE VERSION - MISSING GRID ####
# Basti version
# self.axes.draw_artist(self.axes.patch)
# self.axes.draw_artist(lines[0])
# redraw_in_frame seems to do the same, but not much on the documentation
# https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.redraw_in_frame.html
self.axes.redraw_in_frame()
self.figure.canvas.update()
self.figure.canvas.flush_events()
#### SLOW VERSION - EVERYTHING (else) LOOKS GOOD ####
# self.draw()
class ApplicationWindow(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.setWindowTitle("application main window")
self.file_menu = QtWidgets.QMenu('&File', self)
self.file_menu.addAction('&Quit', self.fileQuit,
QtCore.Qt.CTRL + QtCore.Qt.Key_Q)
self.menuBar().addMenu(self.file_menu)
self.help_menu = QtWidgets.QMenu('&Help', self)
self.menuBar().addSeparator()
self.menuBar().addMenu(self.help_menu)
self.help_menu.addAction('&About', self.about)
self.main_widget = QtWidgets.QWidget(self)
l = QtWidgets.QVBoxLayout(self.main_widget)
sc = MyStaticMplCanvas(self.main_widget, width=5, height=4, dpi=100)
dc = MyDynamicMplCanvas(self.main_widget, width=5, height=4, dpi=100)
l.addWidget(sc)
l.addWidget(dc)
self.main_widget.setFocus()
self.setCentralWidget(self.main_widget)
self.statusBar().showMessage("All hail matplotlib!", 2000)
def fileQuit(self):
self.close()
def closeEvent(self, ce):
self.fileQuit()
def about(self):
QtWidgets.QMessageBox.about(self, "About",
"""embedding_in_qt5.py example
Copyright 2005 Florent Rougon, 2006 Darren Dale, 2015 Jens H Nielsen
This program is a simple example of a Qt5 application embedding matplotlib
canvases.
It may be used and modified with no restriction; raw copies as well as
modified versions may be distributed without limitation.
This is modified from the embedding in qt4 example to show the difference
between qt4 and qt5"""
)
qApp = QtWidgets.QApplication(sys.argv)
aw = ApplicationWindow()
aw.setWindowTitle("%s" % progname)
aw.show()
sys.exit(qApp.exec_())
#qApp.exec_()
Using pyqtgraph will not be a simple solution for me, as I am not very confident in styling it - so unless there is a use('ggplot') I'm pursuing this solution.
form_class = uic.loadUiType("GUI.ui")[0] # Load the UI
class MainWindowClass(QtGui.QMainWindow, form_class):
def __init__(self, target, Afb, np, conversion, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
if self.RadioButton.isChecked():
Ids, Ugs = unipolar_steuerkennlinie(self.target, self.Afb, self.np, self.conversion)
def plot_matplotlibwidget(self, *args):
for x in range(0, 40):
self.matplotlibwidget.axes.plot([args[0][x]], [[args[1][x]]])
self.matplotlibwidget.axes.figure.canvas.draw_idle()
Hi, I have this function and I don't really know how to plot correctly. Now it shows nothing but the does change the scale.
Since it is hard to completely replicate your code and error, I've created you a simple minimal GUI that has a MPL widget and draws a few random lines.
from PyQt4 import QtGui, QtCore
import sys
import functools
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
import numpy as np
from matplotlib.figure import Figure
class test(QtGui.QWidget):
def __init__(self,parent=None):
self.widget=QtGui.QWidget.__init__(self, parent)
# Button to plot
self.btnPlot = QtGui.QPushButton('Plot')
self.btnPlot.connect(self.btnPlot, QtCore.SIGNAL('clicked()'), self.btnPlotPressed)
# Line edit for number of lines
self.qleN = QtGui.QLineEdit(str(0))
# Create canvas
self.setupMPLWidget()
# Layout
self.hbox = QtGui.QHBoxLayout()
self.hbox.addWidget(self.btnPlot)
self.hbox.addWidget(self.qleN)
self.hbox.addWidget(self.canvas)
self.setLayout(self.hbox)
self.show()
def btnPlotPressed(self):
"""Plots a few lines."""
# Get number of buttons to add
n=int(self.qleN.text())
# Generate some data
xs,ys=self.randData(n)
# Plot
self.plot_matplotlibwidget(xs,ys)
def randData(self,n):
"""Creates n random data sets."""
ys=[]
xs=[]
for i in range(n):
xs.append(np.arange(n-i))
ys.append(np.random.random(size=xs[-1].shape))
return xs,ys
def plot_matplotlibwidget(self,*args):
"""Plots list of datasets."""
for x in range(0, len(args[0])):
self.ax.plot(args[0][x], args[1][x])
self.ax.figure.canvas.draw_idle()
def setupMPLWidget(self):
"""Sets up a MPL figure to draw on."""
# Create parenting widget
self.plotFrame = QtGui.QWidget()
self.plotFrame.setMaximumWidth(1)
# Create Figure
self.fig = Figure( dpi=100)
#self.fig.set_size_inches(100,100,forward=True)
self.canvas = FigureCanvas(self.fig)
self.canvas.setParent(self.plotFrame)
self.ax = self.fig.add_subplot(111)
def main():
#Creating application
app = QtGui.QApplication(sys.argv)
main_win = test()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
It has a little QLE where you can specify how many lines you want to draw. I hope this helps.
I am writing a program which is supposed to give me data of a chart when I click certain buttons. I have given the program as far as I am right now. (I still have to connect the last 4 buttons but the first one works.) Now there is another problem: I used to have a chart displayed as I clicked on "One Plot" but since I activated "First Button", the chart does not appear anymore due to the problem mentioned problem. This is the script:
class Main(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.setupUi(self)
self.fig_dict = {}
self.mplfigs.itemClicked.connect(self.changefig)
self.button1.setText("First Point")
self.button1.clicked.connect(self.onClickButton1)
self.dialogbutton1 = PopUp(self)
fig = Figure()
self.addmpl(fig)
#QtCore.pyqtSlot()
def changefig(self, item):
text = item.text()
self.rmmpl()
self.addmpl(self.fig_dict[str(text)])
def addfig(self, name, fig):
self.fig_dict[name] = fig
self.mplfigs.addItem(name)
def addmpl(self, fig):
self.canvas = FigureCanvas(fig)
self.mplvl.addWidget(self.canvas)
self.canvas.draw()
self.toolbar = NavigationToolbar(self.canvas, self.mplwindow, coordinates=True)
self.mplvl.addWidget(self.toolbar)
def onClickButton1(self):
# When button 1 is clicked, I do the following
print "does nothing now."
self.dialogbutton1.exec_()
def rmmpl(self,):
self.mplvl.removeWidget(self.canvas)
self.canvas.close()
self.mplvl.removeWidget(self.toolbar)
self.toolbar.close()
class PopUp(QtGui.QDialog):
def __init__(self, parent=None):
super(PopUp, self).__init__(parent)
self.buttonBox = QtGui.QDialogButtonBox(self)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.textBrowser = QtGui.QTextBrowser(self)
self.textBrowser.append("x - Coordinate = 0 y - Coordinate = 0.031451")
self.verticalLayout = QtGui.QVBoxLayout(self)
self.verticalLayout.addWidget(self.textBrowser)
self.verticalLayout.addWidget(self.buttonBox)
if __name__ == '__main__':
import sys
from PyQt4 import QtGui
import numpy as np
fig1 = Figure()
ax1f1 = fig1.add_subplot(111)
ax1f1.plot(np.random.rand(5))
app = QtGui.QApplication(sys.argv)
main = Main()
main.addfig('One plot', fig1)
print main.fig_dict
main.show()
sys.exit(app.exec_())
In class Main, you are calling changefig function as self.mplfigs.itemClicked.connect(self.changefig).
But function definition of changefig is def changefig(self, item): which expects two arguments - self and item.
When you called changefig - self.mplfigs.itemClicked.connect(self.changefig), only self is passed. But item is not passed.
That's why you are getting that error.
It should be self.mplfigs.itemClicked.connect(self.changefig(item))
I need the small popup dialog to appear at cursor position when user clicks my Chaco plot. But when there are many points in the plot (~100.000) the popup window loads too slow (1-2 seconds) and not responsive in the beginning. So the application becomes not very interactive.. I have no idea how I can speed it up. Can you suggest any solution, workaround or advice something?
Code example:
from chaco.api import ArrayPlotData, Plot, BaseTool
from enable.component_editor import ComponentEditor
from traits.api import HasTraits, Instance
from traitsui.api import View, Item
import numpy as np
from PyQt4 import QtGui, QtCore
# simple popup with button and lineedit
class Dialog(QtGui.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.Popup)
self.resize(100, 50)
self.layout = QtGui.QVBoxLayout(self)
self.lineedit = QtGui.QLineEdit()
self.button = QtGui.QPushButton('button')
self.layout.addWidget(self.button)
self.layout.addWidget(self.lineedit)
# new Tool to process right click over plot
class RightClickTool(BaseTool):
def __init__(self, *args, **kw):
self.dlg = Dialog()
super(RightClickTool, self).__init__(*args, **kw)
def normal_right_down(self, event):
self.dlg.show() # show the dialog on right click
event.handled = True
class MyPlot(HasTraits):
plot = Instance(Plot)
traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False))
def __init__(self):
super(MyPlot, self).__init__()
# data to plot
x = np.linspace(0, 1, 10**6)
y = np.random.rand(10**6)
plotdata = ArrayPlotData(x=x, y=y)
plot = Plot(plotdata)
plot.tools.append(RightClickTool(plot))
plot.plot(('x', 'y'))
self.plot = plot
lineplot = MyPlot()
lineplot.configure_traits()