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()
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()
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()
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.")
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()
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
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.")
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()
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
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()
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()
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()