Exemple #1
0
class MPLplotter(QtGui.QWidget):
    """
  This creates a plotting area with a MPL toolbar.

  This is called for each tabbed sheet that needs a plot window.  The
  toolbar belongs to the canvas.

  Public attributes::
    fig -    a Figure() instance
    canvas - a FigureCanvas() instance
  """
    def __init__(self):
        """
    Instantiate MPLplotter

    It lays out the canvas and the toolbar
    """
        super(MPLplotter, self).__init__()
        self.fig = Figure()
        self.fig.hold(False)
        self.canvas = MPLcanvas(self.fig, self)
        vlayout = QtGui.QVBoxLayout()
        vlayout.addWidget(self.canvas)
        vlayout.addWidget(self.canvas.toolbar)
        self.setLayout(vlayout)
        self.canvas.show()
def setup_canvas(remote):
    """
    Setup the canvas, for use by the other functions that popluate it with
    plots.
    """
    global f, canvas, degreeChar, num_plots
    degreeChar = u'\N{DEGREE SIGN}'
    num_plots = 38
    plot_height = 200
    
    f = Figure(dpi=100)
    f.hold(False)
    if remote == True:
        canvas = FigureCanvasGTK(f)  # a gtk.DrawingArea
    else:
        canvas = FigureCanvasGTKAgg(f)  # a gtk.DrawingArea
    
    # the size request sets the size of the area for the plots.  Second number is the height
    canvas.set_size_request(800, num_plots * plot_height)
    app.viewport_matplotlib.add(canvas)
    canvas.show()
Exemple #3
0
class Watcher(QMainWindow):
    """"""
    def __init__(self, freezer, parent=None):
        """Constructor for Viewer"""
        self.freezer = freezer
        self.numTrials = 0
        self.currTrialNum = 0
        self.allTrials = None
        self.allAlignedTrials = None
        self.allOnsets = None
        self.idList = None

        # # Useful stuff
        self.onsetLine1 = None
        self.onsetLine2 = None

        self.isDragging = False

        QMainWindow.__init__(self, parent)
        # self.showMaximized()
        self.createMainFrame()
        # self.drawTrial()

    def queryData(self, queryStr):
        """Query some data from freezer
        """

        self.idList = []

        self.allTrials = []
        self.allAlignedTrials = []
        self.allOnsets = []

        self.allQueryResults = {
        }  # {'idxxx': {'var1':value1, 'var2':value2...}}
        self.queryStr = queryStr

        # allDocs = self.freezer.processed.find(eval(self.queryStr))
        allDocs = self.freezer.posts.find(eval(self.queryStr))
        for doc in allDocs:
            s = StringIO.StringIO(doc['trialData'])
            tTrialData = pd.read_csv(s)
            self.allTrials.append(tTrialData)

            t = 0  #doc['timeOnset']
            self.allOnsets.append(t)

            tId = doc['_id']
            self.idList.append(tId)

            self.allQueryResults[tId] = {
                'isAccepted': doc['isAccepted'],
                'trialData': tTrialData,
                'timeOnset': int(0.0)
            }

        self.numTrials = len(self.allTrials)

        # self.allAlignedTrials = [t for t in self.allTrials]
        print "Found", self.numTrials, "trials."

    def freezeAllOnsets(self):
        """Freeze timeOnset field in Freezer
        """
        allDocs = self.freezer.processed.find(eval(self.queryStr))
        try:
            for onset, doc in zip(self.allOnsets, allDocs):
                self.freezer.processed.update({'_id': doc['_id']},
                                              {'$set': {
                                                  'timeOnset': onset
                                              }})
            print("Froze %d onsets" % len(self.allOnsets))
        except:
            print("Error updating")

    def freezeAllIsAccepted(self):
        """Freeze timeOnset field in Freezer
        """
        allDocs = self.freezer.processed.find(eval(self.queryStr))
        try:
            for isAccepted, doc in zip(
                    self.allQueryResults[self.idList[self.currTrialNum]]
                ['isAccepted'], allDocs):
                print isAccepted, doc['_id']
                self.freezer.processed.update(
                    {'_id': doc['_id']}, {'$set': {
                        'isAccepted': isAccepted
                    }})
            print("Froze %d isAccepted flags" % len(self.allIsAccepted))
        except:
            print("Error updating")

    def freezeAllQueryResults(self):
        """Freeze timeOnset field in Freezer
        """
        try:
            for id in self.idList:
                print id, {
                    'isAccepted': self.allQueryResults[id]['isAccepted']
                }
                self.freezer.processed.update({'_id': id}, {
                    '$set': {
                        'isAccepted': self.allQueryResults[id]['isAccepted'],
                        'timeOnset': int(self.allQueryResults[id]['timeOnset'])
                    }
                })
            print("Froze %d isAccepted flags" % len(self.idList))
        except:
            print("Error freezing")

    def createMainFrame(self):
        self.main_frame = QWidget()

        self.fig = Figure((5.0, 4.0), dpi=100)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.main_frame)
        self.canvas.setFocusPolicy(Qt.StrongFocus)
        self.canvas.setFocus()

        self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)

        ### Linking some events
        self.canvas.mpl_connect('key_press_event', self.onKey)
        self.canvas.mpl_connect('pick_event', self.onPick)
        self.canvas.mpl_connect('button_press_event', self.onMouseDown)
        self.canvas.mpl_connect('button_release_event', self.onMouseUp)
        self.canvas.mpl_connect('motion_notify_event', self.onMouseMotion)

        self.textbox = QTextEdit("""{"analystName": "zcwaxs"}
                                 """)
        self.textbox.selectAll()
        self.textbox.setMinimumWidth(200)

        self.queryButton = QPushButton("&Query")
        self.connect(self.queryButton, SIGNAL('clicked()'), self.onSubmitQuery)

        self.fwdButton = QPushButton("&>>")
        self.connect(self.fwdButton, SIGNAL('clicked()'), self.onFwd)

        self.bwdButton = QPushButton("&<<")
        self.connect(self.bwdButton, SIGNAL('clicked()'), self.onBwd)

        self.saveButton = QPushButton("&Save")
        self.connect(self.saveButton, SIGNAL('clicked()'), self.onSave)

        self.alignButton = QPushButton("&Close")
        self.connect(self.alignButton, SIGNAL('clicked()'), self.onFinish)

        self.grid_cb = QCheckBox("Show &Grid")
        self.grid_cb.setChecked(False)
        # self.connect(self.grid_cb, SIGNAL('stateChanged(int)'), self.onGrid)

        self.isAcceptedCB = QCheckBox("Accept?")
        self.isAcceptedCB.setChecked(False)
        self.connect(self.isAcceptedCB, SIGNAL('stateChanged(int)'),
                     self.onChangeIsAccepted)

        slider_label = QLabel('Bar width (%):')
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(1, 100)
        self.slider.setValue(20)
        self.slider.setTracking(True)
        self.slider.setTickPosition(QSlider.TicksBothSides)

        # self.connect(self.slider, SIGNAL('valueChanged(int)'), self.onSlider)

        #
        # Layout with box sizers
        #
        hbox = QHBoxLayout()

        for w in [
                self.textbox, self.queryButton, self.isAcceptedCB,
                self.bwdButton, self.fwdButton, self.saveButton,
                self.alignButton, self.grid_cb, slider_label, self.slider
        ]:
            hbox.addWidget(w)
            hbox.setAlignment(w, Qt.AlignVCenter)

        vbox = QVBoxLayout()
        vbox.addWidget(self.canvas)
        vbox.addWidget(self.mpl_toolbar)
        vbox.addLayout(hbox)

        self.main_frame.setLayout(vbox)
        self.setCentralWidget(self.main_frame)

    def drawCurrTrial(self):
        self.fig.clear()
        self.fig.hold(True)
        self.ax1 = self.fig.add_subplot(211)
        self.ax2 = self.fig.add_subplot(212)

        self.ax1.plot(self.currTrial['Left Elbow Flex / Time'])
        self.ax1.set_ylim([10, 130])
        self.ax2.plot(self.currTrial['Biceps'])
        self.ax2.set_ylim([-1.0, 1.0])

        ### Draw timeOnset lines
        self.onsetLine1 = self.ax1.axvline(x=self.currOnset(),
                                           ymin=0,
                                           ymax=100,
                                           color='b',
                                           linewidth=5)
        self.onsetLine2 = self.ax2.axvline(x=self.currOnset(),
                                           ymin=0,
                                           ymax=100,
                                           color='r',
                                           linewidth=5)

        self.canvas.draw()

    def currOnset(self):
        return self.allQueryResults[self.idList[
            self.currTrialNum]]['timeOnset']

    def setOnset(self):
        """Add the field 'onset' to all documents"""
        l = self.currTrial['Left Elbow Flex / Time'][0:800]
        base = sum(l) / float(len(l))
        th = base * 0.98
        f = lambda x: x <= th

        possible = indices(f, self.currTrial['Left Elbow Flex / Time'])
        tOnset = possible[0]
        self.allOnsets[self.currTrialNum] = tOnset
        self.allQueryResults[self.idList[
            self.currTrialNum]]['timeOnset'] = int(tOnset)


#        self.allAlignedTrials[self.currTrialNum] = self.currTrial.drop(xrange(self.currOnset - 100))

    def setPickedOnsetLine(self, artist):
        self.onsetLine1 = artist
        self.onsetLine1.set_color('g')

    def setCurrTrial(self, n=0):
        self.currTrialNum = n
        # print(len(self.allTrials))
        # self.currTrial = self.allTrials[self.currTrialNum]
        self.currTrial = self.allQueryResults[self.idList[n]]['trialData']
        # print(self.currTrialNum, len(self.currTrial))
        self.isAcceptedCB.setChecked(
            self.allQueryResults[self.idList[n]]['isAccepted'])
        self.setOnset()

    def setOnsetLine(self, new_x):
        xs, ys = self.onsetLine1.get_data()
        #new_xs = [min(rbound, max(lbound, new_x)) for xx in xs]
        self.onsetLine1.set_data(new_x, ys)
        self.onsetLine2.set_data(new_x, ys)
        self.allQueryResults[self.idList[
            self.currTrialNum]]['timeOnset'] = new_x
        self.canvas.draw()

    def onPick(self, event):
        self.setPickedOnsetLine(event.artist)
        self.canvas.draw()

    def onMouseDown(self, event):
        self.isDragging = True

    def onMouseUp(self, event):
        self.isDragging = False

    def onMouseMotion(self, event):
        if self.isDragging:
            self.setOnsetLine(event.xdata)

    def onKey(self, event):
        if event.key in '[':
            xs, ys = self.onsetLine1.get_data()
            new_xs = [xx - 20 for xx in xs]
            self.onsetLine1.set_data(new_xs, ys)
        elif event.key in ']':
            xs, ys = self.onsetLine1.get_data()
            new_xs = [xx + 20 for xx in xs]
            self.onsetLine1.set_data(new_xs, ys)
        elif event.key in '{':
            xs, ys = self.onsetLine1.get_data()
            new_xs = [xx - 100 for xx in xs]
            self.onsetLine1.set_data(new_xs, ys)
        elif event.key in '}':
            xs, ys = self.onsetLine1.get_data()
            new_xs = [xx + 100 for xx in xs]
            self.onsetLine1.set_data(new_xs, ys)
        self.canvas.draw()

    def onFwd(self):
        """Go forward 1 trial"""
        self.setCurrTrial(min(self.currTrialNum + 1, self.numTrials - 1))
        self.drawCurrTrial()
        # self.setOnset()
        # self.setOnsetLine()

    def onBwd(self):
        """Go backward 1 trial"""
        self.setCurrTrial(max(self.currTrialNum - 1, 0))
        self.drawCurrTrial()
        # self.setOnset()
        # self.setOnsetLine()

    def onChangeIsAccepted(self, value):
        self.allQueryResults[self.idList[self.currTrialNum]]['isAccepted'] = \
            True if value == 2 else False

    def onFinish(self):
        # self.freezeAllOnsets()
        self.freezeAllQueryResults()
        self.close()

    def onSave(self):
        # self.freezeAllOnsets()
        print self.currTrialNum
        print self.currOnset()
        tDataFrame = self.allQueryResults[self.idList[
            self.currTrialNum]]['trialData']
        tDataFrame = tDataFrame.drop(xrange(self.currOnset() - 1500))
        tDataFrame.to_csv(
            'D:\Code\local_timegrinder\ProcessedData\S2\FES_S02_L_FR_T%d.csv' %
            (self.currTrialNum + 1))

    def onSubmitQuery(self):
        self.queryData(str(self.textbox.toPlainText()))
        self.setCurrTrial()

        self.drawCurrTrial()
Exemple #4
0
class Grinder(QMainWindow):
    def __init__(self, metaData, parent=None):
        # Metadata into properties

        # self.analystName = metaData['analystName']
        self.analystName = metaData['analystName']
        self.expDate = metaData['expDate']
        self.expName = metaData['expName']
        self.rawData = metaData['rawData']
        self.patientName = metaData['patientName']
        self.sideTested = metaData['sideTested']
        self.movementType = metaData['movementType']
        self.uuidId = metaData['uuidId']
        # self.gammaDyn = gammaDyn
        # self.gammaSta = gammaSta

        # Some useful stuff
        self.allEndLines = []
        self.iBegins = []
        self.iEnds = []
        self.currEndLine = None
        self.currEndLineId = None
        self.baseChannel = 'Left Elbow Flex / Time'
        self.isDragging = False

        QMainWindow.__init__(self, parent)
        # self.showMaximized()
        self.createMainFrame()
        self.setNumTrials()

    def createMainFrame(self):
        self.main_frame = QWidget()

        self.fig = Figure((5.0, 4.0), dpi=100)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.main_frame)
        self.canvas.setFocusPolicy(Qt.StrongFocus)
        self.canvas.setFocus()

        self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)

        self.canvas.mpl_connect('key_press_event', self.onKey)
        self.canvas.mpl_connect('pick_event', self.onPick)
        self.canvas.mpl_connect('button_press_event', self.onMouseDown)
        self.canvas.mpl_connect('button_release_event', self.onMouseUp)
        self.canvas.mpl_connect('motion_notify_event', self.onMouseMotion)


        # Initial draw
        self.fig.clear()
        self.fig.hold(True)
        self.ax = self.fig.add_subplot(111)
        self.ax.plot(self.rawData[self.baseChannel])

        # Other GUI controls
        #
        self.numTrialBox = QSpinBox()
        self.numTrialBox.setMinimum(1)
        self.numTrialBox.setValue(1)
        self.numTrialBox.setMinimumWidth(200)
        self.connect(self.numTrialBox, SIGNAL('valueChanged(int)'), self.onNumTrialBox)

        self.submitButton = QPushButton("&Submit")
        self.connect(self.submitButton, SIGNAL('clicked()'), self.onSubmit)

        self.grid_cb = QCheckBox("Show &Grid")
        self.grid_cb.setChecked(False)
        self.connect(self.grid_cb, SIGNAL('stateChanged(int)'), self.onGrid)

        slider_label = QLabel('Bar width (%):')
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(1, 100)
        self.slider.setValue(20)
        self.slider.setTracking(True)
        self.slider.setTickPosition(QSlider.TicksBothSides)
        self.connect(self.slider, SIGNAL('valueChanged(int)'), self.onSlider)

        #
        # Layout with box sizers
        #
        hbox = QHBoxLayout()

        for w in [self.numTrialBox, self.submitButton, self.grid_cb,
                  slider_label, self.slider]:
            hbox.addWidget(w)
            hbox.setAlignment(w, Qt.AlignVCenter)

        vbox = QVBoxLayout()
        vbox.addWidget(self.canvas)
        vbox.addWidget(self.mpl_toolbar)
        vbox.addLayout(hbox)

        self.main_frame.setLayout(vbox)
        self.setCentralWidget(self.main_frame)

    def setEndLine(self, new_x):
        minLen = 50
        if self.currEndLineId > 0:
            leftx, lefty = self.allEndLines[self.currEndLineId - 1].get_data()
            lbound = leftx[0] + minLen
        else:
            lbound = minLen

        if self.currEndLineId < self.numTrials - 1:
            rightx, righty = self.allEndLines[self.currEndLineId + 1].get_data()
            rbound = rightx[0] - minLen
        else:
            rbound = len(self.rawData) - minLen

        xs, ys = self.currEndLine.get_data()
        new_xs = [min(rbound, max(lbound, new_x)) for xx in xs]
        self.currEndLine.set_data(new_xs, ys)
        self.canvas.draw()

    # IOC for all trials
    def setNumTrials(self, n=1):
        for eachLine in self.allEndLines:
            self.ax.lines.remove(eachLine)

        self.numTrials = n
        self.allEndLines = []

        maxL = 100
        initialIndex = 0  # was 100
        length = (self.rawData.shape[0] - initialIndex) / self.numTrials

        self.iBegins = [initialIndex + i * length for i in xrange(self.numTrials)]
        self.iEnds = [initialIndex + (i + 1) * length - 1 for i in xrange(self.numTrials)]

        for i in xrange(self.numTrials):
            self.allEndLines.append(self.ax.axvline(self.iEnds[i], 0, maxL, color='k', picker=10))

        self.beginLine = self.ax.axvline(0, 0, maxL, color='r', linewidth=5)

        # Select the first line by default
        self.setCurrEndLine(self.allEndLines[0])

        self.canvas.draw()

    def setAllTrials(self):
        self.iEnds = [int(l.get_data()[0][0]) for l in self.allEndLines]
        for i in xrange(self.numTrials - 1):
            self.iBegins[i + 1] = self.iEnds[i] + 1
        self.allTraces = [self.rawData[self.iBegins[i]: self.iEnds[i]].reset_index() for i in xrange(self.numTrials)]

    def freezeAllTrials(self):

        try:
            for eachTrial in self.allTraces:
                self.freezer.freezeTrialDict({
                    'expName': self.expName,
                    'expDate': self.expDate,
                    'trialUuid': self.uuidId,
                    'analystName': self.analystName,
                    'patientName': self.patientName,
                    'sideTested': self.sideTested,
                    'movementType': self.movementType}) 

        except:
            print("Error:", sys.exc_info()[0])
        finally:
            print("Attempted to freeze %d pieces of cadaver." % self.numTrials)

    def setFreezer(self, someFreezer):
        self.freezer = someFreezer

    def setCurrEndLine(self, artist):
        self.currEndLine = artist
        for i, line in enumerate(self.allEndLines):
            if line == self.currEndLine:
                self.currEndLineId = i
                line.set_color('r')
            else:
                line.set_color('k')

    def onMouseDown(self, event):
        self.isDragging = True

    def onMouseUp(self, event):
        self.isDragging = False

    def onMouseMotion(self, event):
        if self.isDragging:
            self.setEndLine(event.xdata)

    def onGrid(self):
        pass

    def onSlider(self):
        pass

    def onNumTrialBox(self, value):
        """Update how many trials the analyst sees
        """
        self.setNumTrials(value)

    def onSubmit(self):
        # Split trials into memory based on user input
        self.setAllTrials()

        # Save trials to Freezer (MongoDB database)
        self.freezeAllTrials()
        self.close()

    def onPick(self, event):
        self.setCurrEndLine(event.artist)
        self.canvas.draw()

    def onKey(self, event):
        if event.key in '[':
            xs, ys = self.currEndLine.get_data()
            new_xs = [xx - 20 for xx in xs]
            self.currEndLine.set_data(new_xs, ys)
        elif event.key in ']':
            xs, ys = self.currEndLine.get_data()
            new_xs = [xx + 20 for xx in xs]
            self.currEndLine.set_data(new_xs, ys)
        elif event.key in '{':
            xs, ys = self.currEndLine.get_data()
            new_xs = [xx - 100 for xx in xs]
            self.currEndLine.set_data(new_xs, ys)
        elif event.key in '}':
            xs, ys = self.currEndLine.get_data()
            new_xs = [xx + 100 for xx in xs]
            self.currEndLine.set_data(new_xs, ys)
        self.canvas.draw()
Exemple #5
0
class MatplotDisplay(gpi.GenericWidgetGroup):

    """Embeds the matplotlib figure window.
    """
    valueChanged = gpi.Signal()

    def __init__(self, title, parent=None):
        super(MatplotDisplay, self).__init__(title, parent)

        # gpi interface
        self._collapsables = []
        self._subplotSettings = {}
        #self._subplotPosition = {'right': 0.9, 'bottom': 0.12, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2, 'left': 0.125}
        self._subplotPosition = {'right': 0.913, 'bottom': 0.119, 'top': 0.912, 'wspace': 0.2, 'hspace': 0.2, 'left': 0.111}
        #self._subplot_keepers = ['yscale', 'xscale'] # linear, log
        self._subplot_keepers = []
        self._lineSettings = []
        self._line_keepers = ['linewidth', 'linestyle', 'label', 'marker', 'markeredgecolor', 'markerfacecolor', 'markersize', 'color', 'alpha']

        # since drawing is slow, don't do it as often, use the timer as a
        # debouncer
        self._on_draw_cnt = 0
        self._updatetimer = QtCore.QTimer()
        self._updatetimer.setSingleShot(True)
        self._updatetimer.timeout.connect(self._on_draw)
        self._updatetimer.setInterval(10)

        # plot specific UI side panel
        #  -sets options for plot window so this needs to be run first
        vbox = QtGui.QVBoxLayout()
        vbox.setContentsMargins(0, 0, 0, 0)  # no spaces around this item
        vbox.setSpacing(0)

        # AUTOSCALE
        self._autoscale_btn = gpi.widgets.BasicPushButton(self)
        self._autoscale_btn.set_toggle(True)
        self._autoscale_btn.set_button_title('autoscale')
        self._autoscale_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._autoscale_btn)

        # GRID
        self._grid_btn = gpi.widgets.BasicPushButton(self)
        self._grid_btn.set_toggle(True)
        self._grid_btn.set_button_title('grid')
        self._grid_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._grid_btn)

        # X/Y LIMITS
        lims = QtGui.QGridLayout()
        self._xl = gpi.widgets.BasicDoubleSpinBox(self)
        self._xh = gpi.widgets.BasicDoubleSpinBox(self)
        self._yl = gpi.widgets.BasicDoubleSpinBox(self)
        self._yh = gpi.widgets.BasicDoubleSpinBox(self)
        self._xl.valueChanged.connect(self.on_draw)
        self._xh.valueChanged.connect(self.on_draw)
        self._yl.valueChanged.connect(self.on_draw)
        self._yh.valueChanged.connect(self.on_draw)
        self._xl.set_immediate(True)
        self._xh.set_immediate(True)
        self._yl.set_immediate(True)
        self._yh.set_immediate(True)
        self._xl.set_label('max')
        self._xh.set_label('min')
        self._xl.set_decimals(7)
        self._xh.set_decimals(7)
        self._yl.set_decimals(7)
        self._yh.set_decimals(7)
        self._xlab = QtGui.QLabel('x limits')
        self._ylab = QtGui.QLabel('y limits')
        #self._maxlab = QtGui.QLabel('max')
        #self._minlab = QtGui.QLabel('min')
        #lims.addWidget(self._maxlab,1,0,1,1)
        #lims.addWidget(self._minlab,2,0,1,1)
        lims.addWidget(self._xlab,0,1,1,1,alignment=QtCore.Qt.AlignHCenter)
        lims.addWidget(self._xh,1,1,1,1,alignment=QtCore.Qt.AlignHCenter)
        lims.addWidget(self._xl,2,1,1,1,alignment=QtCore.Qt.AlignHCenter)
        lims.addWidget(self._ylab,0,2,1,1,alignment=QtCore.Qt.AlignHCenter)
        lims.addWidget(self._yh,1,2,1,1,alignment=QtCore.Qt.AlignHCenter)
        lims.addWidget(self._yl,2,2,1,1,alignment=QtCore.Qt.AlignHCenter)
        self._collapsables.append(self._xlab)
        self._collapsables.append(self._ylab)
        self._collapsables.append(self._xl)
        self._collapsables.append(self._xh)
        self._collapsables.append(self._yl)
        self._collapsables.append(self._yh)
        #self._collapsables.append(self._minlab)
        #self._collapsables.append(self._maxlab)

        # TICK MARKS
        ticks = QtGui.QGridLayout()
        self._x_numticks = gpi.widgets.BasicSpinBox(self)
        self._x_numticks.valueChanged.connect(self.on_draw)
        self._y_numticks = gpi.widgets.BasicSpinBox(self)
        self._y_numticks.valueChanged.connect(self.on_draw)
        self._x_ticks = QtGui.QLineEdit()
        self._y_ticks = QtGui.QLineEdit()
        self._x_ticks.textChanged.connect(lambda txt: self.check_validticks(self._x_ticks))
        self._y_ticks.textChanged.connect(lambda txt: self.check_validticks(self._y_ticks))
        self._x_ticks.setPlaceholderText('comma separated list of x labels')
        self._y_ticks.setPlaceholderText('comma separated list of y labels')
        self._x_ticks.returnPressed.connect(self.on_draw)
        self._y_ticks.returnPressed.connect(self.on_draw)
        self._x_numticks.set_immediate(True)
        self._y_numticks.set_immediate(True)
        self._x_numticks.set_min(2)
        self._y_numticks.set_min(2)
        self._x_numticks.set_max(100)
        self._y_numticks.set_max(100)
        self._x_numticks.set_val(5)
        self._y_numticks.set_val(5)
        self._x_numticks.set_label('x ticks')
        self._y_numticks.set_label('y ticks')
        ticks.addWidget(self._x_numticks, 0,0,1,1)
        ticks.addWidget(self._y_numticks, 1,0,1,1)
        ticks.addWidget(self._x_ticks, 0,1,1,1)
        ticks.addWidget(self._y_ticks, 1,1,1,1)
        self._collapsables.append(self._x_numticks)
        self._collapsables.append(self._y_numticks)
        self._collapsables.append(self._x_ticks)
        self._collapsables.append(self._y_ticks)

        # TITLE, XLABEL, YLABEL
        plotlabels = QtGui.QHBoxLayout()
        self._plot_title = QtGui.QLineEdit()
        self._plot_xlab = QtGui.QLineEdit()
        self._plot_ylab = QtGui.QLineEdit()
        self._plot_title.setPlaceholderText('title')
        self._plot_xlab.setPlaceholderText('x label')
        self._plot_ylab.setPlaceholderText('y label')
        self._plot_title.returnPressed.connect(self.on_draw)
        self._plot_xlab.returnPressed.connect(self.on_draw)
        self._plot_ylab.returnPressed.connect(self.on_draw)
        plotlabels.addWidget(self._plot_title)
        plotlabels.addWidget(self._plot_xlab)
        plotlabels.addWidget(self._plot_ylab)
        self._collapsables.append(self._plot_title)
        self._collapsables.append(self._plot_xlab)
        self._collapsables.append(self._plot_ylab)

        # XSCALE, YSCALE
        self._xscale_btn = gpi.widgets.BasicPushButton(self)
        self._xscale_btn.set_toggle(True)
        self._xscale_btn.set_button_title('log(x)')
        self._xscale_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._xscale_btn)
        self._yscale_btn = gpi.widgets.BasicPushButton(self)
        self._yscale_btn.set_toggle(True)
        self._yscale_btn.set_button_title('log(y)')
        self._yscale_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._yscale_btn)

        scale_options_layout = QtGui.QHBoxLayout()
        scale_options_layout.addWidget(self._xscale_btn)
        scale_options_layout.addWidget(self._yscale_btn)

        # LEGEND
        self._legend_btn = gpi.widgets.BasicPushButton(self)
        self._legend_btn.set_toggle(True)
        self._legend_btn.set_button_title('legend')
        self._legend_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._legend_btn)

        # HOLD
        self._hold_btn = gpi.widgets.BasicPushButton(self)
        self._hold_btn.set_toggle(True)
        self._hold_btn.set_button_title('hold')
        #self._hold_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._hold_btn)

        # MOVE AXES TO ORIGIN
        # self._origin_axes_btn = gpi.widgets.BasicPushButton(self)
        # self._origin_axes_btn.set_toggle(True)
        # self._origin_axes_btn.set_button_title("axes at (0,0)")
        # self._collapsables.append(self._origin_axes_btn)

        # RESET
        self._reset_btn = gpi.widgets.BasicPushButton(self)
        self._reset_btn.set_toggle(False)
        self._reset_btn.set_button_title('reset')
        self._reset_btn.valueChanged.connect(self._init_parms_)
        self._collapsables.append(self._reset_btn)

        # X=0, Y=0
        self._xeq0_btn = gpi.widgets.BasicPushButton(self)
        self._xeq0_btn.set_toggle(True)
        self._xeq0_btn.set_button_title('x=0')
        self._xeq0_btn.set_val(True)
        self._xeq0_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._xeq0_btn)
        self._yeq0_btn = gpi.widgets.BasicPushButton(self)
        self._yeq0_btn.set_toggle(True)
        self._yeq0_btn.set_button_title('y=0')
        self._yeq0_btn.set_val(True)
        self._yeq0_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._yeq0_btn)

        # LINE OPTIONS
        self._lino_btn = gpi.widgets.BasicPushButton(self)
        self._lino_btn.set_toggle(False)
        self._lino_btn.set_button_title('line options')
        self._lino_btn.valueChanged.connect(self.lineOptionsDialog)
        self._collapsables.append(self._lino_btn)

        # SUBPLOT SPACING OPTIONS
        self._subplotso_btn = gpi.widgets.BasicPushButton(self)
        self._subplotso_btn.set_toggle(False)
        self._subplotso_btn.set_button_title('spacing options')
        self._subplotso_btn.valueChanged.connect(self.subplotSpacingOptions)
        self._collapsables.append(self._subplotso_btn)
        self.adj_window = None

        plot_options_layout = QtGui.QHBoxLayout()
        plot_options_layout.addWidget(self._subplotso_btn)
        plot_options_layout.addWidget(self._lino_btn)

        grid_legend_lyt = QtGui.QHBoxLayout()
        grid_legend_lyt.addWidget(self._legend_btn)
        grid_legend_lyt.addWidget(self._grid_btn)

        autoscale_scale_lyt = QtGui.QHBoxLayout()
        autoscale_scale_lyt.addWidget(self._autoscale_btn)
        autoscale_scale_lyt.addWidget(self._xscale_btn)
        autoscale_scale_lyt.addWidget(self._yscale_btn)
        autoscale_scale_lyt.addWidget(self._xeq0_btn)
        autoscale_scale_lyt.addWidget(self._yeq0_btn)

        # HLINES
        self._hline1 = QtGui.QFrame()
        self._hline1.setFrameStyle(QtGui.QFrame.HLine | QtGui.QFrame.Sunken)
        self._hline1.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
        self._collapsables.append(self._hline1)

        self._hline2 = QtGui.QFrame()
        self._hline2.setFrameStyle(QtGui.QFrame.HLine | QtGui.QFrame.Sunken)
        self._hline2.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
        self._collapsables.append(self._hline2)

        self._hline3 = QtGui.QFrame()
        self._hline3.setFrameStyle(QtGui.QFrame.HLine | QtGui.QFrame.Sunken)
        self._hline3.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
        self._collapsables.append(self._hline3)

        spc = 10
        self._spacer1 = QtGui.QSpacerItem(1,spc,QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        self._spacer2 = QtGui.QSpacerItem(1,spc,QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        self._spacer3 = QtGui.QSpacerItem(1,spc,QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        self._spacer4 = QtGui.QSpacerItem(1,spc,QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        self._spacer5 = QtGui.QSpacerItem(1,spc,QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        self._spacer6 = QtGui.QSpacerItem(1,spc,QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        self._collapsables.append(self._spacer1)
        self._collapsables.append(self._spacer2)
        self._collapsables.append(self._spacer3)
        self._collapsables.append(self._spacer4)
        self._collapsables.append(self._spacer5)
        self._collapsables.append(self._spacer6)

        # panel layout
        vbox.addLayout(plotlabels)

        vbox.addSpacerItem(self._spacer1)
        vbox.addWidget(self._hline1)
        vbox.addSpacerItem(self._spacer2)

        vbox.addLayout(lims)
        #vbox.addLayout(scale_options_layout)
        #vbox.addWidget(self._autoscale_btn)
        vbox.addLayout(autoscale_scale_lyt)

        vbox.addSpacerItem(self._spacer3)
        vbox.addWidget(self._hline2)
        vbox.addSpacerItem(self._spacer4)

        vbox.addLayout(ticks)
        #vbox.addWidget(self._legend_btn)
        vbox.addLayout(grid_legend_lyt)
        vbox.addLayout(plot_options_layout)
        #vbox.addWidget(self._lino_btn)
        #vbox.addWidget(self._subplotso_btn)

        vbox.addSpacerItem(self._spacer5)
        vbox.addWidget(self._hline3)
        vbox.addSpacerItem(self._spacer6)

        vbox.addWidget(self._hold_btn)
        # vbox.addWidget(self._origin_axes_btn)

        vbox.insertStretch(-1,1)
        vbox.addWidget(self._reset_btn)

        # plot window
        self._data = None
        self._plotwindow = self.create_main_frame()

        # put side panel and plot window together
        hbox = QtGui.QHBoxLayout()
        hbox.addLayout(vbox)
        hbox.addLayout(self._plotwindow)
        hbox.setStretch(0,0)
        hbox.setStretch(1,11)
        self.setLayout(hbox)

        #self._on_draw() # draw once to get initial settings
        #self.copySubplotSettings()

        # Don't hide side-panel options by default
        self.set_collapsed(False)
        self.set_grid(True)
        self.set_autoscale(True)

        # DEFAULTS
        self._init_parms_()

    # setters
    def set_val(self, data):
        '''Takes a list of npy arrays.
        '''
        if isinstance(data, list):
            self._data = data
            self.on_draw()

    def set_grid(self, val):
        self._grid_btn.set_val(val)
        self.on_draw()

    def set_autoscale(self, val):
        self._autoscale_btn.set_val(val)
        self.on_draw()

    def set_collapsed(self, val):
        """bool | Only collapse the display options, not the Plot window.
        """
        self._isCollapsed = val
        for wdg in self._collapsables:
            if hasattr(wdg, 'setVisible'):
                wdg.setVisible(not val)

    def set_xlim(self, val, quiet=False):
        '''tuple of floats (min, max)
        '''
        self._xh.set_val(val[0])
        self._xl.set_val(val[1])
        if not quiet:
            self.on_draw()

    def set_ylim(self, val, quiet=False):
        '''tuple of floats (min, max)
        '''
        self._yh.set_val(val[0])
        self._yl.set_val(val[1])
        if not quiet:
            self.on_draw()

    def set_plotOptions(self, val):
        self._subplotSettings = val

    def set_lineOptions(self, val):
        self._lineSettings = val

    def set_plotPosition(self, val):
        self._subplotPosition = val

    def set_ticks(self, s):
        self._x_numticks.set_val(s['xticknum'])
        self._y_numticks.set_val(s['yticknum'])
        self._x_ticks.setText(s['xticks'])
        self._y_ticks.setText(s['yticks'])

    def set_plotlabels(self, s):
        self._plot_title.setText(s['title'])
        self._plot_xlab.setText(s['xlabel'])
        self._plot_ylab.setText(s['ylabel'])
        self.on_draw()

    def set_legend(self, val):
        self._legend_btn.set_val(val)
        self.on_draw()

    def set_xline(self, val):
        self._yeq0_btn.set_val(val)
        self.on_draw()

    def set_yline(self, val):
        self._xeq0_btn.set_val(val)
        self.on_draw()

    def set_scale(self, val):
        self._xscale_btn.set_val(val['xscale'])
        self._yscale_btn.set_val(val['yscale'])
        self.on_draw()

    # getters
    def get_val(self):
        return self._data

    def get_grid(self):
        return self._grid_btn.get_val()

    def get_autoscale(self):
        return self._autoscale_btn.get_val()

    def get_xlim(self):
        return (self._xh.get_val(), self._xl.get_val())

    def get_ylim(self):
        return (self._yh.get_val(), self._yl.get_val())

    def get_plotOptions(self):
        return self._subplotSettings

    def get_lineOptions(self):
        return self._lineSettings

    def get_plotPosition(self):
        return self._subplotPosition

    def get_ticks(self):
        s = {}
        s['xticknum'] = self._x_numticks.get_val()
        s['yticknum'] = self._y_numticks.get_val()
        s['xticks'] = str(self._x_ticks.text())
        s['yticks'] = str(self._y_ticks.text())
        return s

    def get_plotlabels(self):
        s = {}
        s['title'] = str(self._plot_title.text())
        s['xlabel'] = str(self._plot_xlab.text())
        s['ylabel'] = str(self._plot_ylab.text())
        return s

    def get_legend(self):
        return self._legend_btn.get_val()

    def get_xline(self):
        return self._yeq0_btn.get_val()

    def get_yline(self):
        return self._xeq0_btn.get_val()

    def get_scale(self):
        s = {}
        s['xscale'] = self._xscale_btn.get_val()
        s['yscale'] = self._yscale_btn.get_val()
        return s

    # support
    def check_validticks(self, tickwdg):
        s = tickwdg.text()
        comma_cnt = s.count(',')
        if (comma_cnt > 0) or (len(s) == 0):
            color = '#ffffff' # white
            tickwdg.setStyleSheet('QLineEdit { background-color: %s }' % color)
            return

        #color = '#fff79a' # yellow
        color = '#f6989d' # red
        tickwdg.setStyleSheet('QLineEdit { background-color: %s }' % color)
        return

    def create_main_frame(self):
        self.fig = Figure((6.0, 4.8), dpi=100, facecolor='0.98', linewidth=6.0, edgecolor='0.93')
        self.axes = None
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self)
        self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.canvas.setFocus()

        self.canvas.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.MinimumExpanding)

        #self.mpl_toolbar = NavigationToolbar(self.canvas, self)
        self.mpl_toolbar = NavbarTools(self.canvas, self)
        self.mpl_toolbar.actionTriggered.connect(self.copySubplotSettings)

        self.canvas.mpl_connect('key_press_event', self.on_key_press)

        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(self.canvas)  # the matplotlib canvas
        vbox.addWidget(self.mpl_toolbar)
        return vbox
        #self.setLayout(vbox)

    def lineOptionsDialog(self):
        if self.axes is None:
            print("Matplotlib: no lines to modify, skipping line editor")
            return
        figure_edit(self.axes, self)
        self.copySubplotSettings()
        self.on_draw()

    def subplotSpacingOptions(self):
        if self.fig is None:
            return

        # don't allow the user to open extra windows
        if self.adj_window is not None:
            if self.adj_window.isActive():
                self.adj_window.raise_()
                return

        self.adj_window = MainWin_close()
        self.adj_window.window_closed.connect(self.copySubplotSettings)
        win = self.adj_window

        win.setWindowTitle("Subplot Configuration Tool")
        image = os.path.join( matplotlib.rcParams['datapath'],'images','matplotlib.png' )
        win.setWindowIcon(QtGui.QIcon( image ))

        tool = SubplotToolQt(self.fig, win)
        win.setCentralWidget(tool)
        win.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)

        win.show()

    def copySubplotSettings(self):
        '''Get a copy of the settings found in the 'Figure Options' editor.
        '''
        if self.axes is None:
            return

        # subplot settings
        for k in self._subplot_keepers:
            self._subplotSettings[k] = getattr(self.axes, 'get_'+k)()

        # line settings
        self._lineSettings = []
        for l in self.axes.get_lines():
            s = {}
            for k in self._line_keepers:
                s[k] = getattr(l, 'get_'+k)()
            self._lineSettings.append(s)

        # subplot position 
        self._subplotPosition = {}
        self._subplotPosition['left'] = self.fig.subplotpars.left
        self._subplotPosition['right'] = self.fig.subplotpars.right
        self._subplotPosition['top'] = self.fig.subplotpars.top
        self._subplotPosition['bottom'] = self.fig.subplotpars.bottom
        self._subplotPosition['wspace'] = self.fig.subplotpars.wspace
        self._subplotPosition['hspace'] = self.fig.subplotpars.hspace

    def applySubplotSettings(self):
        '''Everytime the plot is drawn it looses its 'Figure Options' so just
        make sure they are applied again.
        '''
        # subplot settings
        for k in self._subplot_keepers:
            if k in self._subplotSettings:
                getattr(self.axes, 'set_'+k)(self._subplotSettings[k])

        #subplot position
        self.fig.subplots_adjust(**self._subplotPosition)

    def _init_parms_(self):
        '''Default parameter settings
        '''
        self._subplotSettings = {}
        self._subplotPosition = {'right': 0.913, 'bottom': 0.119, 'top': 0.912, 'wspace': 0.2, 'hspace': 0.2, 'left': 0.111}
        self._lineSettings = []
        self.set_autoscale(True)
        self.set_grid(True)
        s = {}
        s['xticknum'] = 5
        s['yticknum'] = 5
        s['xticks'] = ''
        s['yticks'] = ''
        self.set_ticks(s)
        s = {}
        s['title'] = ''
        s['xlabel'] = ''
        s['ylabel'] = ''
        self.set_plotlabels(s)
        self.set_legend(False)
        s = {}
        s['xscale'] = False # linear
        s['yscale'] = False
        self.set_scale(s)
        self.on_draw()

    def on_draw(self):
        self._on_draw_cnt += 1
        if not self._updatetimer.isActive():
            self._updatetimer.start()

    def _on_draw(self):

        # HOLD / Create New AXES
        if not self._hold_btn.get_val():
            self.fig.clear()
            self.axes = self.fig.add_subplot(111)

        # AUTOSCALE and LIMITS
        self.axes.set_autoscale_on(self.get_autoscale())
        if not self.get_autoscale():
            self.axes.set_xlim(self.get_xlim())
            self.axes.set_ylim(self.get_ylim())

        # TITLE, XLABEL and YLABEL
        self.axes.set_title(self.get_plotlabels()['title'], fontweight='bold', fontsize=16)
        self.axes.set_xlabel(self.get_plotlabels()['xlabel'], fontsize=14)
        self.axes.set_ylabel(self.get_plotlabels()['ylabel'], fontsize=14)

        # self.axes.plot(self.x, self.y, 'ro')
        # self.axes.imshow(self.data, interpolation='nearest')
        # self.axes.plot([1,2,3])
    
        # XSCALE
        if self.get_scale()['xscale']:
            self.axes.set_xscale('log')
        else:
            self.axes.set_xscale('linear')

        # YSCALE
        if self.get_scale()['yscale']:
            self.axes.set_yscale('log')
        else:
            self.axes.set_yscale('linear')

        # GRID
        ax_color = '0.5'
        if self.get_grid():
            self.axes.grid(self.get_grid(), color=ax_color)
        else:
            self.axes.grid(self.get_grid())

        # AXES SPINE COLOR
        self.axes.spines['bottom'].set_color(ax_color)
        self.axes.spines['top'].set_color(ax_color) 
        self.axes.spines['right'].set_color(ax_color)
        self.axes.spines['left'].set_color(ax_color)
        self.axes.set_axis_bgcolor('0.97')

        # if self._origin_axes_btn.get_val():
        #     self.axes.spines['left'].set_position('zero')
        #     self.axes.spines['bottom'].set_position('zero')
        #     self.axes.spines['left'].set_smart_bounds(True)
        #     self.axes.spines['bottom'].set_smart_bounds(True)
        #     self.axes.xaxis.set_ticks_position('bottom')
        #     self.axes.yaxis.set_ticks_position('left')

        if self._data is None:
            return

        self.fig.hold(True)

        # plot each set
        # print "--------------------plot the data"
        for data in self._data:
            ln = max(data.shape)
            lw = max(5.0-np.log10(ln), 1.0)
            if ln > 0:
                al = max(1.0-1.0/np.log2(ln), 0.75)
            else:
                al = 0

            if data.shape[-1] == 2:
                self.axes.plot(data[..., 0], data[..., 1], alpha=al, lw=lw)
            else:
                self.axes.plot(data, alpha=al, lw=lw)

        # X=0, Y=0
        if self.get_xline():
            self.axes.axhline(y=0, color='k', zorder=-1, label="y=0")
        if self.get_yline():
            self.axes.axvline(x=0, color='k', zorder=-1, label="x=0")

        # LEGEND
        if self.get_legend():
            handles, labels = self.axes.get_legend_handles_labels()
            self.axes.legend(handles, labels)

        # AUTOSCALE
        if self.get_autoscale():
            self.set_xlim(self.axes.get_xlim(), quiet=True)
            self.set_ylim(self.axes.get_ylim(), quiet=True)

        # X TICKS
        xl = self._x_ticks.text().split(',')
        if len(xl) > 1:
            self.axes.set_xticks(np.linspace(*self.axes.get_xlim(), num=len(xl)))
            self.axes.set_xticklabels(xl)
        else:
            self.axes.set_xticks(np.linspace(*self.axes.get_xlim(), num=self._x_numticks.get_val()))

        # Y TICKS
        yl = self._y_ticks.text().split(',')
        if len(yl) > 1:
            self.axes.set_yticks(np.linspace(*self.axes.get_ylim(), num=len(yl)))
            self.axes.set_yticklabels(yl)
        else:
            self.axes.set_yticks(np.linspace(*self.axes.get_ylim(), num=self._y_numticks.get_val()))

        self.applySubplotSettings()

        self.canvas.draw()

        #print 'draw count: ', self._on_draw_cnt
        self._on_draw_cnt = 0

    def on_key_press(self, event):
        # print 'Matplotlib-> you pressed:' + str(event.key)
        # implement the default mpl key press events described at
        # http://matplotlib.org/users/navigation_toolbar.html#navigation-
        # keyboard-shortcuts
        try:
            from matplotlib.backend_bases import key_press_handler
            key_press_handler(event, self.canvas, self.mpl_toolbar)
        except:
            print("key_press_handler import failed. -old matplotlib version.")
class MatplotDisplay2(gpi.GenericWidgetGroup):
    valueChanged = gpi.Signal()

    def __init__(self, title, parent=None):
        super(MatplotDisplay2, self).__init__(title, parent)

        #self.data = self.get_data2()
        self._data = None
        self.create_main_frame()
        self.on_draw()

    # setters
    def set_val(self, data):
        '''Takes a list of npy arrays.
        '''
        if isinstance(data, list):
            self._data = data
            self.on_draw()
        else:
            return

    # getters
    def get_val(self):
        return self._data

    # support
    def create_main_frame(self):

        self.fig = Figure((5.0, 4.0), dpi=100)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self)
        self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.canvas.setFocus()

        self.mpl_toolbar = NavigationToolbar(self.canvas, self)

        self.canvas.mpl_connect('key_press_event', self.on_key_press)

        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(self.canvas)  # the matplotlib canvas
        vbox.addWidget(self.mpl_toolbar)
        self.setLayout(vbox)

    def get_data2(self):
        return np.arange(20).reshape([4, 5]).copy()

    def on_draw(self):
        self.fig.clear()
        self.axes = self.fig.add_subplot(111)
        # self.axes.plot(self.x, self.y, 'ro')
        # self.axes.imshow(self.data, interpolation='nearest')
        # self.axes.plot([1,2,3])

        if self._data is None:
            return

        self.fig.hold(True)

        # plot each set
        # print "--------------------plot the data"
        for data in self._data:

            # check for x, y data
            if data.shape[-1] == 2:
                self.axes.plot(data[..., 0], data[..., 1], alpha=0.8, lw=2.0)
            else:
                self.axes.plot(data, alpha=0.8, lw=2.0)

        self.canvas.draw()

    def on_key_press(self, event):
        # print 'Matplotlib-> you pressed:' + str(event.key)
        # implement the default mpl key press events described at
        # http://matplotlib.org/users/navigation_toolbar.html#navigation-
        # keyboard-shortcuts
        try:
            from matplotlib.backend_bases import key_press_handler
            key_press_handler(event, self.canvas, self.mpl_toolbar)
        except:
            print("key_press_handler import failed. -old matplotlib version.")
Exemple #7
0
class Grinder(QMainWindow):
    def __init__(self, metaData, parent=None):
        # Metadata into properties

        # self.analystName = metaData['analystName']
        self.analystName = metaData['analystName']
        self.expDate = metaData['expDate']
        self.expName = metaData['expName']
        self.rawData = metaData['rawData']
        self.patientName = metaData['patientName']
        self.sideTested = metaData['sideTested']
        self.movementType = metaData['movementType']
        # self.gammaDyn = gammaDyn
        # self.gammaSta = gammaSta

        # Some useful stuff
        self.allEndLines = []
        self.iBegins = []
        self.iEnds = []
        self.currEndLine = None
        self.currEndLineId = None
        self.baseChannel = 'Left Shoulder Flex / Time'
        self.isDragging = False

        QMainWindow.__init__(self, parent)
        # self.showMaximized()
        self.createMainFrame()
        self.setNumTrials()

    def createMainFrame(self):
        self.main_frame = QWidget()

        self.fig = Figure((5.0, 4.0), dpi=100)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.main_frame)
        self.canvas.setFocusPolicy(Qt.StrongFocus)
        self.canvas.setFocus()

        self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)

        self.canvas.mpl_connect('key_press_event', self.onKey)
        self.canvas.mpl_connect('pick_event', self.onPick)
        self.canvas.mpl_connect('button_press_event', self.onMouseDown)
        self.canvas.mpl_connect('button_release_event', self.onMouseUp)
        self.canvas.mpl_connect('motion_notify_event', self.onMouseMotion)

        # Initial draw
        self.fig.clear()
        self.fig.hold(True)
        self.ax = self.fig.add_subplot(111)
        self.ax.plot(self.rawData[self.baseChannel])

        # Other GUI controls
        #
        self.numTrialBox = QSpinBox()
        self.numTrialBox.setMinimum(1)
        self.numTrialBox.setValue(2)
        self.numTrialBox.setMinimumWidth(200)
        self.connect(self.numTrialBox, SIGNAL('valueChanged(int)'),
                     self.onNumTrialBox)

        self.submitButton = QPushButton("&Submit")
        self.connect(self.submitButton, SIGNAL('clicked()'), self.onSubmit)

        self.grid_cb = QCheckBox("Show &Grid")
        self.grid_cb.setChecked(False)
        self.connect(self.grid_cb, SIGNAL('stateChanged(int)'), self.onGrid)

        slider_label = QLabel('Bar width (%):')
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(1, 100)
        self.slider.setValue(20)
        self.slider.setTracking(True)
        self.slider.setTickPosition(QSlider.TicksBothSides)
        self.connect(self.slider, SIGNAL('valueChanged(int)'), self.onSlider)

        #
        # Layout with box sizers
        #
        hbox = QHBoxLayout()

        for w in [
                self.numTrialBox, self.submitButton, self.grid_cb,
                slider_label, self.slider
        ]:
            hbox.addWidget(w)
            hbox.setAlignment(w, Qt.AlignVCenter)

        vbox = QVBoxLayout()
        vbox.addWidget(self.canvas)
        vbox.addWidget(self.mpl_toolbar)
        vbox.addLayout(hbox)

        self.main_frame.setLayout(vbox)
        self.setCentralWidget(self.main_frame)

    def setEndLine(self, new_x):
        minLen = 50
        if self.currEndLineId > 0:
            leftx, lefty = self.allEndLines[self.currEndLineId - 1].get_data()
            lbound = leftx[0] + minLen
        else:
            lbound = minLen

        if self.currEndLineId < self.numTrials - 1:
            rightx, righty = self.allEndLines[self.currEndLineId +
                                              1].get_data()
            rbound = rightx[0] - minLen
        else:
            rbound = len(self.rawData) - minLen

        xs, ys = self.currEndLine.get_data()
        new_xs = [min(rbound, max(lbound, new_x)) for xx in xs]
        self.currEndLine.set_data(new_xs, ys)
        self.canvas.draw()

    # IOC for all trials
    def setNumTrials(self, n=1):
        for eachLine in self.allEndLines:
            self.ax.lines.remove(eachLine)

        self.numTrials = n
        self.allEndLines = []

        maxL = 100
        initialIndex = 0  # was 100
        length = (self.rawData.shape[0] - initialIndex) / self.numTrials

        self.iBegins = [
            initialIndex + i * length for i in xrange(self.numTrials)
        ]
        self.iEnds = [
            initialIndex + (i + 1) * length - 1 for i in xrange(self.numTrials)
        ]

        for i in xrange(self.numTrials):
            self.allEndLines.append(
                self.ax.axvline(self.iEnds[i], 0, maxL, color='k', picker=10))

        self.beginLine = self.ax.axvline(0, 0, maxL, color='r', linewidth=5)

        # Select the first line by default
        self.setCurrEndLine(self.allEndLines[0])

        self.canvas.draw()

    def setAllTrials(self):
        self.iEnds = [int(l.get_data()[0][0]) for l in self.allEndLines]
        for i in xrange(self.numTrials - 1):
            self.iBegins[i + 1] = self.iEnds[i] + 1
        self.allTraces = [
            self.rawData[self.iBegins[i]:self.iEnds[i]].reset_index()
            for i in xrange(self.numTrials)
        ]

    def freezeAllTrials(self):
        try:
            for eachTrial in self.allTraces:
                self.freezer.freezeTrialDict({
                    'expName': self.expName,
                    'expDate': self.expDate,
                    'trialData': eachTrial,
                    'analystName': self.analystName,
                    'patientName': self.patientName,
                    'sideTested': self.sideTested,
                    'movementType': self.movementType
                })
        except:
            print("Error when writing to database")
        finally:
            print("Successfully froze %d pieces of cadaver." % self.numTrials)

    def setFreezer(self, someFreezer):
        self.freezer = someFreezer

    def setCurrEndLine(self, artist):
        self.currEndLine = artist
        for i, line in enumerate(self.allEndLines):
            if line == self.currEndLine:
                self.currEndLineId = i
                line.set_color('r')
            else:
                line.set_color('k')

    def onMouseDown(self, event):
        self.isDragging = True

    def onMouseUp(self, event):
        self.isDragging = False

    def onMouseMotion(self, event):
        if self.isDragging:
            self.setEndLine(event.xdata)

    def onGrid(self):
        pass

    def onSlider(self):
        pass

    def onNumTrialBox(self, value):
        """Update how many trials the analyst sees
        """
        self.setNumTrials(value)

    def onSubmit(self):
        # Split trials into memory based on user input
        self.setAllTrials()

        # Save trials to Freezer (MongoDB database)
        self.freezeAllTrials()
        self.close()

    def onPick(self, event):
        self.setCurrEndLine(event.artist)
        self.canvas.draw()

    def onKey(self, event):
        if event.key in '[':
            xs, ys = self.currEndLine.get_data()
            new_xs = [xx - 20 for xx in xs]
            self.currEndLine.set_data(new_xs, ys)
        elif event.key in ']':
            xs, ys = self.currEndLine.get_data()
            new_xs = [xx + 20 for xx in xs]
            self.currEndLine.set_data(new_xs, ys)
        elif event.key in '{':
            xs, ys = self.currEndLine.get_data()
            new_xs = [xx - 100 for xx in xs]
            self.currEndLine.set_data(new_xs, ys)
        elif event.key in '}':
            xs, ys = self.currEndLine.get_data()
            new_xs = [xx + 100 for xx in xs]
            self.currEndLine.set_data(new_xs, ys)
        self.canvas.draw()
Exemple #8
0
def makeplot(plotrec, results, variables, parent = None):
    """
    Given a plot record from a spec sheet and a full set of results, generate
    a plot.  The name of the plot file and the vectors to plot, labels, legends,
    and so forth are all contained in the 'plotrec' dictionary.
    """

    binrex = re.compile(r'([0-9]*)\'([bodh])', re.IGNORECASE)
    # Organize data into plot lines according to formatting

    if 'type' in plotrec:
        plottype = plotrec['type']
    else:
        plottype = 'xyplot'

    # Find index of X data in results
    if plottype == 'histogram':
        xname = 'RESULT'
    else:
        xname = plotrec['xaxis']
    rlen = len(results[0])
    try:
        xidx = next(r for r in range(rlen) if results[0][r] == xname)
    except StopIteration:
        return None
                            
    # Find unique values of each variable (except results, traces, and iterations)
    steps = [[0]]
    traces = [0]
    bmatch = binrex.match(results[1][0])
    if bmatch:
        digits = bmatch.group(1)
        if digits == '':
            digits = len(results[2][0])
        else:
            digits = int(digits)
        cbase = bmatch.group(2)
        if cbase == 'b':
            base = 2
        elif cbase == 'o':
            base = 8
        elif cbase == 'd':
            base = 10
        else:
            base = 16
        binconv = [[base, digits]]
    else:
        binconv = [[]]

    for i in range(1, rlen):
        lsteps = []

        # results labeled 'ITERATIONS', 'RESULT', 'TRACE', or 'TIME' are treated as plot vectors
        isvector = False
        if results[0][i] == 'ITERATIONS':
            isvector = True
        elif results[0][i] == 'RESULT':
            isvector = True
        elif results[0][i] == 'TIME':
            isvector = True
        elif results[0][i].split(':')[0] == 'TRACE':
            isvector = True

        # results whose labels are in the 'variables' list are treated as plot vectors
        if isvector == False:
            if variables:
                try:
                    varrec = next(item for item in variables if item['condition'] == results[0][i])
                except StopIteration:
                    pass
                else:
                    isvector = True

        # those results that are not traces are stepped conditions (unless they are constant)
        if isvector == False:
            try:
                for item in list(a[i] for a in results[2:]):
                    if item not in lsteps:
                        lsteps.append(item)
            except IndexError:
                # Diagnostic
                print("Error: Failed to find " + str(i) + " items in result set")
                print("Results set has " + len(results[0]) + " entries")
                print(str(results[0]))
                for x in range(2, len(results)):
                    if len(results[x]) <= i:
                        print("Failed at entry " + str(x))
                        print(str(results[x]))
                        break

        # 'ITERATIONS' and 'TIME' are the x-axis variable, so don't add them to traces
        # (but maybe just check that xaxis name is not made into a trace?)
        elif results[0][i] != 'ITERATIONS' and results[0][i] != 'TIME':
            traces.append(i)
        steps.append(lsteps)

        # Mark which items need converting from digital.  Format is verilog-like.  Use
        # a format width that is larger than the actual number of digits to force
        # unsigned conversion.
        bmatch = binrex.match(results[1][i])
        if bmatch:
            digits = bmatch.group(1)
            if digits == '':
                digits = len(results[2][i])
            else:
                digits = int(digits)
            cbase = bmatch.group(2)
            if cbase == 'b':
                base = 2
            elif cbase == 'o':
                base = 8
            elif cbase == 'd':
                base = 10
            else:
                base = 16
            binconv.append([base, digits])
        else:
            binconv.append([])
        
    # Support older method of declaring a digital vector
    if xname.split(':')[0] == 'DIGITAL':
        binconv[xidx] = [2, len(results[2][0])]

    # Which stepped variables (ignoring X axis variable) have more than one value?
    watchsteps = list(i for i in range(1, rlen) if len(steps[i]) > 1 and i != xidx)

    # Diagnostic
    # print("Stepped conditions are: ")
    # for j in watchsteps:
    #      print(results[0][j] + '  (' + str(len(steps[j])) + ' steps)')

    # Collect results.  Make a separate record for each unique set of stepped conditions
    # encountered.  Record has (X, Y) vector and a list of conditions.
    pdata = {}
    for item in results[2:]:
        if xname.split(':')[0] == 'DIGITAL' or binconv[xidx] != []:
            base = binconv[xidx][0]
            digits = binconv[xidx][1]
            # Recast binary strings as integers
            # Watch for strings that have been cast to floats (need to find the source of this)
            if '.' in item[xidx]:
                item[xidx] = item[xidx].split('.')[0]
            a = int(item[xidx], base)
            b = twos_comp(a, digits)
            xvalue = b
        else:
            xvalue = item[xidx]

        slist = []
        for j in watchsteps:
             slist.append(item[j])
        istr = ','.join(slist)
        if istr not in pdata:
            stextlist = []
            for j in watchsteps:
                if results[1][j] == '':
                    stextlist.append(results[0][j] + '=' + item[j])
                else:
                    stextlist.append(results[0][j] + '=' + item[j] + ' ' + results[1][j])
            pdict = {}
            pdata[istr] = pdict
            pdict['xdata'] = []
            if stextlist:
                tracelegnd = False
            else:
                tracelegnd = True

            for i in traces:
                aname = 'ydata' + str(i)
                pdict[aname] = []
                alabel = 'ylabel' + str(i)
                tracename = results[0][i]
                if ':' in tracename:
                    tracename = tracename.split(':')[1]

                if results[1][i] != '' and not binrex.match(results[1][i]):
                    tracename += ' (' + results[1][i] + ')'

                pdict[alabel] = tracename

            pdict['sdata'] = ' '.join(stextlist)
        else:
            pdict = pdata[istr]
        pdict['xdata'].append(xvalue)

        for i in traces:
            # For each trace, convert the value from digital to integer if needed
            if binconv[i] != []:
                base = binconv[i][0]
                digits = binconv[i][1]
                a = int(item[i], base)
                b = twos_comp(a, digits)
                yvalue = b
            else:
                yvalue = item[i]

            aname = 'ydata' + str(i)
            pdict[aname].append(yvalue)

    fig = Figure()
    if parent == None:
        canvas = FigureCanvasAgg(fig)
    else:
        canvas = FigureCanvasTkAgg(fig, parent)

    # With no parent, just make one plot and put the legend off to the side.  The
    # 'extra artists' capability of print_figure will take care of the bounding box.
    # For display, prepare two subplots so that the legend takes up the space of the
    # second one.
    if parent == None:
        ax = fig.add_subplot(111)
    else:
        ax = fig.add_subplot(121)

    fig.hold(True)
    for record in pdata:
        pdict = pdata[record]

        # Check if xdata is numeric
        try:
            test = float(pdict['xdata'][0])
        except ValueError:
            numeric = False
            xdata = [i for i in range(len(pdict['xdata']))]
        else:
            numeric = True
            xdata = list(map(float,pdict['xdata']))

        if plottype == 'histogram':
            ax.hist(xdata, histtype='barstacked', label=pdict['sdata'], stacked=True)
        else:
            for i in traces:
                aname = 'ydata' + str(i)
                alabl = 'ylabel' + str(i)
                ax.plot(xdata, pdict[aname], label=pdict[alabl] + ' ' + pdict['sdata'])
                # Diagnostic
                # print("Y values for " + aname + ": " + str(pdict[aname]))

        if not numeric:
            ax.set_xticks(xdata)
            ax.set_xticklabels(pdict['xdata'])

    if 'xlabel' in plotrec:
        if results[1][xidx] == '' or binrex.match(results[1][xidx]):
            ax.set_xlabel(plotrec['xlabel'])
        else:
            ax.set_xlabel(plotrec['xlabel'] + ' (' + results[1][xidx] + ')')
    else:
        # Automatically generate X axis label if not given alternate text
        xtext = results[0][xidx]
        if results[1][xidx] != '':
            xtext += ' (' + results[1][xidx] + ')'
        ax.set_xlabel(xtext)

    if 'ylabel' in plotrec:
        if results[1][0] == '' or binrex.match(results[1][0]):
            ax.set_ylabel(plotrec['ylabel'])
        else:
            ax.set_ylabel(plotrec['ylabel'] + ' (' + results[1][0] + ')')
    else:
        # Automatically generate Y axis label if not given alternate text
        ytext = results[0][0]
        if results[1][0] != '' or binrex.match(results[1][0]):
            ytext += ' (' + results[1][0] + ')'
        ax.set_ylabel(ytext)

    ax.grid(True)
    if watchsteps or tracelegnd:
        legnd = ax.legend(loc = 2, bbox_to_anchor = (1.05, 1), borderaxespad=0.)
    else:
        legnd = None

    if legnd:
        legnd.draggable()

    if parent == None:
        if not os.path.exists('simulation_files'):
            os.makedirs('simulation_files')

        filename = 'simulation_files/' + plotrec['filename']
        # NOTE: print_figure only makes use of bbox_extra_artists if
        # bbox_inches is set to 'tight'.  This forces a two-pass method
        # that calculates the real maximum bounds of the figure.  Otherwise
        # the legend gets clipped.
        if legnd:
            canvas.print_figure(filename, bbox_inches = 'tight',
                        bbox_extra_artists = [legnd])
        else:
            canvas.print_figure(filename, bbox_inches = 'tight')

    return canvas
Exemple #9
0
class MatplotDisplay(gpi.GenericWidgetGroup):

    """Embeds the matplotlib figure window.
    """
    valueChanged = gpi.Signal()

    def __init__(self, title, parent=None):
        super().__init__(title, parent)

        # gpi interface
        self._collapsables = []
        self._subplotSettings = {}
        #self._subplotPosition = {'right': 0.9, 'bottom': 0.12, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2, 'left': 0.125}
        self._subplotPosition = {'right': 0.913, 'bottom': 0.119, 'top': 0.912, 'wspace': 0.2, 'hspace': 0.2, 'left': 0.111}
        #self._subplot_keepers = ['yscale', 'xscale'] # linear, log
        self._subplot_keepers = []
        self._lineSettings = []
        self._line_keepers = ['linewidth', 'linestyle', 'label', 'marker', 'markeredgecolor', 'markerfacecolor', 'markersize', 'color', 'alpha']

        # since drawing is slow, don't do it as often, use the timer as a
        # debouncer
        self._on_draw_cnt = 0
        self._updatetimer = QtCore.QTimer()
        self._updatetimer.setSingleShot(True)
        self._updatetimer.timeout.connect(self._on_draw)
        self._updatetimer.setInterval(10)

        # plot specific UI side panel
        #  -sets options for plot window so this needs to be run first
        vbox = QtWidgets.QVBoxLayout()
        vbox.setContentsMargins(0, 0, 0, 0)  # no spaces around this item
        vbox.setSpacing(0)

        # AUTOSCALE
        self._autoscale_btn = gpi.widgets.BasicPushButton(self)
        self._autoscale_btn.set_toggle(True)
        self._autoscale_btn.set_button_title('autoscale')
        self._autoscale_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._autoscale_btn)

        # GRID
        self._grid_btn = gpi.widgets.BasicPushButton(self)
        self._grid_btn.set_toggle(True)
        self._grid_btn.set_button_title('grid')
        self._grid_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._grid_btn)

        # X/Y LIMITS
        lims = QtWidgets.QGridLayout()
        self._xl = gpi.widgets.BasicDoubleSpinBox(self)
        self._xh = gpi.widgets.BasicDoubleSpinBox(self)
        self._yl = gpi.widgets.BasicDoubleSpinBox(self)
        self._yh = gpi.widgets.BasicDoubleSpinBox(self)
        self._xl.valueChanged.connect(self.on_draw)
        self._xh.valueChanged.connect(self.on_draw)
        self._yl.valueChanged.connect(self.on_draw)
        self._yh.valueChanged.connect(self.on_draw)
        self._xl.set_immediate(True)
        self._xh.set_immediate(True)
        self._yl.set_immediate(True)
        self._yh.set_immediate(True)
        self._xl.set_label('max')
        self._xh.set_label('min')
        self._xl.set_decimals(7)
        self._xh.set_decimals(7)
        self._yl.set_decimals(7)
        self._yh.set_decimals(7)
        self._xlab = QtWidgets.QLabel('x limits')
        self._ylab = QtWidgets.QLabel('y limits')
        #self._maxlab = QtWidgets.QLabel('max')
        #self._minlab = QtWidgets.QLabel('min')
        #lims.addWidget(self._maxlab,1,0,1,1)
        #lims.addWidget(self._minlab,2,0,1,1)
        lims.addWidget(self._xlab,0,1,1,1,alignment=QtCore.Qt.AlignHCenter)
        lims.addWidget(self._xh,1,1,1,1,alignment=QtCore.Qt.AlignHCenter)
        lims.addWidget(self._xl,2,1,1,1,alignment=QtCore.Qt.AlignHCenter)
        lims.addWidget(self._ylab,0,2,1,1,alignment=QtCore.Qt.AlignHCenter)
        lims.addWidget(self._yh,1,2,1,1,alignment=QtCore.Qt.AlignHCenter)
        lims.addWidget(self._yl,2,2,1,1,alignment=QtCore.Qt.AlignHCenter)
        self._collapsables.append(self._xlab)
        self._collapsables.append(self._ylab)
        self._collapsables.append(self._xl)
        self._collapsables.append(self._xh)
        self._collapsables.append(self._yl)
        self._collapsables.append(self._yh)
        #self._collapsables.append(self._minlab)
        #self._collapsables.append(self._maxlab)

        # TICK MARKS
        ticks = QtWidgets.QGridLayout()
        self._x_numticks = gpi.widgets.BasicSpinBox(self)
        self._x_numticks.valueChanged.connect(self.on_draw)
        self._y_numticks = gpi.widgets.BasicSpinBox(self)
        self._y_numticks.valueChanged.connect(self.on_draw)
        self._x_ticks = QtWidgets.QLineEdit()
        self._y_ticks = QtWidgets.QLineEdit()
        self._x_ticks.textChanged.connect(lambda txt: self.check_validticks(self._x_ticks))
        self._y_ticks.textChanged.connect(lambda txt: self.check_validticks(self._y_ticks))
        self._x_ticks.setPlaceholderText('comma separated list of x labels')
        self._y_ticks.setPlaceholderText('comma separated list of y labels')
        self._x_ticks.returnPressed.connect(self.on_draw)
        self._y_ticks.returnPressed.connect(self.on_draw)
        self._x_numticks.set_immediate(True)
        self._y_numticks.set_immediate(True)
        self._x_numticks.set_min(2)
        self._y_numticks.set_min(2)
        self._x_numticks.set_max(100)
        self._y_numticks.set_max(100)
        self._x_numticks.set_val(5)
        self._y_numticks.set_val(5)
        self._x_numticks.set_label('x ticks')
        self._y_numticks.set_label('y ticks')
        ticks.addWidget(self._x_numticks, 0,0,1,1)
        ticks.addWidget(self._y_numticks, 1,0,1,1)
        ticks.addWidget(self._x_ticks, 0,1,1,1)
        ticks.addWidget(self._y_ticks, 1,1,1,1)
        self._collapsables.append(self._x_numticks)
        self._collapsables.append(self._y_numticks)
        self._collapsables.append(self._x_ticks)
        self._collapsables.append(self._y_ticks)

        # TITLE, XLABEL, YLABEL
        plotlabels = QtWidgets.QHBoxLayout()
        self._plot_title = QtWidgets.QLineEdit()
        self._plot_xlab = QtWidgets.QLineEdit()
        self._plot_ylab = QtWidgets.QLineEdit()
        self._plot_title.setPlaceholderText('title')
        self._plot_xlab.setPlaceholderText('x label')
        self._plot_ylab.setPlaceholderText('y label')
        self._plot_title.returnPressed.connect(self.on_draw)
        self._plot_xlab.returnPressed.connect(self.on_draw)
        self._plot_ylab.returnPressed.connect(self.on_draw)
        plotlabels.addWidget(self._plot_title)
        plotlabels.addWidget(self._plot_xlab)
        plotlabels.addWidget(self._plot_ylab)
        self._collapsables.append(self._plot_title)
        self._collapsables.append(self._plot_xlab)
        self._collapsables.append(self._plot_ylab)

        # XSCALE, YSCALE
        self._xscale_btn = gpi.widgets.BasicPushButton(self)
        self._xscale_btn.set_toggle(True)
        self._xscale_btn.set_button_title('log(x)')
        self._xscale_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._xscale_btn)
        self._yscale_btn = gpi.widgets.BasicPushButton(self)
        self._yscale_btn.set_toggle(True)
        self._yscale_btn.set_button_title('log(y)')
        self._yscale_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._yscale_btn)

        scale_options_layout = QtWidgets.QHBoxLayout()
        scale_options_layout.addWidget(self._xscale_btn)
        scale_options_layout.addWidget(self._yscale_btn)

        # LEGEND
        self._legend_btn = gpi.widgets.BasicPushButton(self)
        self._legend_btn.set_toggle(True)
        self._legend_btn.set_button_title('legend')
        self._legend_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._legend_btn)

        # HOLD
        self._hold_btn = gpi.widgets.BasicPushButton(self)
        self._hold_btn.set_toggle(True)
        self._hold_btn.set_button_title('hold')
        #self._hold_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._hold_btn)

        # MOVE AXES TO ORIGIN
        # self._origin_axes_btn = gpi.widgets.BasicPushButton(self)
        # self._origin_axes_btn.set_toggle(True)
        # self._origin_axes_btn.set_button_title("axes at (0,0)")
        # self._collapsables.append(self._origin_axes_btn)

        # RESET
        self._reset_btn = gpi.widgets.BasicPushButton(self)
        self._reset_btn.set_toggle(False)
        self._reset_btn.set_button_title('reset')
        self._reset_btn.valueChanged.connect(self._init_parms_)
        self._collapsables.append(self._reset_btn)

        # X=0, Y=0
        self._xeq0_btn = gpi.widgets.BasicPushButton(self)
        self._xeq0_btn.set_toggle(True)
        self._xeq0_btn.set_button_title('x=0')
        self._xeq0_btn.set_val(True)
        self._xeq0_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._xeq0_btn)
        self._yeq0_btn = gpi.widgets.BasicPushButton(self)
        self._yeq0_btn.set_toggle(True)
        self._yeq0_btn.set_button_title('y=0')
        self._yeq0_btn.set_val(True)
        self._yeq0_btn.valueChanged.connect(self.on_draw)
        self._collapsables.append(self._yeq0_btn)

        # LINE OPTIONS
        self._lino_btn = gpi.widgets.BasicPushButton(self)
        self._lino_btn.set_toggle(False)
        self._lino_btn.set_button_title('line options')
        self._lino_btn.valueChanged.connect(self.lineOptionsDialog)
        self._collapsables.append(self._lino_btn)

        # SUBPLOT SPACING OPTIONS
        self._subplotso_btn = gpi.widgets.BasicPushButton(self)
        self._subplotso_btn.set_toggle(False)
        self._subplotso_btn.set_button_title('spacing options')
        self._subplotso_btn.valueChanged.connect(self.subplotSpacingOptions)
        self._collapsables.append(self._subplotso_btn)
        self.adj_window = None

        plot_options_layout = QtWidgets.QHBoxLayout()
        plot_options_layout.addWidget(self._subplotso_btn)
        plot_options_layout.addWidget(self._lino_btn)

        grid_legend_lyt = QtWidgets.QHBoxLayout()
        grid_legend_lyt.addWidget(self._legend_btn)
        grid_legend_lyt.addWidget(self._grid_btn)

        autoscale_scale_lyt = QtWidgets.QHBoxLayout()
        autoscale_scale_lyt.addWidget(self._autoscale_btn)
        autoscale_scale_lyt.addWidget(self._xscale_btn)
        autoscale_scale_lyt.addWidget(self._yscale_btn)
        autoscale_scale_lyt.addWidget(self._xeq0_btn)
        autoscale_scale_lyt.addWidget(self._yeq0_btn)

        # HLINES
        self._hline1 = QtWidgets.QFrame()
        self._hline1.setFrameStyle(QtWidgets.QFrame.HLine | QtWidgets.QFrame.Sunken)
        self._hline1.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        self._collapsables.append(self._hline1)

        self._hline2 = QtWidgets.QFrame()
        self._hline2.setFrameStyle(QtWidgets.QFrame.HLine | QtWidgets.QFrame.Sunken)
        self._hline2.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        self._collapsables.append(self._hline2)

        self._hline3 = QtWidgets.QFrame()
        self._hline3.setFrameStyle(QtWidgets.QFrame.HLine | QtWidgets.QFrame.Sunken)
        self._hline3.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        self._collapsables.append(self._hline3)

        spc = 10
        self._spacer1 = QtWidgets.QSpacerItem(1,spc,QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        self._spacer2 = QtWidgets.QSpacerItem(1,spc,QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        self._spacer3 = QtWidgets.QSpacerItem(1,spc,QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        self._spacer4 = QtWidgets.QSpacerItem(1,spc,QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        self._spacer5 = QtWidgets.QSpacerItem(1,spc,QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        self._spacer6 = QtWidgets.QSpacerItem(1,spc,QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        self._collapsables.append(self._spacer1)
        self._collapsables.append(self._spacer2)
        self._collapsables.append(self._spacer3)
        self._collapsables.append(self._spacer4)
        self._collapsables.append(self._spacer5)
        self._collapsables.append(self._spacer6)

        # panel layout
        vbox.addLayout(plotlabels)

        vbox.addSpacerItem(self._spacer1)
        vbox.addWidget(self._hline1)
        vbox.addSpacerItem(self._spacer2)

        vbox.addLayout(lims)
        #vbox.addLayout(scale_options_layout)
        #vbox.addWidget(self._autoscale_btn)
        vbox.addLayout(autoscale_scale_lyt)

        vbox.addSpacerItem(self._spacer3)
        vbox.addWidget(self._hline2)
        vbox.addSpacerItem(self._spacer4)

        vbox.addLayout(ticks)
        #vbox.addWidget(self._legend_btn)
        vbox.addLayout(grid_legend_lyt)
        vbox.addLayout(plot_options_layout)
        #vbox.addWidget(self._lino_btn)
        #vbox.addWidget(self._subplotso_btn)

        vbox.addSpacerItem(self._spacer5)
        vbox.addWidget(self._hline3)
        vbox.addSpacerItem(self._spacer6)

        vbox.addWidget(self._hold_btn)
        # vbox.addWidget(self._origin_axes_btn)

        vbox.insertStretch(-1,1)
        vbox.addWidget(self._reset_btn)

        # plot window
        self._data = None
        self._plotwindow = self.create_main_frame()

        # put side panel and plot window together
        hbox = QtWidgets.QHBoxLayout()
        hbox.addLayout(vbox)
        hbox.addLayout(self._plotwindow)
        hbox.setStretch(0,0)
        hbox.setStretch(1,11)
        self.setLayout(hbox)

        #self._on_draw() # draw once to get initial settings
        #self.copySubplotSettings()

        # Don't hide side-panel options by default
        self.set_collapsed(False)
        self.set_grid(True)
        self.set_autoscale(True)

        # DEFAULTS
        self._init_parms_()

    # setters
    def set_val(self, data):
        '''Takes a list of npy arrays.
        '''
        if isinstance(data, list):
            self._data = data
            self.on_draw()

    def set_grid(self, val):
        self._grid_btn.set_val(val)
        self.on_draw()

    def set_autoscale(self, val):
        self._autoscale_btn.set_val(val)
        self.on_draw()

    def set_collapsed(self, val):
        """bool | Only collapse the display options, not the Plot window.
        """
        self._isCollapsed = val
        for wdg in self._collapsables:
            if hasattr(wdg, 'setVisible'):
                wdg.setVisible(not val)

    def set_xlim(self, val, quiet=False):
        '''tuple of floats (min, max)
        '''
        self._xh.set_val(val[0])
        self._xl.set_val(val[1])
        if not quiet:
            self.on_draw()

    def set_ylim(self, val, quiet=False):
        '''tuple of floats (min, max)
        '''
        self._yh.set_val(val[0])
        self._yl.set_val(val[1])
        if not quiet:
            self.on_draw()

    def set_plotOptions(self, val):
        self._subplotSettings = val

    def set_lineOptions(self, val):
        self._lineSettings = val

    def set_plotPosition(self, val):
        self._subplotPosition = val

    def set_ticks(self, s):
        self._x_numticks.set_val(s['xticknum'])
        self._y_numticks.set_val(s['yticknum'])
        self._x_ticks.setText(s['xticks'])
        self._y_ticks.setText(s['yticks'])

    def set_plotlabels(self, s):
        self._plot_title.setText(s['title'])
        self._plot_xlab.setText(s['xlabel'])
        self._plot_ylab.setText(s['ylabel'])
        self.on_draw()

    def set_legend(self, val):
        self._legend_btn.set_val(val)
        self.on_draw()

    def set_xline(self, val):
        self._yeq0_btn.set_val(val)
        self.on_draw()

    def set_yline(self, val):
        self._xeq0_btn.set_val(val)
        self.on_draw()

    def set_scale(self, val):
        self._xscale_btn.set_val(val['xscale'])
        self._yscale_btn.set_val(val['yscale'])
        self.on_draw()

    # getters
    def get_val(self):
        return self._data

    def get_grid(self):
        return self._grid_btn.get_val()

    def get_autoscale(self):
        return self._autoscale_btn.get_val()

    def get_xlim(self):
        return (self._xh.get_val(), self._xl.get_val())

    def get_ylim(self):
        return (self._yh.get_val(), self._yl.get_val())

    def get_plotOptions(self):
        return self._subplotSettings

    def get_lineOptions(self):
        return self._lineSettings

    def get_plotPosition(self):
        return self._subplotPosition

    def get_ticks(self):
        s = {}
        s['xticknum'] = self._x_numticks.get_val()
        s['yticknum'] = self._y_numticks.get_val()
        s['xticks'] = str(self._x_ticks.text())
        s['yticks'] = str(self._y_ticks.text())
        return s

    def get_plotlabels(self):
        s = {}
        s['title'] = str(self._plot_title.text())
        s['xlabel'] = str(self._plot_xlab.text())
        s['ylabel'] = str(self._plot_ylab.text())
        return s

    def get_legend(self):
        return self._legend_btn.get_val()

    def get_xline(self):
        return self._yeq0_btn.get_val()

    def get_yline(self):
        return self._xeq0_btn.get_val()

    def get_scale(self):
        s = {}
        s['xscale'] = self._xscale_btn.get_val()
        s['yscale'] = self._yscale_btn.get_val()
        return s

    # support
    def check_validticks(self, tickwdg):
        s = tickwdg.text()
        comma_cnt = s.count(',')
        if (comma_cnt > 0) or (len(s) == 0):
            color = '#ffffff' # white
            tickwdg.setStyleSheet('QLineEdit { background-color: %s }' % color)
            return

        #color = '#fff79a' # yellow
        color = '#f6989d' # red
        tickwdg.setStyleSheet('QLineEdit { background-color: %s }' % color)
        return

    def create_main_frame(self):
        self.fig = Figure((6.0, 4.8), dpi=100, facecolor='0.98', linewidth=6.0, edgecolor='0.93')
        self.axes = None
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self)
        self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.canvas.setFocus()

        self.canvas.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)

        #self.mpl_toolbar = NavigationToolbar(self.canvas, self)
        self.mpl_toolbar = NavbarTools(self.canvas, self)
        self.mpl_toolbar.actionTriggered.connect(self.copySubplotSettings)

        self.canvas.mpl_connect('key_press_event', self.on_key_press)

        vbox = QtWidgets.QVBoxLayout()
        vbox.addWidget(self.canvas)  # the matplotlib canvas
        vbox.addWidget(self.mpl_toolbar)
        return vbox
        #self.setLayout(vbox)

    def lineOptionsDialog(self):
        if self.axes is None:
            print("Matplotlib: no lines to modify, skipping line editor")
            return
        figure_edit(self.axes, self)
        self.copySubplotSettings()
        self.on_draw()

    def subplotSpacingOptions(self):
        if self.fig is None:
            return

        # don't allow the user to open extra windows
        if self.adj_window is not None:
            if self.adj_window.isActive():
                self.adj_window.raise_()
                return

        self.adj_window = MainWin_close()
        self.adj_window.window_closed.connect(self.copySubplotSettings)
        win = self.adj_window

        win.setWindowTitle("Subplot Configuration Tool")
        image = os.path.join( matplotlib.rcParams['datapath'],'images','matplotlib.png' )
        win.setWindowIcon(QtGui.QIcon( image ))

        tool = SubplotToolQt(self.fig, win)
        win.setCentralWidget(tool)
        win.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)

        win.show()

    def copySubplotSettings(self):
        '''Get a copy of the settings found in the 'Figure Options' editor.
        '''
        if self.axes is None:
            return

        # subplot settings
        for k in self._subplot_keepers:
            self._subplotSettings[k] = getattr(self.axes, 'get_'+k)()

        # line settings
        self._lineSettings = []
        for l in self.axes.get_lines():
            s = {}
            for k in self._line_keepers:
                s[k] = getattr(l, 'get_'+k)()
            self._lineSettings.append(s)

        # subplot position
        self._subplotPosition = {}
        self._subplotPosition['left'] = self.fig.subplotpars.left
        self._subplotPosition['right'] = self.fig.subplotpars.right
        self._subplotPosition['top'] = self.fig.subplotpars.top
        self._subplotPosition['bottom'] = self.fig.subplotpars.bottom
        self._subplotPosition['wspace'] = self.fig.subplotpars.wspace
        self._subplotPosition['hspace'] = self.fig.subplotpars.hspace

    def applySubplotSettings(self):
        '''Everytime the plot is drawn it looses its 'Figure Options' so just
        make sure they are applied again.
        '''
        # subplot settings
        for k in self._subplot_keepers:
            if k in self._subplotSettings:
                getattr(self.axes, 'set_'+k)(self._subplotSettings[k])

        #subplot position
        self.fig.subplots_adjust(**self._subplotPosition)

    def _init_parms_(self):
        '''Default parameter settings
        '''
        self._subplotSettings = {}
        self._subplotPosition = {'right': 0.913, 'bottom': 0.119, 'top': 0.912, 'wspace': 0.2, 'hspace': 0.2, 'left': 0.111}
        self._lineSettings = []
        self.set_autoscale(True)
        self.set_grid(True)
        s = {}
        s['xticknum'] = 5
        s['yticknum'] = 5
        s['xticks'] = ''
        s['yticks'] = ''
        self.set_ticks(s)
        s = {}
        s['title'] = ''
        s['xlabel'] = ''
        s['ylabel'] = ''
        self.set_plotlabels(s)
        self.set_legend(False)
        s = {}
        s['xscale'] = False # linear
        s['yscale'] = False
        self.set_scale(s)
        self.on_draw()

    def on_draw(self):
        self._on_draw_cnt += 1
        if not self._updatetimer.isActive():
            self._updatetimer.start()

    def _on_draw(self):

        # HOLD / Create New AXES
        if not self._hold_btn.get_val():
            self.fig.clear()
            self.axes = self.fig.add_subplot(111)

        # AUTOSCALE and LIMITS
        self.axes.set_autoscale_on(self.get_autoscale())
        if not self.get_autoscale():
            self.axes.set_xlim(self.get_xlim())
            self.axes.set_ylim(self.get_ylim())

        # TITLE, XLABEL and YLABEL
        self.axes.set_title(self.get_plotlabels()['title'], fontweight='bold', fontsize=16)
        self.axes.set_xlabel(self.get_plotlabels()['xlabel'], fontsize=14)
        self.axes.set_ylabel(self.get_plotlabels()['ylabel'], fontsize=14)

        # self.axes.plot(self.x, self.y, 'ro')
        # self.axes.imshow(self.data, interpolation='nearest')
        # self.axes.plot([1,2,3])

        # XSCALE
        if self.get_scale()['xscale']:
            self.axes.set_xscale('log')
        else:
            self.axes.set_xscale('linear')

        # YSCALE
        if self.get_scale()['yscale']:
            self.axes.set_yscale('log')
        else:
            self.axes.set_yscale('linear')

        # GRID
        ax_color = '0.5'
        if self.get_grid():
            self.axes.grid(self.get_grid(), color=ax_color)
        else:
            self.axes.grid(self.get_grid())

        # AXES SPINE COLOR
        self.axes.spines['bottom'].set_color(ax_color)
        self.axes.spines['top'].set_color(ax_color)
        self.axes.spines['right'].set_color(ax_color)
        self.axes.spines['left'].set_color(ax_color)
        try:
            # deprecated in Matplotlib 2.0
            self.axes.set_axis_bgcolor('0.97')
        except AttributeError:
            self.axes.set_facecolor('0.97')

        # if self._origin_axes_btn.get_val():
        #     self.axes.spines['left'].set_position('zero')
        #     self.axes.spines['bottom'].set_position('zero')
        #     self.axes.spines['left'].set_smart_bounds(True)
        #     self.axes.spines['bottom'].set_smart_bounds(True)
        #     self.axes.xaxis.set_ticks_position('bottom')
        #     self.axes.yaxis.set_ticks_position('left')

        if self._data is None:
            return

        try:
            self.fig.hold(True)
        except:
            pass

        # plot each set
        # print "--------------------plot the data"
        for data in self._data:
            ln = max(data.shape)
            lw = max(5.0-np.log10(ln), 1.0)
            if ln > 0:
                al = max(1.0-1.0/np.log2(ln), 0.75)
            else:
                al = 0

            if data.shape[-1] == 2:
                self.axes.plot(data[..., 0], data[..., 1], alpha=al, lw=lw)
            else:
                self.axes.plot(data, alpha=al, lw=lw)

        # X=0, Y=0
        if self.get_xline():
            self.axes.axhline(y=0, color='k', zorder=-1, label="y=0")
        if self.get_yline():
            self.axes.axvline(x=0, color='k', zorder=-1, label="x=0")

        # LEGEND
        if self.get_legend():
            handles, labels = self.axes.get_legend_handles_labels()
            self.axes.legend(handles, labels)

        # AUTOSCALE
        if self.get_autoscale():
            self.set_xlim(self.axes.get_xlim(), quiet=True)
            self.set_ylim(self.axes.get_ylim(), quiet=True)

        # X TICKS
        xl = self._x_ticks.text().split(',')
        if len(xl) > 1:
            self.axes.set_xticks(np.linspace(*self.axes.get_xlim(), num=len(xl)))
            self.axes.set_xticklabels(xl)
        else:
            self.axes.set_xticks(np.linspace(*self.axes.get_xlim(), num=self._x_numticks.get_val()))

        # Y TICKS
        yl = self._y_ticks.text().split(',')
        if len(yl) > 1:
            self.axes.set_yticks(np.linspace(*self.axes.get_ylim(), num=len(yl)))
            self.axes.set_yticklabels(yl)
        else:
            self.axes.set_yticks(np.linspace(*self.axes.get_ylim(), num=self._y_numticks.get_val()))

        self.applySubplotSettings()

        self.canvas.draw()

        #print 'draw count: ', self._on_draw_cnt
        self._on_draw_cnt = 0

    def on_key_press(self, event):
        # print 'Matplotlib-> you pressed:' + str(event.key)
        # implement the default mpl key press events described at
        # http://matplotlib.org/users/navigation_toolbar.html#navigation-
        # keyboard-shortcuts
        try:
            from matplotlib.backend_bases import key_press_handler
            key_press_handler(event, self.canvas, self.mpl_toolbar)
        except:
            print("key_press_handler import failed. -old matplotlib version.")
Exemple #10
0
class MatplotDisplay2(gpi.GenericWidgetGroup):
    valueChanged = gpi.Signal()

    def __init__(self, title, parent=None):
        super(MatplotDisplay2, self).__init__(title, parent)

        #self.data = self.get_data2()
        self._data = None
        self.create_main_frame()
        self.on_draw()

    # setters
    def set_val(self, data):
        '''Takes a list of npy arrays.
        '''
        if isinstance(data, list):
            self._data = data
            self.on_draw()
        else:
            return

    # getters
    def get_val(self):
        return self._data

    # support
    def create_main_frame(self):

        self.fig = Figure((5.0, 4.0), dpi=100)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self)
        self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.canvas.setFocus()

        self.mpl_toolbar = NavigationToolbar(self.canvas, self)

        self.canvas.mpl_connect('key_press_event', self.on_key_press)

        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(self.canvas)  # the matplotlib canvas
        vbox.addWidget(self.mpl_toolbar)
        self.setLayout(vbox)

    def get_data2(self):
        return np.arange(20).reshape([4, 5]).copy()

    def on_draw(self):
        self.fig.clear()
        self.axes = self.fig.add_subplot(111)
        # self.axes.plot(self.x, self.y, 'ro')
        # self.axes.imshow(self.data, interpolation='nearest')
        # self.axes.plot([1,2,3])

        if self._data is None:
            return

        self.fig.hold(True)

        # plot each set
        # print "--------------------plot the data"
        for data in self._data:

            # check for x, y data
            if data.shape[-1] == 2:
                self.axes.plot(data[..., 0], data[..., 1], alpha=0.8, lw=2.0)
            else:
                self.axes.plot(data, alpha=0.8, lw=2.0)

        self.canvas.draw()

    def on_key_press(self, event):
        # print 'Matplotlib-> you pressed:' + str(event.key)
        # implement the default mpl key press events described at
        # http://matplotlib.org/users/navigation_toolbar.html#navigation-
        # keyboard-shortcuts
        try:
            from matplotlib.backend_bases import key_press_handler
            key_press_handler(event, self.canvas, self.mpl_toolbar)
        except:
            print("key_press_handler import failed. -old matplotlib version.")
Exemple #11
0
class Watcher(QMainWindow):
    """"""

    def __init__(self, freezer, parent=None):
        """Constructor for Viewer"""
        self.freezer = freezer
        self.numTrials = 0
        self.currTrialNum = 0
        self.allTrials = None
        self.allAlignedTrials = None
        self.allOnsets = None
        self.idList = None

        # # Useful stuff
        self.onsetLine1 = None
        self.onsetLine2 = None
        
        self.isDragging = False

        QMainWindow.__init__(self, parent)
        # self.showMaximized()
        self.createMainFrame()
        # self.drawTrial()

    def queryData(self, queryStr):
        """Query some data from freezer
        """
        
        self.idList = []
        
        self.allTrials = []
        self.allAlignedTrials = []
        self.allOnsets = []
        
        self.allQueryResults = {} # {'idxxx': {'var1':value1, 'var2':value2...}}
        self.queryStr = queryStr

        # allDocs = self.freezer.processed.find(eval(self.queryStr))
        allDocs = self.freezer.posts.find(eval(self.queryStr))
        for doc in allDocs:
            s = StringIO.StringIO(doc['trialData'])
            tTrialData = pd.read_csv(s)
            self.allTrials.append(tTrialData)

            t = 0#doc['timeOnset']
            self.allOnsets.append(t)
            
            tId = doc['_id']
            self.idList.append(tId)
            
            self.allQueryResults[tId] = {
                'isAccepted': doc['isAccepted'],
                'trialData': tTrialData,
                'timeOnset': int(0.0)
            }

        self.numTrials = len(self.allTrials)

        # self.allAlignedTrials = [t for t in self.allTrials]
        print "Found", self.numTrials, "trials."

    def freezeAllOnsets(self):
        """Freeze timeOnset field in Freezer
        """
        allDocs = self.freezer.processed.find(eval(self.queryStr))
        try:
            for onset, doc in zip(self.allOnsets, allDocs):
                self.freezer.processed.update({'_id': doc['_id']},
                                              {'$set': {'timeOnset': onset}})
            print("Froze %d onsets" % len(self.allOnsets))
        except:
            print("Error updating")

    def freezeAllIsAccepted(self):
        """Freeze timeOnset field in Freezer
        """
        allDocs = self.freezer.processed.find(eval(self.queryStr))
        try:
            for isAccepted, doc in zip(self.allQueryResults[self.idList[self.currTrialNum]]['isAccepted'], allDocs):
                print isAccepted, doc['_id']
                self.freezer.processed.update({'_id': doc['_id']},
                                              {'$set': {'isAccepted': isAccepted}})
            print("Froze %d isAccepted flags" % len(self.allIsAccepted))
        except:
            print("Error updating")            

    def freezeAllQueryResults(self):
        """Freeze timeOnset field in Freezer
        """        
        try:
            for id in self.idList:
                print id, {'isAccepted': self.allQueryResults[id]['isAccepted']}
                self.freezer.processed.update({'_id': id},
                                              {'$set': {'isAccepted': self.allQueryResults[id]['isAccepted'],
                                                        'timeOnset': int(self.allQueryResults[id]['timeOnset'])}})
            print("Froze %d isAccepted flags" % len(self.idList))
        except:
            print("Error freezing")

    def createMainFrame(self):
        self.main_frame = QWidget()

        self.fig = Figure((5.0, 4.0), dpi=100)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.main_frame)
        self.canvas.setFocusPolicy(Qt.StrongFocus)
        self.canvas.setFocus()

        self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)

        ### Linking some events        
        self.canvas.mpl_connect('key_press_event', self.onKey)
        self.canvas.mpl_connect('pick_event', self.onPick)
        self.canvas.mpl_connect('button_press_event', self.onMouseDown)
        self.canvas.mpl_connect('button_release_event', self.onMouseUp)
        self.canvas.mpl_connect('motion_notify_event', self.onMouseMotion)




        self.textbox = QTextEdit("""{"analystName": "zcwaxs"}
                                 """)
        self.textbox.selectAll()
        self.textbox.setMinimumWidth(200)

        self.queryButton = QPushButton("&Query")
        self.connect(self.queryButton, SIGNAL('clicked()'), self.onSubmitQuery)

        self.fwdButton = QPushButton("&>>")
        self.connect(self.fwdButton, SIGNAL('clicked()'), self.onFwd)

        self.bwdButton = QPushButton("&<<")
        self.connect(self.bwdButton, SIGNAL('clicked()'), self.onBwd)

        self.alignButton = QPushButton("&Close")
        self.connect(self.alignButton, SIGNAL('clicked()'), self.onFinish)

        self.grid_cb = QCheckBox("Show &Grid")
        self.grid_cb.setChecked(False)
        # self.connect(self.grid_cb, SIGNAL('stateChanged(int)'), self.onGrid)

        self.isAcceptedCB = QCheckBox("Accept?")
        self.isAcceptedCB.setChecked(False)
        self.connect(self.isAcceptedCB, SIGNAL('stateChanged(int)'), self.onChangeIsAccepted)
        
        slider_label = QLabel('Bar width (%):')
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(1, 100)
        self.slider.setValue(20)
        self.slider.setTracking(True)
        self.slider.setTickPosition(QSlider.TicksBothSides)

        # self.connect(self.slider, SIGNAL('valueChanged(int)'), self.onSlider)

        #
        # Layout with box sizers
        #
        hbox = QHBoxLayout()

        for w in [self.textbox, self.queryButton,self.isAcceptedCB, 
                  self.bwdButton, self.fwdButton, self.alignButton,
                  self.grid_cb, slider_label, self.slider]:
            hbox.addWidget(w)
            hbox.setAlignment(w, Qt.AlignVCenter)

        vbox = QVBoxLayout()
        vbox.addWidget(self.canvas)
        vbox.addWidget(self.mpl_toolbar)
        vbox.addLayout(hbox)

        self.main_frame.setLayout(vbox)
        self.setCentralWidget(self.main_frame)

    def drawCurrTrial(self):
        self.fig.clear()
        self.fig.hold(True)
        self.ax1 = self.fig.add_subplot(211)
        self.ax2 = self.fig.add_subplot(212)

        self.ax1.plot(self.currTrial['Left Shoulder Flex / Time'])
        self.ax1.set_ylim([20, 120])
        self.ax2.plot(self.currTrial['Biceps'])
        self.ax2.set_ylim([-1.0, 1.0])
                
        ### Draw timeOnset lines
        self.onsetLine1 = self.ax1.axvline(x=self.currOnset(), ymin=0, ymax=100, color='b', linewidth=5)
        self.onsetLine2 = self.ax2.axvline(x=self.currOnset(), ymin=0, ymax=100, color='r', linewidth=5)

        
        self.canvas.draw()
    
    def currOnset(self):
       return self.allQueryResults[self.idList[self.currTrialNum]]['timeOnset']


    def setOnset(self):
        """Add the field 'onset' to all documents"""
        l = self.currTrial['Left Shoulder Flex / Time'][0:800]
        base = sum(l) / float(len(l))
        th = base * 0.98
        f = lambda x: x <= th
        
        possible = indices(f, self.currTrial['Left Shoulder Flex / Time'])
        tOnset = possible[0]
        self.allOnsets[self.currTrialNum] = tOnset
        self.allQueryResults[self.idList[self.currTrialNum]]['timeOnset'] = int(tOnset)
#        self.allAlignedTrials[self.currTrialNum] = self.currTrial.drop(xrange(self.currOnset - 100))
        
    def setPickedOnsetLine(self, artist):
        self.onsetLine1 = artist
        self.onsetLine1.set_color('g')
                
    def setCurrTrial(self, n=0):
        self.currTrialNum = n
        # print(len(self.allTrials))
        # self.currTrial = self.allTrials[self.currTrialNum]
        self.currTrial = self.allQueryResults[self.idList[n]]['trialData']
        # print(self.currTrialNum, len(self.currTrial))
        self.isAcceptedCB.setChecked(self.allQueryResults[self.idList[n]]['isAccepted'])
        self.setOnset()

    def setOnsetLine(self, new_x):
        xs, ys = self.onsetLine1.get_data()
        #new_xs = [min(rbound, max(lbound, new_x)) for xx in xs]
        self.onsetLine1.set_data(new_x, ys)
        self.onsetLine2.set_data(new_x, ys)
        self.allQueryResults[self.idList[self.currTrialNum]]['timeOnset'] = new_x
        self.canvas.draw()

    def onPick(self, event):
        self.setPickedOnsetLine(event.artist)
        self.canvas.draw()

    def onMouseDown(self, event):
        self.isDragging = True

    def onMouseUp(self, event):
        self.isDragging = False

    def onMouseMotion(self, event):
        if self.isDragging:
            self.setOnsetLine(event.xdata)
            
    def onKey(self, event):
        if event.key in '[':
            xs, ys = self.onsetLine1.get_data()
            new_xs = [xx - 20 for xx in xs]
            self.onsetLine1.set_data(new_xs, ys)
        elif event.key in ']':
            xs, ys = self.onsetLine1.get_data()
            new_xs = [xx + 20 for xx in xs]
            self.onsetLine1.set_data(new_xs, ys)
        elif event.key in '{':
            xs, ys = self.onsetLine1.get_data()
            new_xs = [xx - 100 for xx in xs]
            self.onsetLine1.set_data(new_xs, ys)
        elif event.key in '}':
            xs, ys = self.onsetLine1.get_data()
            new_xs = [xx + 100 for xx in xs]
            self.onsetLine1.set_data(new_xs, ys)
        self.canvas.draw()

    def onFwd(self):
        """Go forward 1 trial"""
        self.setCurrTrial(min(self.currTrialNum + 1, self.numTrials - 1))
        self.drawCurrTrial()
        # self.setOnset()
        # self.setOnsetLine()

    def onBwd(self):
        """Go backward 1 trial"""
        self.setCurrTrial(max(self.currTrialNum - 1, 0))
        self.drawCurrTrial()
        # self.setOnset()
        # self.setOnsetLine()
    
    def onChangeIsAccepted(self, value):            
        self.allQueryResults[self.idList[self.currTrialNum]]['isAccepted'] = \
            True if value == 2 else False
        
    def onFinish(self):
        # self.freezeAllOnsets()
        self.freezeAllQueryResults()
        self.close()

    def onSubmitQuery(self):
        self.queryData(str(self.textbox.toPlainText()))
        self.setCurrTrial()
        
        self.drawCurrTrial()
Exemple #12
0
class ResidualPlot(FigureCanvas):

    __instance = None

    def __init__(self):
        Global.event.task_selected.connect(self._on_task_selected)
        Global.event.plot_x_limit_changed.connect(self._on_x_limit_changed)
        Global.event.task_deleted.connect(self._on_task_deleted)
        Global.event.tasks_list_updated.connect(self._on_tasks_list_updated)

        self.task = None
        self.axes = None
        self.last_x_limit = []
        self.chi2s = []
        bg_color = str(QPalette().color(QPalette.Active, QPalette.Window).name())
        rcParams.update({'font.size': 10})

        self.figure = Figure(facecolor=bg_color, edgecolor=bg_color)
        self.figure.hold(False)
        super(ResidualPlot, self).__init__(self.figure)

        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.updateGeometry()
        self.hide()

    def _on_task_selected(self, task):
        self.set_task(task)
        self.redraw()

    def _on_task_deleted(self, task):
        if self.task == task:
            self.set_task(None)
            self.clear()

    def _on_tasks_list_updated(self):
        if not len(Global.tasks()):
            self.set_task(None)
            self.clear()

    def set_task(self, task):
        self.task = task

    def clear(self):
        self.figure.clf()
        self.figure.clear()
        self.draw()
        self.parent().chi2_label.hide()
        self.parent().chi2_value.hide()
        self.hide()
        gc.collect()

    def redraw(self):
        self.clear()

        if self.task.result.chi2 is None:
            self.parent().chi2_label.hide()
            self.parent().chi2_value.hide()
            self.hide()
            return

        self.chi2s.append(self.task.result.chi2)

        self.show()
        self.parent().chi2_label.show()
        self.parent().chi2_value.show()

        self.axes = self.figure.add_subplot(1, 1, 1)
        self.axes.grid(False)
        self.figure.set_alpha(0)
        self.axes.set_xlabel('Phase')
        self.axes.set_ylabel('Residual')

        phases = []
        delta_values = []

        keys = sorted(self.task.result.data().keys())

        for key in keys:
            if self.task.result.data()[key]['delta_value'] is not None:
                phases.append(key)
                delta_values.append(self.task.result.data()[key]['delta_value'])


        y_max = max(abs(min(delta_values)), abs(max(delta_values)))
        y_pad = (y_max / 100) * 10

        self.axes.set_autoscaley_on(False)
        self.axes.set_ylim([-(y_max + y_pad), y_max + y_pad])

        self.axes.set_autoscalex_on(False)
        self.axes.set_xlim(self.last_x_limit)

        color = QColor(0,0,0)
        min_chi2 = min(self.chi2s)
        if len(self.chi2s) == 1 :
            color = QColor(0,0,0)
        elif self.task.result.chi2 <= min_chi2 :
            color = QColor(0,139,0)
        else:
            color = QColor(255,0,0)

        self.axes.axhline(y=0, ls='--', linewidth=0.5, color='black')
        self.axes.scatter(phases, delta_values, s=0.5, color='r')

        palette = self.parent().chi2_value.palette()
        palette.setColor(QPalette.Active, QPalette.Text, color)
        self.parent().chi2_value.setPalette(palette)
        self.parent().chi2_value.setText(str(self.task.result.chi2))

        self.draw()

    def _on_x_limit_changed(self, limit):
        self.last_x_limit = limit
Exemple #13
0
class Plot(FigureCanvas):

    __instance = None

    def __init__(self):
        Global.event.task_selected.connect(self._on_task_selected)
        Global.event.task_deleted.connect(self._on_task_deleted)
        Global.event.tasks_list_updated.connect(self._on_tasks_list_updated)

        self.task = None
        self.last_x_limit = []
        self.axes = None

        bg_color = str(QPalette().color(QPalette.Active, QPalette.Window).name())
        rcParams.update({'font.size': 10})

        self.figure = Figure(facecolor=bg_color, edgecolor=bg_color)
        self.figure.hold(False)
        super(Plot, self).__init__(self.figure)

        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.updateGeometry()

    def _on_task_selected(self, task):
        self.set_task(task)
        self.redraw()

    def _on_task_deleted(self, task):
        if self.task == task:
            self.set_task(None)
            self.clear()
            ResultTab.instance().set_data([], [], [], [])

    def _on_tasks_list_updated(self):
        if not len(Global.tasks()):
            self.set_task(None)
            self.clear()
            ResultTab.instance().set_data([], [], [], [])

    @staticmethod
    def instance():
        return Plot.__instance

    def set_task(self, task):
        self.task = task

    def clear(self):
        self.figure.clf()
        self.figure.clear()
        gc.collect()

    def redraw(self):
        self.clear()

        self.axes = self.figure.add_subplot(1, 1, 1)
        self.axes.grid(True)
        self.axes.set_xlabel('Phase')
        self.axes.set_ylabel('Flux')

        result_phases = []
        result_values = []
        import_phases = []
        import_values = []

        keys = sorted(self.task.result.data().keys())

        for key in keys:
            if self.task.result.data()[key]['result_value'] is not None:
                result_phases.append(key)
                result_values.append(self.task.result.data()[key]['result_value'])

            if self.task.result.data()[key]['import_value'] is not None:
                import_phases.append(key)
                import_values.append(self.task.result.data()[key]['import_value'])

        ResultTab.instance().set_data(result_phases, result_values, import_phases, import_values)

        if not result_phases and not import_phases :
            return

        y_r_min = 1
        y_r_max = 0
        x_r_max = 0
        y_i_min = 1
        y_i_max = 0
        x_i_max = 0

        if result_values :
            y_r_min = min(result_values)
            y_r_max = max(result_values)
            x_r_max = max(abs(min(result_phases)), abs(max(result_phases)))

        if import_values :
            y_i_min = min(import_values)
            y_i_max = max(import_values)
            x_i_max = max(abs(min(import_phases)), abs(max(import_phases)))

        y_max = max(y_r_max, y_i_max)
        y_min = min(y_r_min, y_i_min)
        x_max = max(x_r_max, x_i_max)
        y_pad = ((y_max - y_min) / 100) * 10
        x_pad = (x_max / 100) * 10

        if y_min == y_max:
            y_min += 1
            y_max -= 1

        self.axes.set_autoscaley_on(False)
        self.axes.set_ylim([y_min - y_pad, y_max + y_pad])

        self.last_x_limit = [-(x_max + x_pad), x_max + x_pad]
        Global.event.plot_x_limit_changed.emit(self.last_x_limit)

        self.axes.set_autoscalex_on(False)
        self.axes.set_xlim(self.last_x_limit)

        if len(result_phases):
            self.axes.plot(result_phases, result_values, color='b', label="Prediction")

        if len(import_phases):
            self.axes.scatter(import_phases, import_values, s=1, color='r', label='Observation')

        self.draw()
Exemple #14
0
class Watcher(QMainWindow):
    """"""

    def __init__(self, freezer, parent=None):
        """Constructor for Viewer"""
        self.freezer = freezer
        self.numTrials = 0
        self.currTrialId = 0
        self.allTrials = None
        self.allAlignedTrials = None
        self.allOnsets = None

        # # Useful stuff
        self.onsetLine1 = None
        self.onsetLine2 = None

        QMainWindow.__init__(self, parent)
        # self.showMaximized()
        self.createMainFrame()
        # self.drawTrial()

    def queryData(self, queryStr):
        """Query some data from freezer
        """
        self.allTrials = []
        self.allAlignedTrials = []
        self.allOnsets = []
        self.queryStr = queryStr

        # allDocs = self.freezer.processed.find(eval(self.queryStr))
        allDocs = self.freezer.posts.find(eval(self.queryStr))
        for doc in allDocs:
            s = StringIO.StringIO(doc['trialData'])
            t = pd.read_csv(s)
            self.allTrials.append(t)

            t = 0#doc['timeOnset']
            self.allOnsets.append(t)

        self.numTrials = len(self.allTrials)

        # self.allAlignedTrials = [t for t in self.allTrials]
        print "Found", self.numTrials, "trials."

    def freezeAllOnsets(self):
        """Freeze timeOnset field in Freezer
        """
        allDocs = self.freezer.processed.find(eval(self.queryStr))
        try:
            for onset, doc in zip(self.allOnsets, allDocs):
                self.freezer.processed.update({'_id': doc['_id']},
                                              {'$set': {'timeOnset': onset}})
            print("Froze %d onsets" % len(self.allOnsets))
        except:
            print("Error updating")

    def createMainFrame(self):
        self.main_frame = QWidget()

        self.fig = Figure((5.0, 4.0), dpi=100)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.main_frame)
        self.canvas.setFocusPolicy(Qt.StrongFocus)
        self.canvas.setFocus()

        self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)

        # Other GUI controls
        #
        self.textbox = QTextEdit("""{"analystName": "Minos Niu",
                                     "gammaDyn": 100,
                                     "gammaSta": 100}
                                 """)
        self.textbox.selectAll()
        self.textbox.setMinimumWidth(200)

        self.queryButton = QPushButton("&Query")
        self.connect(self.queryButton, SIGNAL('clicked()'), self.onSubmit)

        self.fwdButton = QPushButton("&>>")
        self.connect(self.fwdButton, SIGNAL('clicked()'), self.onFwd)

        self.bwdButton = QPushButton("&<<")
        self.connect(self.bwdButton, SIGNAL('clicked()'), self.onBwd)

        self.alignButton = QPushButton("&Close")
        self.connect(self.alignButton, SIGNAL('clicked()'), self.onFinish)

        self.grid_cb = QCheckBox("Show &Grid")
        self.grid_cb.setChecked(False)
        # self.connect(self.grid_cb, SIGNAL('stateChanged(int)'), self.onGrid)

        slider_label = QLabel('Bar width (%):')
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(1, 100)
        self.slider.setValue(20)
        self.slider.setTracking(True)
        self.slider.setTickPosition(QSlider.TicksBothSides)
        # self.connect(self.slider, SIGNAL('valueChanged(int)'), self.onSlider)

        #
        # Layout with box sizers
        #
        hbox = QHBoxLayout()

        for w in [self.textbox, self.queryButton,
                  self.bwdButton, self.fwdButton, self.alignButton,
                  self.grid_cb, slider_label, self.slider]:
            hbox.addWidget(w)
            hbox.setAlignment(w, Qt.AlignVCenter)

        vbox = QVBoxLayout()
        vbox.addWidget(self.canvas)
        vbox.addWidget(self.mpl_toolbar)
        vbox.addLayout(hbox)

        self.main_frame.setLayout(vbox)
        self.setCentralWidget(self.main_frame)

    def drawCurrTrial(self):
        self.fig.clear()
        self.fig.hold(True)
        self.ax1 = self.fig.add_subplot(211)
        self.ax2 = self.fig.add_subplot(212)

        self.ax1.plot(self.currTrial['musLce0'])
        self.ax1.set_ylim([0.5, 1.5])
        self.ax2.plot(self.currTrial['emg0'])
        self.ax2.set_ylim([-6.0, 6.0])
        self.canvas.draw()

    def setOnsetLine(self):
        maxL = 100

        if self.onsetLine1 in self.ax1.lines:
            self.ax1.lines.remove(self.onsetLine1)
        if self.onsetLine2 in self.ax2.lines:
            self.ax2.lines.remove(self.onsetLine2)

        self.onsetLine1 = self.ax1.axvline(self.currOnset, 0, maxL, color='r')
        self.onsetLine2 = self.ax2.axvline(self.currOnset, 0, maxL, color='r')
        self.canvas.draw()

    def setOnset(self):
        """Add the field 'onset' to all documents"""
        l = self.currTrial.musLce0[0:100]
        base = sum(l) / float(len(l))
        th = base * 1.02
        f = lambda i: self.currTrial.musLce0[i] <= th <= self.currTrial.musLce0[min(len(self.currTrial) - 1, i + 1)]

        possible = filter(f, range(len(self.currTrial.musLce0)))
        if possible:
            self.currOnset = possible[0]
        else:
            self.currOnset = len(self.currTrial) / 2
        self.allOnsets[self.currTrialId] = self.currOnset
        self.allAlignedTrials[self.currTrialId] = self.currTrial.drop(xrange(self.currOnset - 100))

    def setCurrTrial(self, n=0):
        self.currTrialId = n
        # print(len(self.allTrials))
        self.currTrial = self.allTrials[self.currTrialId]
        # print(self.currTrialId, len(self.currTrial))

    def onFwd(self):
        """Go forward 1 trial"""
        self.setCurrTrial(min(self.currTrialId + 1, self.numTrials - 1))
        self.drawCurrTrial()
        # self.setOnset()
        # self.setOnsetLine()

    def onBwd(self):
        """Go backward 1 trial"""
        self.setCurrTrial(max(self.currTrialId - 1, 0))
        self.drawCurrTrial()
        # self.setOnset()
        # self.setOnsetLine()

    def onFinish(self):
        # self.freezeAllOnsets()
        self.close()

    def onSubmit(self):
        self.queryData(str(self.textbox.toPlainText()))
        self.setCurrTrial()
        self.drawCurrTrial()
Exemple #15
0
class Plot(FigureCanvas):
    def __init__(self,parent=None,labels=('','')):
        self.fig = Figure()
        self.axes = self.fig.add_subplot(111)
        self.axes.set_xlabel(labels[0])
        self.axes.set_ylabel(labels[1])
        self.axes.set_autoscale_on(True)
        FigureCanvas.__init__(self, self.fig)
        FigureCanvas.setSizePolicy(self,
                                   QtGui.QSizePolicy.Expanding,
                                   QtGui.QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
        self.lines = {}
        self.setParent(parent)
        self.fig.hold(True)
        self.drawRequested = False
        self.image = None
    def setPointFormat(self,pf):
        self.pointFormat = pf
    def addPoint(self,x,y,lineLabel,plotParams={'marker':'+'}.copy()):
        l = self.lines.get(lineLabel,None)
        if l:
            xdata = np.append(l.get_xdata(),x)
            ydata = np.append(l.get_ydata(),y)
            l.set_data(xdata,ydata)
        else:
            if 'label' not in plotParams:
                plotParams['label'] = lineLabel
            l = Line2D(np.array([x]),np.array([y]),**plotParams)
            self.axes.add_line(l)
            self.lines[lineLabel] = l
            self.axes.legend()
        self.axes.relim()
        self.axes.autoscale_view()
        self.requestDraw()
    def requestDraw(self):
        if self.isVisible():
            self.draw()
            self.drawRequested = False
        else:
            self.drawRequested = True
    def showEvent(self, *args, **kwargs):
        super(Plot,self).showEvent(*args, **kwargs)
        if self.drawRequested:
            self.draw()
    @QtCore.Slot()
    def clearPlot(self,label):
        l = self.lines.get(label,None)
        if l:
            l.remove()
            del self.lines[label]
        self.axes.legend()
        self.requestDraw()
    @QtCore.Slot()
    def clear(self):
        self.lines.clear()
        self.axes.clear()
        self.axes.legend()
        self.image = None
        self.requestDraw()
    @QtCore.Slot()
    def imshow(self,data):
        if self.image is None:
            self.image = self.axes.imshow(data,interpolation='nearest')
        self.requestDraw()