예제 #1
0
    def createBarChartA(self, dataDict, title, type):

        f1 = plt.figure(figsize=(1.5625, 1.5))
        #f1.set_facecolor(None)
        #f1.patch.set_alpha(0.0)
        temp = f1.add_subplot(111)

        my_colors = list(
            islice(cycle(['b', 'r', 'g', 'y', 'k']), None, len(dataDict)))

        temp.bar(range(len(dataDict)),
                 dataDict.values(),
                 align='center',
                 width=0.2,
                 color=my_colors)
        temp.set_xticks(range(len(dataDict)))
        temp.set_xticklabels(dataDict.keys())
        plt.setp(temp.get_xticklabels(),
                 rotation=20,
                 horizontalalignment='right')
        canvas2 = FigureCanvas(f1)
        plt.gcf().subplots_adjust(bottom=0.5)
        plt.title(title)
        canvas2.setMinimumWidth(150)
        canvas2.setMinimumHeight(150)

        self.statsFigures[type] = f1
        return canvas2
예제 #2
0
    def r_rep_widget(self):
        """
        This class creates the figure and instance of the ReducedRepPlot that is used to create the plot in the
        top right corner

        Parameters
        ----------
        self

        Returns
        -------
        None

        """
        figure = plt.figure()
        canvas = FigureCanvas(figure)
        canvas.mpl_connect('button_press_event', self.click_handling)
        FigureCanvas.setSizePolicy(canvas, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(canvas)
        canvas.setMinimumWidth(800)
        self.rpp = ReducedRepPlot(self.data_dict, self.key_list, 0, 100, 0, 100, "min", figure, canvas)
        toolbar = NavigationToolBar(canvas, self)
        layout = QtGui.QVBoxLayout()
        layout.addWidget(toolbar)
        layout.addWidget(canvas)
        self.display_box_1.addStretch()
        self.display_box_1.addLayout(layout)
예제 #3
0
    def createBarChartCorrelation(self, dataTupple):
        f1 = plt.figure(figsize=(1.5625, 1.5))
        #f1.set_facecolor(None)
        #f1.patch.set_alpha(0.0)
        temp = f1.add_subplot(111)

        x_axis_Titles = [function[0] for function in dataTupple]
        dataPoints = [function[1] for function in dataTupple]

        my_colors = list(
            islice(cycle(['b', 'r', 'g', 'y', 'k']), None, len(dataTupple)))

        temp.bar(range(len(dataTupple)),
                 dataPoints,
                 align='center',
                 width=0.2,
                 color=my_colors)
        temp.set_xticks(range(len(dataTupple)))
        temp.set_xticklabels(x_axis_Titles)
        plt.setp(temp.get_xticklabels(),
                 rotation=20,
                 horizontalalignment='right')
        canvas2 = FigureCanvas(f1)
        plt.gcf().subplots_adjust(bottom=0.5)
        plt.gca().set_ylim([min(dataPoints) - 0.2, 1])
        plt.title("Function Correlation")
        canvas2.setMinimumWidth(150)
        canvas2.setMinimumHeight(150)
        self.statsFigures["FunctionCorrelations"] = f1
        return canvas2
예제 #4
0
    def createBarChart(self):

        D = {u'Label0': 26, u'Label1': 17, u'Label2': 30}

        f1 = plt.figure(figsize=(1.5625, 0.2))
        #f1.set_facecolor(None)
        #f1.patch.set_alpha(0.0)
        temp = f1.add_subplot(111)
        my_colors = list(islice(cycle(['b', 'r', 'g', 'y', 'k']), None,
                                len(D)))
        temp.bar(range(len(D)),
                 D.values(),
                 align='center',
                 width=0.2,
                 color=my_colors)

        canvas2 = FigureCanvas(f1)
        canvas2.setMinimumWidth(150)
        canvas2.setMinimumHeight(150)
        return canvas2
예제 #5
0
    def createPieChart(self):
        # The slices will be ordered and plotted counter-clockwise.
        labels = 'User', 'Compiler', 'Other'
        sizes = [15, 55, 30]
        colors = ['blue', '#FA8500', '#80390A']
        explode = (0, 0.1, 0)  # only "explode" the 2nd slice (i.e. 'Hogs')

        figure = plt.figure(figsize=(1.5625, 0.2))
        #figure.set_facecolor(None)
        #figure.patch.set_alpha(0.0)
        canvas = FigureCanvas(figure)
        axes = figure.add_subplot(111)
        axes.pie(sizes,
                 explode=explode,
                 labels=labels,
                 colors=colors,
                 autopct='%1.1f%%',
                 shadow=True,
                 startangle=90)

        canvas.setMinimumWidth(150)
        canvas.setMinimumHeight(150)
        return canvas
예제 #6
0
    def createBoxPlot(self, dataDict):
        # basic plot
        f1 = plt.figure(figsize=(1.5625, 0.2))
        #f1.set_facecolor(None)
        #f1.patch.set_alpha(0.0)
        temp = f1.add_subplot(111)

        ## Create data
        np.random.seed(10)
        collectn_1 = dataDict.values()
        collectn_2 = np.random.normal(80, 30, 200)
        collectn_3 = np.random.normal(90, 20, 200)
        collectn_4 = np.random.normal(70, 25, 200)

        ## combine these different collections into a list
        data_to_plot = [collectn_1, collectn_2, collectn_3, collectn_4]

        # fake up some more data
        temp.boxplot(data_to_plot)
        # multiple box plots on one figure
        canvas2 = FigureCanvas(f1)
        canvas2.setMinimumWidth(150)
        canvas2.setMinimumHeight(150)
        return canvas2
예제 #7
0
파일: main_gui.py 프로젝트: pgroning/best
class MainWin(QMainWindow):
#class AppForm(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setWindowTitle('Main Window')
        #self.resize(1100,620)
        #self.move(200,200)
        
        # Initial window size/pos last saved
        self.settings = QSettings("greenbird")
        self.settings.beginGroup("MainWindow")
        self.resize(self.settings.value("size", QVariant(QSize(1100, 620))).toSize());
        self.move(self.settings.value("pos", QVariant(QPoint(200, 200))).toPoint())
        self.settings.endGroup()
        
        #screenShape = QDesktopWidget().screenGeometry()
        #self.resize( screenShape.width()*0.8,screenShape.width()*0.445 )
        #self.setMinimumWidth(1100)
        #self.setMinimumHeight(610)
        #Tracer()()

        self.resizeEvent = self.on_resize

        # Retrieve initial data
        #self.data_init()
        #self.case_id_current = 0

        self.create_menu()
        self.create_toolbar()
        self.create_main_frame()
        self.create_status_bar()

        self.on_draw() # Init plot
        #self.draw_fuelmap()

        #self.textbox.setText('1 2 3 4')
        #self.data_init()
        
        #self.case_cbox.setCurrentIndex(0) # Set default plot case
        #self.case_id_current = 0
        #self.on_plot() # Init plot
        #self.on_draw()
        #self.draw_fuelmap()
        #Tracer()()

    def on_resize(self,event):
        self.axes.set_xlim(0,1.2)
        self.axes.set_ylim(0,1)

    def openFile(self):
        #file_choices = "inp (*.inp);;pickle (*.p)"
        file_choices = "Data files (*.inp *.p)"
        filename = unicode(QFileDialog.getOpenFileName(self, 'Open file', '', file_choices))
        if filename:
            filext = os.path.splitext(filename)[1]
            if filext == ".p":
                self.load_pickle(filename)
            elif filext == ".inp":
                self.read_cax(filename)

    def load_pickle(self,filename):
        self.statusBar().showMessage('Importing data from %s' % filename, 2000)
        self.dataobj = casio()
        self.dataobj.loadpic(filename)

        self.init_pinobjects()
        #fuetype = 'SVEA-96'
        #self.dataobj.btf = btf(self.dataobj,fuetype)

        #self.setpincoords()
        #self.draw_fuelmap()
        #self.set_pinvalues()

        # Update case number list box
        ncases = len(self.dataobj.cases)
        for i in range(1,ncases+1):
            self.case_cbox.addItem(str(i))
        self.connect(self.case_cbox, SIGNAL('currentIndexChanged(int)'), self.fig_update)
        self.fig_update()
        
        
    def dataobj_finished(self):
        print "dataobject constructed"
        self.init_pinobjects()

        # Perform reference quick calculation for base case 
        print "Performing a reference quick calculation..."
        ncases = len(self.dataobj.cases)
        for case_num in range(ncases):
            self.quick_calc(case_num)

        #pyqt_trace()
        #self.thread.quit()
        #self.draw_fuelmap()
        #self.set_pinvalues()
        self.timer.stop()

        # Update case number list box
        #ncases = len(self.dataobj.cases)
        for i in range(1,ncases+1):
            self.case_cbox.addItem(str(i))
        self.connect(self.case_cbox, SIGNAL('currentIndexChanged(int)'), self.fig_update)
        self.fig_update()
            
        self.progressbar.update(100)
        self.progressbar.setWindowTitle('All data imported')
        self.progressbar.button.setText('Ok')
        self.progressbar.button.clicked.disconnect(self.killThread)
        self.progressbar.button.clicked.connect(self.progressbar.close)
        self.progressbar.button.setEnabled(True)
        
        #pyqt_trace()
        #QMessageBox.information(self,"Done!","All data imported!")

    def progressbar_update(self,val=None):
        if val is not None:
            self.progressbar._value = max(val,self.progressbar._value)
        self.progressbar.update(self.progressbar._value)
        self.progressbar._value += 1

    def killThread(self):
        print 'killThread'
        self.disconnect(self.timer,SIGNAL('timeout()'),self.progressbar_update)
        self.disconnect(self.thread,SIGNAL('finished()'),self.dataobj_finished)
        self.disconnect(self.thread,SIGNAL('progressbar_update(int)'),self.progressbar_update)
        self.thread._kill = True
        self.progressbar.close()
        #self.progressbar.close
#        self.thread.wait()
#        print 'killed'

    def read_cax(self,filename):
        msg = """ Click Yes to start importing data from cax files.
         
         This may take a while. Continue?
        """
        msgBox = QMessageBox()
        ret = msgBox.information(self,"Importing data",msg.strip(),QMessageBox.Yes|QMessageBox.Cancel)
        #ret = msgBox.question(self,"Importing data",msg.strip(),QMessageBox.Yes|QMessageBox.Cancel)
        self.statusBar().showMessage('Importing data from %s' % filename, 2000)
        self._filename = filename
        if ret == QMessageBox.Yes:

            #self.progressbar = ProgressBar()

            #self.dataobj = casio()
            self.thread = dataThread(self)
            self.connect(self.thread,SIGNAL('finished()'),self.dataobj_finished)
            self.connect(self.thread,SIGNAL('progressbar_update(int)'),self.progressbar_update)
            self.thread.start()

            self.progressbar = ProgressBar()
            xpos = self.pos().x() + self.width()/2 - self.progressbar.width()/2
            ypos = self.pos().y() + self.height()/2 - self.progressbar.height()/2
            self.progressbar.move(xpos,ypos)
            self.progressbar.show()
            self.progressbar.button.setEnabled(False)
            self.progressbar.button.clicked.connect(self.killThread)
            #self.progressbar.button.clicked.connect(self.progressbar.close)

            self.timer = QTimer()
            self.connect(self.timer,SIGNAL('timeout()'),self.progressbar_update)
            self.progressbar._value = 1
            self.timer.start(500)

            #time.sleep(20)
            #self.thread.terminate()
            #pyqt_trace()

            #print self.dataobj.data.caxfiles

            #self.dataobj = casio()
            #self.dataobj.readinp(filename)
            #self.dataobj.readcax()

            #self.dataobj.calcbtf()
            #fuetype = 'SVEA-96'
            #self.dataobj.btf = btf(self.dataobj,fuetype)

            #self.setpincoords()
            #self.draw_fuelmap()
            #self.set_pinvalues()
            #self.dataobj.savecas()
        else:
            return

    def saveData(self):
        file_choices = "Data files (*.p)"
        filename = unicode(QFileDialog.getSaveFileName(self, 'Open file', '', file_choices))
        self.dataobj.savepic(filename)

    def plotWin(self):
        #print "Open plot window"
        if hasattr(self,'dataobj'):
            plotwin = PlotWin(self)
            plotwin.show()
        else:
            msg = "There is no data to plot."
            msgBox = QMessageBox()
            msgBox.information(self,"No data",msg.strip(),QMessageBox.Close)

            
    def init_pinobjects(self):
        self.pinobjects = []
        ncases = len(self.dataobj.cases)
        for case_num in range(ncases):
            LFU = self.dataobj.cases[case_num].data.LFU
            ENR = self.dataobj.cases[case_num].data.ENR
            BA = self.dataobj.cases[case_num].data.BA
            pinlist = []
            for i in range(LFU.shape[0]):
                for j in range(LFU.shape[1]):
                    if LFU[i,j] > 0:
                        pinobj = cpin(self.axes)
                        pinobj.pos = [i,j]
                        pinobj.ENR = ENR[i,j]
                        pinobj.BA = BA[i,j]
                        pinobj.LFU = LFU[i,j]
                        pinlist.append(pinobj)
            self.pinobjects.append(pinlist)

            
    def set_pinvalues(self):
        #print "Set values"
        param_str = str(self.param_cbox.currentText())
        case_num = int(self.case_cbox.currentIndex())
        point_num = int(self.point_sbox.value())
        #print param_str,case_num,point_num

        #self.table.setHorizontalHeaderItem(1,QTableWidgetItem(param_str))
        #if param_str == 'FINT': param_str = 'POW'

        #if hasattr(self,'dataobj'): # data is loaded
        #    if param_str == 'ENR':
        #        pinvalues = getattr(self.dataobj.cases[case_num].data,param_str)
        #    else:
        #        pinvalues = getattr(self.dataobj.cases[case_num].statepts[point_num],param_str)
        #    #print pinvalues

        ENR = getattr(self.dataobj.cases[case_num].data,'ENR')
        EXP = getattr(self.dataobj.cases[case_num].statepts[point_num],'EXP')
        FINT = getattr(self.dataobj.cases[case_num].statepts[point_num],'POW')
        #BTF = self.dataobj.btf.DOX[point_num,:,:]

        burnup = self.dataobj.cases[case_num].statepts[point_num].burnup
        try:
            btf_num = next(i for i,x in enumerate(self.dataobj.btf.burnpoints) if x == burnup)
            BTF = self.dataobj.btf.DOX[btf_num,:,:]
        except:
            BTF = np.zeros(np.shape(self.dataobj.btf.DOX)[1:])
            BTF.fill(np.nan)

        npst = self.dataobj.cases[case_num].data.npst
        LFU = self.dataobj.cases[case_num].data.LFU
        BA = self.dataobj.cases[case_num].data.BA

        self.table.sortItems(0,Qt.AscendingOrder) # Sorting column 0 in ascending order
        self.setpincoords()
 
        #pyqt_trace()
        #row = 0
        k = 0
        for i in range(npst):
            for j in range(npst):
                if LFU[i,j] > 0:
                #if j != 5 and i !=5:
                #    if not ((i==4 and j==4) or (i==4 and j==6) or (i==6 and j==4) or (i==6 and j==6)):
                        #print i,j
                        #print self.circlelist[k].text.get_text()
                    self.pinobjects[case_num][k].EXP = EXP[i,j]
                    self.pinobjects[case_num][k].FINT = FINT[i,j]
                    self.pinobjects[case_num][k].BTF = BTF[i,j]
                    #self.circlelist[k].ENR = ENR[i,j]
                    #self.circlelist[k].EXP = EXP[i,j]
                    #self.circlelist[k].FINT = FINT[i,j]
                    #self.circlelist[k].BA = BA[i,j]
                    #self.circlelist[k].BTF = BTF[i,j]
                    #k += 1
                    #expval = QTableWidgetItem().setData(Qt.DisplayRole,EXP[i,j])
                    #self.table.setItem(row,1,expval)
                    expItem = QTableWidgetItem()
                    expItem.setData(Qt.EditRole, QVariant(float(np.round(EXP[i,j],3))))
                    fintItem = QTableWidgetItem()
                    fintItem.setData(Qt.EditRole, QVariant(float(np.round(FINT[i,j],3))))
                    btfItem = QTableWidgetItem()
                    btfItem.setData(Qt.EditRole, QVariant(float(np.round(BTF[i,j],3))))    

                    self.table.setItem(k,1,expItem)
                    self.table.setItem(k,2,fintItem)
                    self.table.setItem(k,3,btfItem)
                    k += 1
                    
                    #self.table.setItem(row,1,expItem)
                    #self.table.setItem(row,2,fintItem)
                    #self.table.setItem(row,3,btfItem)

                        #item.setData(Qt.EditRole, QVariant(float(FINT[i,j])))
                        #self.table.setItem(row,2,item)
                        #self.table.setItem(row,1,QTableWidgetItem(str(EXP[i,j])))
                        #self.table.setItem(row,2,QTableWidgetItem(str(FINT[i,j])))
                    #self.table.setItem(row,3,QTableWidgetItem(str(0)))
                #if j != 5 and i !=5: # Ignore water cross
                #if not (np.all(LFU[i,:]==0) or np.all(LFU[:,j]==0)): # Ignore water cross
                #    row += 1
        
        burnup = self.dataobj.cases[case_num].statepts[point_num].burnup
        voi = self.dataobj.cases[case_num].statepts[point_num].voi
        vhi = self.dataobj.cases[case_num].statepts[point_num].vhi
        kinf = self.dataobj.cases[case_num].statepts[point_num].kinf
        fint = self.dataobj.cases[case_num].statepts[point_num].fint
        btf = BTF.max()
        tfu = self.dataobj.cases[case_num].statepts[point_num].tfu
        tmo = self.dataobj.cases[case_num].statepts[point_num].tmo

        self.statusBar().showMessage("Burnup=%.3f : VOI=%.0f : VHI=%.0f : Kinf=%.5f : Fint=%.3f : BTF=%.4f : TFU=%.0f : TMO=%.0f" 
                                     % (burnup,voi,vhi,kinf,fint,btf,tfu,tmo))

        #if param_str == 'ENR':
            # Print pin ENR
        npins = len(self.pinobjects[case_num])
        #npins = len(self.circlelist)
        
        for i in range(npins):
            
            if self.pinobjects[case_num][i].BA == 0:
                j = next(j for j,cobj in enumerate(self.enrpinlist) if cobj.ENR == self.pinobjects[case_num][i].ENR)
            else:
                j = next(j for j,cobj in enumerate(self.enrpinlist)
                         if cobj.BA == self.pinobjects[case_num][i].BA and cobj.ENR == self.pinobjects[case_num][i].ENR)
            self.pinobjects[case_num][i].LFU = j+1
            fc = self.enrpinlist[j].circle.get_facecolor() 
            
            if param_str == 'ENR':
                #if self.pinobjects[case_num][i].BA == 0:
                #    j = next(j for j,cobj in enumerate(self.enrpinlist) if cobj.ENR == self.pinobjects[case_num][i].ENR)
                #else:
                #    j = next(j for j,cobj in enumerate(self.enrpinlist)
                #             if cobj.BA == self.pinobjects[case_num][i].BA and cobj.ENR == self.pinobjects[case_num][i].ENR)
                
                #if self.circlelist[i].BA == 0:
                #    j = next(j for j,cobj in enumerate(self.enrpinlist) if cobj.ENR == self.circlelist[i].ENR)
                #else:
                #    j = next(j for j,cobj in enumerate(self.enrpinlist)
                #             if cobj.BA == self.circlelist[i].BA and cobj.ENR == self.circlelist[i].ENR)
                
                #fc = self.enrpinlist[j].circle.get_facecolor()
                text = self.enrpinlist[j].text.get_text()
                self.pinobjects[case_num][i].text.remove()
                self.pinobjects[case_num][i].set_text(text)
                #self.circlelist[i].set_text(text)
                #self.circlelist[i].circle.set_facecolor(fc)
                self.pinobjects[case_num][i].circle.set_facecolor(fc)

            elif param_str == 'BTF':
                #text =  ('%.2f' % (self.pinobjects[case_num][i].BTF))
                btf_ratio = self.pinobjects[case_num][i].BTF/btf*100
                text =  ('%.0f' % (btf_ratio))
                self.pinobjects[case_num][i].text.remove()
                self.pinobjects[case_num][i].set_text(text)
                self.pinobjects[case_num][i].circle.set_facecolor(fc)
                
            elif param_str == 'EXP':
                if self.pinobjects[case_num][i].EXP < 10:
                    text =  ('%.1f' % (self.pinobjects[case_num][i].EXP))
                else:
                    text =  ('%.0f' % (self.pinobjects[case_num][i].EXP))
                self.pinobjects[case_num][i].text.remove()
                self.pinobjects[case_num][i].set_text(text)
                self.pinobjects[case_num][i].circle.set_facecolor(fc)
                
            #elif param_str == 'EXP':
            #    if self.circlelist[i].EXP < 10:
            #        text =  ('%.1f' % (self.circlelist[i].EXP))
            #    else:
            #        text =  ('%.0f' % (self.circlelist[i].EXP))
            #    self.circlelist[i].set_text(text)

            elif param_str == 'FINT':
                if self.pinobjects[case_num][i].FINT < 10:
                    text =  ('%.1f' % (self.pinobjects[case_num][i].FINT))
                else:
                    text =  ('%.0f' % (self.pinobjects[case_num][i].FINT))
                self.pinobjects[case_num][i].text.remove()
                self.pinobjects[case_num][i].set_text(text)
                self.pinobjects[case_num][i].circle.set_facecolor(fc)
            
            #elif param_str == 'FINT':
            #    if self.circlelist[i].FINT < 10:
            #        text =  ('%.1f' % (self.circlelist[i].FINT))
            #    else:
            #        text =  ('%.0f' % (self.circlelist[i].FINT))
            #    self.circlelist[i].set_text(text)
                
                
        self.canvas.draw()

        #self.circlelist[0].set_text(pinvalues[0,0])


    def setpincoords(self):
        self.table.clearContents()
        #self.xlist = ('01','02','03','04','05','06','07','08','09','10')
        #self.ylist  = ('A','B','C','D','E','F','G','H','I','J')
        case_num = int(self.case_cbox.currentIndex())
        npin = len(self.pinobjects[case_num])
        #npin = len(self.circlelist)
        self.table.setRowCount(npin)
        
        for i,pinobj in enumerate(self.pinobjects[case_num]):
        #for i,pinobj in enumerate(self.circlelist):
            coord_item = QTableWidgetItem(pinobj.coord)
            self.table.setVerticalHeaderItem(i,coord_item)
            i_item = QTableWidgetItem()
            i_item.setData(Qt.EditRole, QVariant(int(i)))
            self.table.setItem(i,0,i_item)


    def save_plot(self):
        file_choices = "PNG (*.png)|*.png"
        
        path = unicode(QFileDialog.getSaveFileName(self, 
                        'Save file', '', 
                        file_choices))
        if path:
            self.canvas.print_figure(path, dpi=self.dpi)
            self.statusBar().showMessage('Saved to %s' % path, 2000)
    
    def on_about(self):
        msg = """A design tool using PyQt with matplotlib.
        """
        QMessageBox.about(self, "About the software", msg.strip())

    def tableHeaderSort(self):
        #print "Sort header"
        case_num = int(self.case_cbox.currentIndex())
        for i,pinobj in enumerate(self.pinobjects[case_num]):
            #for i,pinobj in enumerate(self.circlelist):
            #item = QTableWidgetItem(str(self.table.item(i,0).text()))
            index = int(self.table.item(i,0).text())
            item = QTableWidgetItem(str(self.pinobjects[case_num][index].coord))
            #item = QTableWidgetItem(str(self.circlelist[index].coord))
            self.table.setVerticalHeaderItem(i,item)


    def tableSelectRow(self,i):
        index = next(j for j in range(self.table.rowCount()) 
                     if int(self.table.item(j,0).text()) == i)
        self.table.selectRow(index)


    def pinSelect(self,i):
        index = int(self.table.item(i,0).text())
        self.mark_pin(index)


    def on_click(self, event):
        # The event received here is of the type
        # matplotlib.backend_bases.PickEvent
        #
        # It carries lots of information, of which we're using
        # only a small amount here.
        # 

        #print event.x,event.y
        #if qApp.keyboardModifiers() & Qt.ControlModifier: # ctrl+click
        #    remove = False
        #else:
        #    remove = True
        case_num = int(self.case_cbox.currentIndex())

        if event.button is 1:
            #print event.xdata, event.ydata
            i = np.nan
            try: # check if any circle is selected and return the index
                i = next(i for i,cobj in enumerate(self.pinobjects[case_num])
                #i = next(i for i,cobj in enumerate(self.circlelist) 
                         if cobj.is_clicked(event.xdata,event.ydata))
            except:
                pass
            if i >= 0: # A Circle is selected
                #print self.circlelist[i].coord
                self.tableSelectRow(i)
                #self.table.selectRow(i)
                #print i,self.circlelist[i].x,self.circlelist[i].y
                self.mark_pin(i)
                self.pinselection_index = i
                j = self.halfsym_pin(i)


    def halfsym_pin(self,i):
        case_num = int(self.case_cbox.currentIndex())
        pos = self.pinobjects[case_num][i].pos
        sympos = list(reversed(pos))
        j = next(k for k,po in enumerate(self.pinobjects[case_num]) if po.pos == sympos)
        return j

    def mark_pin(self,i):
        case_num = int(self.case_cbox.currentIndex())
        d = self.pinobjects[case_num][i].circle.get_radius()*2*1.25
        x = self.pinobjects[case_num][i].x-d/2
        y = self.pinobjects[case_num][i].y-d/2

        #d = self.circlelist[i].circle.get_radius()*2*1.25
        #x = self.circlelist[i].x-d/2
        #y = self.circlelist[i].y-d/2
        if hasattr(self,'clickpatch'): # Remove any previously selected circles
            try:
                self.clickpatch.remove()
            except:
                pass
        #self.clickrect = mpatches.Rectangle((x,y), d, d,hatch='.',
        #                                    fc=(1,1,1),alpha=1.0,ec=(1, 0, 0))
        #self.clickrect = mpatches.Rectangle((x,y), d, d,
        #                                    fc=(1,1,1),Fill=False,ec=(0, 0, 0))
        r = self.pinobjects[case_num][i].circle.get_radius()*1.3
        x = self.pinobjects[case_num][i].x
        y = self.pinobjects[case_num][i].y
        #r = self.circlelist[i].circle.get_radius()*1.3
        #x = self.circlelist[i].x
        #y = self.circlelist[i].y
        self.clickpatch = mpatches.Circle((x,y), r, fc=(1,1,1), alpha=1.0, ec=(0.2, 0.2, 0.2))
        self.clickpatch.set_linestyle('solid')
        self.clickpatch.set_fill(False)
        self.clickpatch.set_linewidth(2.0)
        self.axes.add_patch(self.clickpatch)
        self.canvas.draw()

    def enr_add(self):
        halfsym = True
        case_num = int(self.case_cbox.currentIndex())
        ivec=[]
        ivec.append(self.pinselection_index)
        if halfsym:
            isym = self.halfsym_pin(ivec[0])
            if isym != ivec[0]: ivec.append(isym)
        for i in ivec:
            #print "Increase enrichment for pin " + str(i)
            pinEnr = self.pinobjects[case_num][i].ENR
            pinBA = self.pinobjects[case_num][i].BA
            #pinEnr = self.circlelist[i].ENR
            #pinBA = self.circlelist[i].BA
            
            for j,x in enumerate(self.enrpinlist):
                if np.isnan(x.BA): x.BA = 0.0
                if x.ENR == pinEnr and x.BA == pinBA:
                    break
            if j < len(self.enrpinlist)-1:
                self.__pinenr_update(i,j+1)

    def enr_sub(self):
        halfsym = True
        case_num = int(self.case_cbox.currentIndex())
        ivec=[]
        ivec.append(self.pinselection_index)
        if halfsym:
            isym = self.halfsym_pin(ivec[0])
            if isym != ivec[0]: ivec.append(isym)
        for i in ivec:
            #print "Decrease enrichment for pin " + str(i)
            pinEnr = self.pinobjects[case_num][i].ENR
            pinBA = self.pinobjects[case_num][i].BA
            #pinEnr = self.circlelist[i].ENR
            #pinBA = self.circlelist[i].BA

            for j,x in enumerate(self.enrpinlist):
                if np.isnan(x.BA): x.BA = 0.0
                if x.ENR == pinEnr and x.BA == pinBA:
                    break
            if j > 0:
                self.__pinenr_update(i,j-1)

        
        #enrArray = [x.ENR for x in self.enrpinlist][::-1] # Reverse order
        #print enrArray


    def __pinenr_update(self,i,j):
        #i = self.pinselection_index
        case_num = int(self.case_cbox.currentIndex())
        self.pinobjects[case_num][i].LFU = j+1
        self.pinobjects[case_num][i].ENR = self.enrpinlist[j].ENR
        #self.circlelist[i].ENR = self.enrpinlist[j].ENR
        if np.isnan(self.enrpinlist[j].BA):
            self.pinobjects[case_num][i].BA = 0.0
            #self.circlelist[i].BA = 0.0
        else:
            self.pinobjects[case_num][i].BA = self.enrpinlist[j].BA
            #self.circlelist[i].BA = self.enrpinlist[j].BA

        fc = self.enrpinlist[j].circle.get_facecolor()
        text = self.enrpinlist[j].text.get_text()
        if str(self.param_cbox.currentText()) == 'ENR':
            self.pinobjects[case_num][i].text.remove()
            self.pinobjects[case_num][i].set_text(text)
        #self.circlelist[i].set_text(text)
        self.pinobjects[case_num][i].circle.set_facecolor(fc)
        #self.circlelist[i].circle.set_facecolor(fc)

        self.dataobj.cases[case_num].qcalc[0].LFU = self.__lfumap(case_num)
        
        self.canvas.draw()


    def __lfumap(self,case_num):
        print "Creating LFU map"
        #case_num = int(self.case_cbox.currentIndex())
        
        #pyqt_trace()

        # Initialize new LFU map and fill with zeros
        LFU_old = self.dataobj.cases[case_num].data.LFU
        LFU = np.zeros((LFU_old.shape[0],LFU_old.shape[1]));
        
        k = 0
        for i in range(LFU.shape[0]):
            for j in range(LFU.shape[1]):
                if LFU_old[i,j] > 0:
                    LFU[i,j] = self.pinobjects[case_num][k].LFU
                    k += 1
        return LFU

    

    def quick_calc(self,case_num):
        print "Performing quick calculation..."
        LFU = self.__lfumap(case_num)
        self.dataobj.cases[case_num].qcalc[0].LFU = LFU
        self.dataobj.cases[case_num].quickcalc()
        print "Done" 

#       case_num = int(self.case_cbox.currentIndex())        
#        self.dataobj.cases[case_num].pertcalc()

        

        #pyqt_trace()

    def fig_update(self):
        """ Redraw figure and update values
        """
        #self.on_draw()
        self.axes.clear()
        self.draw_fuelmap()
        self.set_pinvalues()

    def on_draw(self):
        """ Setup the figure axis
        """

        # clear the axes and redraw the plot anew
        #
        #self.fig.clf()
        self.axes.clear()
        self.axes.axis('equal')
        #self.axes.set_xlim(0,1)
        #self.axes.set_ylim(0,1)
        #self.axes.axis('equal')
        
        #self.axes.set_position([0,0,1,1])
        #self.axes.set_xlim(0,1.2)
        #self.axes.set_ylim(0,1)
        self.axes.set_position([0,0,1,1])
        #self.axes.set_visible(False)
        self.axes.set_frame_on(False)
        self.axes.get_xaxis().set_visible(False)
        self.axes.get_yaxis().set_visible(False)
        #Tracer()()
        #self.axes.grid(self.grid_cb.isChecked())

        #xmax = self.slider.value()
        #self.axes.set_xlim(0,xmax)

        #self.axes.axis('equal')

        #Tracer()()
        
        #self.canvas.draw()

    def draw_fuelmap(self):
        """ Draw fuel map
        """
        #print "draw fuel map"
        from map_s96o2 import s96o2
        from map_a10xm import a10xm

        #print "draw fuel map"
        self.fig.set_facecolor((1,1,0.8784))
        # Draw outer rectangle
        rect = mpatches.Rectangle((0.035,0.035), 0.935, 0.935, fc=(0.8,0.898,1),ec=(0.3, 0.3, 0.3))
        self.axes.add_patch(rect)
        
        # Draw control rods
        rodrect_v = mpatches.Rectangle((0.011,0.13), 0.045, 0.77, ec=(0.3, 0.3, 0.3))
        rodrect_v.set_fill(False)
        self.axes.add_patch(rodrect_v)
        #self.axes.hlines(0.17,0.011,0.056)
        pp = [[0.011, 0.17], [0.056, 0.17]]
        poly = mpatches.Polygon(pp)
        poly.set_closed(False)
        self.axes.add_patch(poly)
        pp = [[0.011, 0.86], [0.056, 0.86]]
        poly = mpatches.Polygon(pp)
        poly.set_closed(False)
        self.axes.add_patch(poly)

        rodrect_h = mpatches.Rectangle((0.1,0.95), 0.77, 0.045, ec=(0.3, 0.3, 0.3))
        rodrect_h.set_fill(False)
        self.axes.add_patch(rodrect_h)
        pp = [[0.14, 0.95], [0.14, 0.995]]
        poly = mpatches.Polygon(pp)
        poly.set_closed(False)
        self.axes.add_patch(poly)
        pp = [[0.83, 0.95], [0.83, 0.995]]
        poly = mpatches.Polygon(pp)
        poly.set_closed(False)
        self.axes.add_patch(poly)


        # a fancy box with round corners (pad).
        p_fancy = mpatches.FancyBboxPatch((0.12, 0.12),
                                          0.77, 0.77,
                                          boxstyle="round,pad=0.04",
                                          #fc=(0.85,1,1),
                                          fc=(1,1,1),
                                          ec=(0.3, 0.3, 0.3))
        p_fancy.set_linewidth(4.0)
        self.axes.add_patch(p_fancy)
        
        if self.dataobj.data.fuetype == 'SVEA-96':
            s96o2(self)
        elif self.dataobj.data.fuetype == 'A10XM':
            a10xm(self)
 
        # Draw symmetry line
        #pp = [[0.035, 0.965], [0.965, 0.035]]
        #poly = mpatches.Polygon(pp)
        #poly.set_closed(False)
        #self.axes.add_patch(poly)

        
    def startpoint(self,case_id):
        voi_val = int(self.voi_cbox.currentText())
        vhi_val = int(self.vhi_cbox.currentText())
        type_val = str(self.type_cbox.currentText())

        case = self.cas.cases[case_id]
        if type_val == 'CCl':
            idx0 = case.findpoint(tfu=293)
            voi = case.statepts[idx0].voi
            vhi = case.statepts[idx0].vhi
            voi_index = [i for i,v in enumerate(self.voilist) if int(v) == voi][0]
            vhi_index = [i for i,v in enumerate(self.vhilist) if int(v) == vhi][0]
            self.voi_cbox.setCurrentIndex(voi_index)
            self.vhi_cbox.setCurrentIndex(vhi_index)
        else:
            idx0 = case.findpoint(voi=voi_val,vhi=vhi_val)
        return idx0



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

        # Create the mpl Figure and FigCanvas objects. 
        # 5x4 inches, 100 dots-per-inch
        #
        self.dpi = 100
        self.fig = Figure((6, 5), dpi=self.dpi, facecolor=None)
        #self.fig = Figure((6, 5), dpi=self.dpi, facecolor=(1,1,1))
        self.canvas = FigureCanvas(self.fig)
        self.canvas.mpl_connect('button_press_event',self.on_click)
        self.canvas.setParent(self.main_frame)
        self.canvas.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
        self.canvas.setMinimumWidth(500)
        self.canvas.setMinimumHeight(416)
        
        cvbox = QVBoxLayout()
        cvbox.addWidget(self.canvas)
        canvasGbox = QGroupBox()
        canvasGbox.setStyleSheet("QGroupBox { background-color: rgb(200, 200,\
        200); border:1px solid gray; border-radius:5px;}")
        canvasGbox.setLayout(cvbox)

        # Since we have only one plot, we can use add_axes 
        # instead of add_subplot, but then the subplot
        # configuration tool in the navigation toolbar wouldn't
        # work.
        #
        self.axes = self.fig.add_subplot(111)
        
        # Bind the 'pick' event for clicking on one of the bars
        #
        #self.canvas.mpl_connect('pick_event', self.on_pick)
        
        # Create the navigation toolbar, tied to the canvas
        #
        #self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)

        # Other GUI controls
        # 
        #self.textbox = QLineEdit()
        #self.textbox.setMinimumWidth(200)
        #self.connect(self.textbox, SIGNAL('editingFinished ()'), self.on_draw)

                
        #self.draw_button = QPushButton("Draw")
        #self.connect(self.draw_button, SIGNAL('clicked()'), self.on_plot)
        
        #self.grid_cb = QCheckBox("Show Grid")
        #self.grid_cb.setChecked(True)
        #self.connect(self.grid_cb, SIGNAL('stateChanged(int)'), self.on_draw)
        
        #slider_label = QLabel('X-max:')
        #self.slider = QSlider(Qt.Horizontal)
        #self.slider.setRange(1, 75)
        #self.slider.setValue(65)
        #self.slider.setTracking(True)
        #self.slider.setTickPosition(QSlider.TicksBothSides)
        #self.connect(self.slider, SIGNAL('valueChanged(int)'), self.on_draw)
 
        param_label = QLabel('Parameter:')
        self.param_cbox = QComboBox()
        paramlist = ['ENR','FINT','EXP','BTF','BTFP','XFL1','XFL2','ROD','LOCK']
        for i in paramlist:
            self.param_cbox.addItem(i)
        #self.connect(self.param_cbox, SIGNAL('currentIndexChanged(int)'), self.on_plot)
        param_hbox = QHBoxLayout()
        param_hbox.addWidget(param_label)
        param_hbox.addWidget(self.param_cbox)
        self.connect(self.param_cbox, SIGNAL('currentIndexChanged(int)'), self.set_pinvalues)

        case_label = QLabel('Case number:')
        self.case_cbox = QComboBox()
        #caselist = ['1', '2', '3']
        #for i in caselist:
        #    self.case_cbox.addItem(i)
        case_hbox = QHBoxLayout()
        case_hbox.addWidget(case_label)
        case_hbox.addWidget(self.case_cbox)
        #self.connect(self.case_cbox, SIGNAL('currentIndexChanged(int)'), self.set_pinvalues)
        #self.connect(self.case_cbox, SIGNAL('currentIndexChanged(int)'), self.fig_update)

        point_label = QLabel('Point number:')
        self.point_sbox = QSpinBox()
        self.point_sbox.setMinimum(0)
        self.point_sbox.setMaximum(10000)
        point_hbox = QHBoxLayout()
        point_hbox.addWidget(point_label)
        point_hbox.addWidget(self.point_sbox)
        self.connect(self.point_sbox, SIGNAL('valueChanged(int)'), self.set_pinvalues)

        self.enr_plus_button = QPushButton("+ enr")
        self.enr_minus_button = QPushButton("- enr")
        enr_hbox = QHBoxLayout()
        enr_hbox.addWidget(self.enr_minus_button)
        enr_hbox.addWidget(self.enr_plus_button)
        self.connect(self.enr_plus_button, SIGNAL('clicked()'), self.enr_add)
        self.connect(self.enr_minus_button, SIGNAL('clicked()'), self.enr_sub)

        self.calc_quick_button = QPushButton("Quick calc")
        self.calc_full_button = QPushButton("Full calc")
        calc_hbox = QHBoxLayout()
        calc_hbox.addWidget(self.calc_quick_button)
        calc_hbox.addWidget(self.calc_full_button)
        self.connect(self.calc_quick_button, SIGNAL('clicked()'), self.quick_calc)

        type_label = QLabel('Type:')
        self.type_cbox = QComboBox()
        typelist = ['Hot', 'HCr', 'CCl', 'CCr']
        for i in typelist:
            self.type_cbox.addItem(i)
        #self.connect(self.type_cbox, SIGNAL('currentIndexChanged(int)'), self.on_index)

        voi_label = QLabel('VOI:')
        self.voi_cbox = QComboBox()
        self.voilist = ['0', '40', '80']
        for i in self.voilist:
            self.voi_cbox.addItem(i)
        # Determine voi index
        #voi = self.cas.cases[self.case_id_current].statepts[0].voi
        #voi_index = [i for i,v in enumerate(self.voilist) if int(v) == voi]
        #voi_index = voi_index[0]
        #self.voi_cbox.setCurrentIndex(voi_index)
        #self.connect(self.voi_cbox, SIGNAL('currentIndexChanged(int)'), self.on_plot)

        vhi_label = QLabel('VHI:')
        self.vhi_cbox = QComboBox()
        self.vhilist = ['0', '40', '80']
        for i in self.vhilist:
            self.vhi_cbox.addItem(i)
        # Determine vhi index
        #vhi = self.cas.cases[self.case_id_current].statepts[0].vhi
        #vhi_index = [i for i,v in enumerate(self.vhilist) if int(v) == vhi]
        #vhi_index = vhi_index[0]
        #self.vhi_cbox.setCurrentIndex(vhi_index)
        #self.connect(self.vhi_cbox, SIGNAL('currentIndexChanged(int)'), self.on_plot)


        #self.case_cbox.setWhatsThis("What is this?")

        #self.connect(self.case_cbox, SIGNAL('activated(QString)'), self.on_case)
        #self.connect(self.case_cbox, SIGNAL('currentIndexChanged(int)'), self.on_plot)
        #Tracer()()

        # Define table widget
        self.table = QTableWidget()
        self.table.setRowCount(100)
        self.table.setColumnCount(4)
        #self.table.verticalHeader().hide()
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch)
        self.table.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.Minimum)
        self.table.setMinimumWidth(180)
        self.table.setHorizontalHeaderLabels(('Index','EXP','FINT','BTF'))
        self.table.setSortingEnabled(True)
        self.table.setColumnHidden(0,True)
        
        #self.connect(self.table.horizontalHeader(),SIGNAL('QHeaderView.sortIndicatorChanged(int)'),self.openFile)
        self.connect(self.table.horizontalHeader(),SIGNAL('sectionClicked(int)'),self.tableHeaderSort)
        self.connect(self.table.verticalHeader(),SIGNAL('sectionClicked(int)'),self.pinSelect)
        #self.connect(self.table,SIGNAL('cellClicked(int,int)'),self.pinSelect)
        #self.connect(self.table,SIGNAL('currentChanged(int)'),self.pinSelect)
        #Tracer()()
        self.table.cellActivated.connect(self.pinSelect)
        self.table.cellClicked.connect(self.pinSelect)
        #self.table.selectionModel().selectionChanged.connect(self.pinSelect)

        tvbox = QVBoxLayout()
        tvbox.addWidget(self.table)
        tableGbox = QGroupBox()
        tableGbox.setStyleSheet("QGroupBox { background-color: rgb(200, 200,\
        200); border:1px solid gray; border-radius:5px;}")
        tableGbox.setLayout(tvbox)
        
        #self.hview = QHeaderView

       #self.tableview = QTableView()
        #self.connect(self.table.horizontalHeader().sectionClicked(), SIGNAL('logicalIndex(int)'),self.openFile)
        #self.connect(QHeaderView.sortIndicatorChanged(), SIGNAL('logicalIndex(int)'),self.openFile)
        

        #self.setpincoords()
        self.table.resizeColumnsToContents()
        #Tracer()()

        #
        # Layout with box sizers
        # 
        vbox = QVBoxLayout()
        vbox.addLayout(param_hbox)
        vbox.addLayout(case_hbox)
        vbox.addLayout(point_hbox)
        vbox.addLayout(enr_hbox)
        vbox.addLayout(calc_hbox)

        #spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        #vbox.addItem(spacerItem)
        vbox.addStretch(1)

        groupbox = QGroupBox()
        groupbox.setStyleSheet("QGroupBox { background-color: rgb(200, 200,\
        200); border:1px solid gray; border-radius:5px;}")
        groupbox.setLayout(vbox)

        #for w in [  self.textbox, self.draw_button, self.grid_cb,
        #            slider_label, self.slider]:
        
        #for w in [  type_label, self.type_cbox, voi_label, self.voi_cbox,
        #            vhi_label, self.vhi_cbox]:
        #
        #    vbox.addWidget(w)
        #    vbox.setAlignment(w, Qt.AlignHCenter)
        

        #self.bundle = Bundle()
        #self.bundle.setParent(self.main_frame)
        #Tracer()()

        hbox = QHBoxLayout()

        #hbox.addWidget(self.bundle)
        #vbox.addLayout(hbox)
        #vbox.addWidget(self.canvas)
        #hbox2.addWidget(self.mpl_toolbar)
        
        spacerItemH = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)

        #hbox.addLayout(vbox)
        hbox.addWidget(groupbox)
        #hbox.addItem(spacerItemH)
        #hbox.addWidget(self.canvas)
        hbox.addWidget(canvasGbox)
        #hbox.addItem(spacerItemH)
        hbox.addWidget(tableGbox)
        #hbox.addWidget(self.table)
        #hbox.addItem(spacerItemH)

        self.main_frame.setLayout(hbox)
        self.setCentralWidget(self.main_frame)
        #Tracer()()
    
    def create_status_bar(self):
        self.status_text = QLabel("Main window")
        self.statusBar().addWidget(self.status_text, 1)
        
    def create_menu(self):        
        self.file_menu = self.menuBar().addMenu("&File")
        
        save_settings_action = self.create_action("&Save settings...",
            shortcut="Ctrl+E", slot=self.save_plot, 
            tip="Save settings")
        quit_action = self.create_action("&Quit", slot=self.close, 
                                         shortcut="Ctrl+Q", tip="Close the application")
        
        open_file_action = self.create_action("&Open file...", slot=self.openFile,
                                              shortcut="Ctrl+L", tip="Open file")

        save_data_action = self.create_action("&Save data...", slot=self.saveData,
                                              shortcut="Ctrl+S", tip="Save data to file")

        self.add_actions(self.file_menu, 
            (open_file_action, save_data_action, save_settings_action, None, quit_action))


        self.edit_menu = self.menuBar().addMenu("&Edit") 
        preferences = self.create_action("Preferences...", tip="Preferences...")        
        self.add_actions(self.edit_menu, (None, preferences))

        self.tools_menu = self.menuBar().addMenu("&Tools")
        plot_action = self.create_action("Plot...", tip="Plot...", slot=self.plotWin)
        btf_action = self.create_action("BTF...", tip="BTF...")
        casmo_action = self.create_action("CASMO...", tip="CASMO...")
        data_action = self.create_action("Fuel data...", tip="Fuel data...")
        table_action = self.create_action("Point table...", tip="Point table...")
        optim_action = self.create_action("Optimization...", tip="BTF optimization...")
        egv_action = self.create_action("EGV...", tip="EGV...")
        self.add_actions(self.tools_menu, 
                         (plot_action, btf_action, casmo_action, data_action,
                          table_action, optim_action, egv_action))
        
        
        self.help_menu = self.menuBar().addMenu("&Help")
        about_action = self.create_action("&About", 
            shortcut='F1', slot=self.on_about, 
            tip='About the demo')
        
        self.add_actions(self.help_menu, (about_action,))

    def create_toolbar(self):
        exitAction = QAction(QIcon('icons/exit-icon_32x32.png'), 'Exit', self)
        #exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(self.close)

        fileAction = QAction(QIcon('icons/open-file-icon_32x32.png'), 'Open file', self)
        fileAction.setStatusTip('Open file')
        fileAction.triggered.connect(self.openFile)

        settingsAction = QAction(QIcon('icons/preferences-icon_32x32.png'), 'Settings', self)
        settingsAction.setStatusTip('Settings')

        plotAction = QAction(QIcon('icons/diagram-icon_32x32.png'), 'Plot', self)
        plotAction.setStatusTip('Open plot window')
        plotAction.triggered.connect(self.plotWin)

        toolbar = self.addToolBar('Toolbar')
        toolbar.addAction(fileAction)
        toolbar.addAction(settingsAction)
        toolbar.addAction(plotAction)
        toolbar.addAction(exitAction)

        toolbar.setMovable(False)
        toolbar.setFloatable(True)
        toolbar.setAutoFillBackground(False)


    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def create_action(  self, text, slot=None, shortcut=None, 
                        icon=None, tip=None, checkable=False, 
                        signal="triggered()"):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(":/%s.png" % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot)
        if checkable:
            action.setCheckable(True)
        return action

    def closeEvent(self, event):
        # Write window size and position to config file
        self.settings.beginGroup("MainWindow")
        self.settings.setValue("size", QVariant(self.size()))
        self.settings.setValue("pos", QVariant(self.pos()))
        self.settings.endGroup()
        print "Good bye!"
예제 #8
0
class miVentana(QtGui.QWidget):
    def __init__(self):
        super(miVentana, self).__init__()
        self.titulo = 'Toda Informacion'
        self.ejeX = 'Todos'
        self.ejeY = 'Tiempo'
        self.miFilaAuxiliar = Queue()
        self.miTarjetaAdquisicion = TarjetaAdquisicion(self.miFilaAuxiliar)
        self.puertoConectadoExitoso = self.miTarjetaAdquisicion.reconociPuerto
        time.sleep(2)
        self.initUI()
        self.estadoAuxiliar = False
        self.indices = {
            'Todos': [0, '$[V] [A] [C] [rpm]$'],
            'Tiempo': [0, '$t [s]$'],
            'Voltaje': [1, 'v [V]'],
            'Corriente': [2, '$I [A]$'],
            'Temperatura': [3, '$T [C]$'],
            'rpm': [4, '$\omega [rpm]$']
        }

    def initUI(self):
        ## PARAMETROS DEL MOTOR
        self.miTituloIzquierdo = QtGui.QLabel('Datos de Placa')
        self.parametrosOrganizacionales = QtGui.QHBoxLayout()
        self.parametrosDePlaca1 = QtGui.QHBoxLayout()
        self.parametrosDePlaca2 = QtGui.QHBoxLayout()
        self.parametrosDePlaca3 = QtGui.QHBoxLayout()
        self.miMotor = QtGui.QLabel('Motor:')
        self.miDataMotor = QtGui.QLineEdit('Motor-001')
        self.parametrosOrganizacionales.addWidget(self.miMotor)
        self.parametrosOrganizacionales.addWidget(self.miDataMotor)
        self.miPotenciaPlaca = QtGui.QLabel('Potencia Nominal [HP]:')
        self.miDatoPotenciaPlaca = QtGui.QLineEdit(str(85))
        self.parametrosDePlaca1.addWidget(self.miPotenciaPlaca)
        self.parametrosDePlaca1.addWidget(self.miDatoPotenciaPlaca)
        self.miTensionNominal = QtGui.QLabel('Voltaje Nominal [V]:')
        self.miDataTensionNominal = QtGui.QLineEdit(str(350))
        self.parametrosDePlaca2.addWidget(self.miTensionNominal)
        self.parametrosDePlaca2.addWidget(self.miDataTensionNominal)
        self.miVelocidadNominal = QtGui.QLabel('Velocidad Nominal [rpm]:')
        self.miDataVelocidadNominal = QtGui.QLineEdit(str(3500))
        self.parametrosDePlaca3.addWidget(self.miVelocidadNominal)
        self.parametrosDePlaca3.addWidget(self.miDataVelocidadNominal)

        # MENU SUPERIOS
        extractAction = QtGui.QAction('&SALIR', self)
        extractAction.setShortcut('Ctrl+Q')
        extractAction.setStatusTip('Salir de la aplicacion')
        extractAction.triggered.connect(self.closeApplication)

        ## CONTROL EJECUCIÓN
        self.botonDeInicio = QtGui.QPushButton("Importar Datos")
        self.botonDeCancel = QtGui.QPushButton("Detener")
        self.botonDeInicializacion = QtGui.QPushButton("Descartar Prueba")
        self.botonParaPDF = QtGui.QPushButton("Exportar Info")
        #self.botonParaPDF.setStyleSheet("background-color: green")
        self.botonDeInicializacion.setEnabled(False)
        self.botonParaPDF.setEnabled(False)
        self.botonDeCancel.setEnabled(False)
        self.botonDeInicio.resize(100, 100)
        self.botonDeCancel.resize(100, 100)
        #self.botonDeInicio.setMinimumHeight(60)
        #self.botonDeCancel.setMinimumHeight(60)

        self.barraControlPrograma = QtGui.QHBoxLayout()
        self.barraControlPrograma.addWidget(self.botonDeInicio)
        self.barraControlPrograma.addWidget(self.botonDeCancel)

        self.barraControlPostPrograma = QtGui.QHBoxLayout()
        self.barraControlPostPrograma.addWidget(self.botonDeInicializacion)
        self.barraControlPostPrograma.addWidget(self.botonParaPDF)

        ## Control de Botones
        self.botonDeInicio.clicked.connect(self.importarDatos)
        self.botonDeCancel.clicked.connect(self.detenerDatos)
        self.botonDeInicializacion.clicked.connect(self.inicializarTodo)
        self.botonParaPDF.clicked.connect(self.exportarInformacion)

        # a figure instance to plot on
        #self.figure = Figure()
        self.figure = graficaActual.figure(figsize=(15, 5))

        # this is the Canvas Widget that displays the `figure`
        # it takes the `figure` instance as a parameter to __init__
        self.canvas = FigureCanvas(self.figure)
        self.canvas.resize(500, 800)
        self.canvas.setMinimumWidth(450)
        self.canvas.setMaximumWidth(500)
        self.canvas.setMinimumHeight(350)

        # this is the Navigation widget
        # it takes the Canvas widget and a parent
        self.toolbar = NavigationToolbar(self.canvas, self)

        ### CONTROL DE GRAFICA:
        self.miTituloControlGrafica = QtGui.QLabel(
            'Graficar: (Inicio: ' +
            self.miTarjetaAdquisicion.horaInicioLiteral + ')')
        self.miLegendaVS = QtGui.QLabel('vs')

        self.seleccionDeOrdenada = QtGui.QComboBox(self)
        self.seleccionDeOrdenada.addItem('Todos')
        self.seleccionDeOrdenada.addItem('Voltaje')
        self.seleccionDeOrdenada.addItem('Corriente')
        self.seleccionDeOrdenada.addItem('Temperatura')
        self.seleccionDeOrdenada.addItem('rpm')

        self.seleccionDeAbsisa = QtGui.QComboBox(self)
        self.seleccionDeAbsisa.addItem('Tiempo')
        self.seleccionDeAbsisa.addItem('Voltaje')
        self.seleccionDeAbsisa.addItem('Corriente')
        self.seleccionDeAbsisa.addItem('Temperatura')
        self.seleccionDeAbsisa.addItem('rpm')

        self.seleccionDeOrdenada.activated[str].connect(
            self.actualizarOrdenada)
        self.seleccionDeAbsisa.activated[str].connect(self.actualizarAbsisa)

        self.barraControlGrafica = QtGui.QHBoxLayout()
        self.barraControlGrafica.addWidget(self.seleccionDeOrdenada)
        self.barraControlGrafica.addWidget(self.miLegendaVS)
        self.barraControlGrafica.addWidget(self.seleccionDeAbsisa)

        ## SECCION COMENTARIOS:
        self.miTituloComentarios = QtGui.QLabel('Comentarios:')
        self.miComentario = QtGui.QTextEdit()
        #self.miComentario.setMinimumHeight(50)

        ## Control de puerto
        self.miEtiquetaPuerto = QtGui.QLabel('Conectar a:')
        self.miIntroduccionPuerto = QtGui.QLineEdit('ttyAMA0')

        ## Adquisicion de datos:
        self.miDataMotor.editingFinished.connect(self.actualizarIngresoDatos)
        self.miDatoPotenciaPlaca.editingFinished.connect(
            self.actualizarIngresoDatos)
        self.miDataTensionNominal.editingFinished.connect(
            self.actualizarIngresoDatos)
        self.miDataVelocidadNominal.editingFinished.connect(
            self.actualizarIngresoDatos)
        self.miIntroduccionPuerto.returnPressed.connect(
            self.intentoIntroducirPuerto)
        #self.miComentario.textChanged.connect(self.actualizarIngresoDatos)

        ## GRAFICA IZQUIERDA

        capaVerticalAuxiliar = QtGui.QVBoxLayout()
        if not self.puertoConectadoExitoso:
            self.miEtiquetaPuerto.setText('No conectado, Conectar a:')
            self.botonDeInicio.setEnabled(False)
        capaVerticalAuxiliar.addWidget(self.miEtiquetaPuerto)
        capaVerticalAuxiliar.addWidget(self.miIntroduccionPuerto)
        capaVerticalAuxiliar.addWidget(self.miTituloIzquierdo)
        capaVerticalAuxiliar.addLayout(self.parametrosOrganizacionales)
        capaVerticalAuxiliar.addLayout(self.parametrosDePlaca1)
        capaVerticalAuxiliar.addLayout(self.parametrosDePlaca2)
        capaVerticalAuxiliar.addLayout(self.parametrosDePlaca3)
        capaVerticalAuxiliar.addWidget(self.miTituloControlGrafica)
        capaVerticalAuxiliar.addLayout(self.barraControlGrafica)
        capaVerticalAuxiliar.addWidget(self.miTituloComentarios)
        capaVerticalAuxiliar.addWidget(self.miComentario)
        capaVerticalAuxiliar.addStretch(1)
        capaVerticalAuxiliar.addLayout(self.barraControlPostPrograma)
        capaVerticalAuxiliar.addLayout(self.barraControlPrograma)

        graficaV = QtGui.QVBoxLayout()

        graficaV.addWidget(self.toolbar)
        graficaV.addWidget(self.canvas)

        layoutHorizontalPrincipal = QtGui.QHBoxLayout()
        #layoutHorizontalPrincipal.addStretch(1)
        layoutHorizontalPrincipal.addLayout(capaVerticalAuxiliar)
        layoutHorizontalPrincipal.addLayout(graficaV)
        self.setMinimumHeight(430)

        self.setLayout(layoutHorizontalPrincipal)

        self.setGeometry(300, 300, 300, 150)
        self.setWindowTitle('Adquisición de datos de Motor DC')
        self.setWindowIcon(QtGui.QIcon('./pictures/logo.png'))
        try:
            QtGui.QApplication.setStyle(QtGui.QStyleFactory.create(
                sys.argv[1]))
        except:
            QtGui.QApplication.setStyle(
                QtGui.QStyleFactory.create('Cleanlooks'))
        self.show()

    def closeApplication(self):
        choice = QtGui.QMessageBox.question(
            self, 'Leaving so soon?',
            'Are you sure you want to exit the program?',
            QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
        if choice == QtGui.QMessageBox.Yes:
            self.miTarjetaAdquisicion.salir()
            sys.exit()
        else:
            pass

    def intentoIntroducirPuerto(self):
        exitoConexion = self.miTarjetaAdquisicion.iniciarPuerto(
            puerto='/dev/' + self.miIntroduccionPuerto.text())
        if exitoConexion:
            self.miEtiquetaPuerto.setText('Exito, conectado a ' +
                                          self.miIntroduccionPuerto.text())
            self.miIntroduccionPuerto.clear()  #setVisible(False)
            self.botonDeInicio.setEnabled(True)
        else:
            self.miEtiquetaPuerto.setText('Aun no puedo conectarme a ' +
                                          self.miIntroduccionPuerto.text())
            self.miIntroduccionPuerto.clear()

    def actualizarIngresoDatos(self):
        campos = [
            self.miDataMotor.text(),
            self.miDatoPotenciaPlaca.text(),
            self.miDataTensionNominal.text(),
            self.miDataVelocidadNominal.text(),
            self.miComentario.toPlainText()
        ]
        if (self.miTarjetaAdquisicion.actualizarCampos(campos)):
            self.botonParaPDF.setEnabled(True)
            self.botonDeInicializacion.setEnabled(True)
        else:
            self.botonParaPDF.setEnabled(False)
            self.botonDeInicializacion.setEnabled(False)

    def actualizarOrdenada(self, text):
        self.refrescarGrafica(self.seleccionDeOrdenada.currentText(),
                              self.seleccionDeAbsisa.currentText(),
                              self.miTarjetaAdquisicion.obtenerUltimosDatos())

    def actualizarAbsisa(self, text):
        self.refrescarGrafica(self.seleccionDeOrdenada.currentText(),
                              self.seleccionDeAbsisa.currentText(),
                              self.miTarjetaAdquisicion.obtenerUltimosDatos())

    def importarDatos(self):
        self.estadoAuxiliar = True
        self.miTarjetaAdquisicion.recibirInformacion()
        self.miTituloControlGrafica.setText(
            'Graficar : Inicio (' +
            self.miTarjetaAdquisicion.horaInicioLiteral + ')')
        self.botonDeCancel.setEnabled(True)
        self.botonDeInicio.setEnabled(False)
        self.miTareaGraficaParalela = threading.Thread(
            target=self.actualizacionAutomaticaGrafica, args=("task", ))
        self.miTareaGraficaParalela.start()

    def inicializarTodo(self):
        # Se hace un refresco previo para borrar los valores que puedan estar en etapa intermedia
        self.refrescarGrafica('Todos', 'Tiempo',
                              self.miTarjetaAdquisicion.actualizarDatos())
        self.miTarjetaAdquisicion.inicializar()
        self.refrescarGrafica('Todos', 'Tiempo',
                              self.miTarjetaAdquisicion.actualizarDatos())
        self.actualizarIngresoDatos()
        self.botonDeInicio.setEnabled(True)

    def exportarInformacion(self):
        self.actualizarIngresoDatos()
        self.miTarjetaAdquisicion.exportarDatosACSV()
        self.refrescarGrafica(self.seleccionDeOrdenada.currentText(),
                              self.seleccionDeAbsisa.currentText(),
                              self.miTarjetaAdquisicion.obtenerUltimosDatos(),
                              True)

    def detenerDatos(self):
        self.estadoAuxiliar = False
        self.miTarjetaAdquisicion.detenerInformacion()
        self.botonDeInicio.setText("Importar Datos")
        self.botonDeCancel.setEnabled(False)
        self.miTareaGraficaParalela.do_run = False
        self.miTareaGraficaParalela.join()
        self.actualizarIngresoDatos()

    def actualizacionAutomaticaGrafica(self, argumento):
        self.miTareaGraficaParalela = threading.currentThread()
        while getattr(self.miTareaGraficaParalela, "do_run", True):
            self.refrescarGrafica(self.seleccionDeOrdenada.currentText(),
                                  self.seleccionDeAbsisa.currentText(),
                                  self.miTarjetaAdquisicion.actualizarDatos())
            #print(len(self.miTarjetaAdquisicion.actualizarDatos()[0]))
        #print('Finalizando grafica desde adentro')

    def refrescarGrafica(self,
                         argumentoOrdenada,
                         argumentoAbsisa,
                         listaDatos,
                         guardarEnPDF=False):
        if listaDatos == None:
            #print('Nada que actualizar')
            pass
        else:
            self.titulo = self.miDataMotor.text()
            if argumentoOrdenada == 'Todos':
                graficaActual.cla()
                ax1 = self.figure.add_subplot(111)
                t = listaDatos[0]  #range(len(listaDatos[0]))
                v = listaDatos[1]
                c = listaDatos[2]
                T = listaDatos[3]
                r = listaDatos[4]
                graficaActual.title(self.titulo)
                graficaActual.ylabel('$[V] [A] [C] [rpm]$')
                graficaActual.xlabel(
                    self.miTarjetaAdquisicion.horaInicioLiteral + '+ $t [s]$')
                graficaActual.grid()
                graficaActual.plot(t, v, label='v')
                graficaActual.plot(t, c, label='i')
                graficaActual.plot(t, T, label='T')
                graficaActual.plot(t, r, label='rpm')
                #graficaActual.plot(t,v,'b.-',label='v',t,c,'y.-',label='i',t,T,'r.-',label='T',t,r,'g.-',label='rpm')
                graficaActual.legend(loc='upper center',
                                     bbox_to_anchor=(0.5, 1.05),
                                     ncol=4,
                                     fancybox=True,
                                     shadow=True)
                if guardarEnPDF:
                    graficaActual.savefig(self.titulo + '_' +
                                          self.miTarjetaAdquisicion.fechaHora +
                                          '.pdf',
                                          bbox_inches='tight')
                self.canvas.draw()
                graficaActual.gcf().clear()
            else:
                graficaActual.cla()
                ax1 = self.figure.add_subplot(111)
                a = listaDatos[self.indices[argumentoAbsisa][0]]
                o = listaDatos[self.indices[argumentoOrdenada][0]]
                self.titulo += '_' + argumentoOrdenada + '_vs_' + argumentoAbsisa
                graficaActual.title(self.titulo)
                if self.indices[argumentoAbsisa][0] == 0:
                    graficaActual.xlabel(
                        self.miTarjetaAdquisicion.horaInicioLiteral + ' + ' +
                        self.indices[argumentoAbsisa][1])
                else:
                    graficaActual.xlabel(self.indices[argumentoAbsisa][1])

                graficaActual.ylabel(self.indices[argumentoOrdenada][1])
                graficaActual.grid()
                graficaActual.plot(a, o)
                if guardarEnPDF:
                    graficaActual.savefig(self.titulo + '_' +
                                          self.miTarjetaAdquisicion.fechaHora +
                                          '.pdf',
                                          bbox_inches='tight')
                self.canvas.draw()
class ViewerPlot(QtGui.QWidget):
    def __init__(self, data_model=None, x_model=None, y_model=None, parent=None):
        super(ViewerPlot, self).__init__(parent)

        self._model = data_model
        self._x_model = x_model
        self._y_model = y_model

        # show lines or histogram
        self._line_plot_active = True
        self._line_legend = None
        self._selected_x_cache = None
        # _large_data_limit define the upper limit before the user
        # needs to check the `plot_larger_data_check` checkbox to allow plotting
        self._large_data_limit = 10000000
        # _max_data_points defines the maximum number of data points before
        # we resample to data to short plot time
        self._max_data_points = 10000

        # set the binning for the histogram
        self._binning_user_set = False

        self._init_gui()

    def _init_gui(self):
        self.setContentsMargins(1, 1, 1, 1)

        plot_toolbar = sywidgets.SyToolBar(self)
        self.x_label = QtGui.QLabel('X:')
        self.x_value = QtGui.QComboBox()
        self.x_value.setModel(self._x_model)
        self.x_value.setToolTip('Select the column used for the x values')
        y_label = QtGui.QLabel('Y:')
        self.y_value = sywidgets.CheckableComboBox()
        self.y_value.setModel(self._y_model)
        self.y_value.setToolTip('Select the columns used for the y values. '
                                'Multiple columns can be selected.')

        resample_label = QtGui.QLabel('Resample:')
        self.resample_value = QtGui.QSpinBox()
        self.resample_value.setMinimum(1)
        self.resample_value.setMaximum(100000)
        self.resample_value.setToolTip('The step size used for resampling of large datasets.')
        resample_widget = QtGui.QWidget(self)
        resample_widget.setContentsMargins(2, 2, 2, 2)
        resample_layout = QtGui.QHBoxLayout()
        resample_layout.setContentsMargins(0, 0, 0, 0)
        resample_layout.addWidget(resample_label)
        resample_layout.addWidget(self.resample_value)
        resample_widget.setLayout(resample_layout)

        self.plot_large_data_check = QtGui.QCheckBox('Plot large data')
        self.plot_large_data_check.setToolTip('Check if large data should be plotted.')
        
        binning_label = QtGui.QLabel('Binning:')
        self.binning_value = QtGui.QSpinBox()
        self.binning_value.setValue(10)
        self.binning_value.setMinimum(1)
        self.binning_value.setMaximum(100000)
        self.binning_value.setToolTip('The number of bins used for the histogram.')
        binning_widget = QtGui.QWidget(self)
        binning_widget.setContentsMargins(2, 2, 2, 2)
        binning_layout = QtGui.QHBoxLayout()
        binning_layout.setContentsMargins(0, 0, 0, 0)
        binning_layout.addWidget(binning_label)
        binning_layout.addWidget(self.binning_value)
        binning_widget.setLayout(binning_layout)

        plot_toolbar.addWidget(self.x_label)
        plot_toolbar.addWidget(self.x_value)
        self._y_label_action = plot_toolbar.addWidget(y_label)
        self._y_value_action = plot_toolbar.addWidget(self.y_value)
        plot_toolbar.addSeparator()
        # plot settings menu
        self.plot_setting_menu = QtGui.QMenu(plot_toolbar)
        # create resample menu action
        resample_action = QtGui.QWidgetAction(self)
        resample_action.setDefaultWidget(resample_widget)
        self.plot_setting_menu.addAction(resample_action)

        self.large_data_action = QtGui.QWidgetAction(self)
        self.large_data_action.setDefaultWidget(self.plot_large_data_check)
        self.large_data_action.setVisible(False)
        self.plot_setting_menu.addAction(self.large_data_action)

        self.binning_action = QtGui.QWidgetAction(self)
        self.binning_action.setDefaultWidget(binning_widget)
        self.binning_action.setVisible(False)
        self.plot_setting_menu.addAction(self.binning_action)

        setting_button = QtGui.QToolButton()
        setting_button.setMenu(self.plot_setting_menu)
        setting_button.setPopupMode(QtGui.QToolButton.InstantPopup)

        setting_button_action = QtGui.QWidgetAction(self)
        setting_button_action.setDefaultWidget(setting_button)

        icon = QtGui.QIcon(prim.get_icon_path('actions/system-run-symbolic.svg'))
        setting_button.setIcon(icon)
        plot_toolbar.addAction(setting_button_action)
        setting_button.setToolTip('Configure plot settings such as data resample or histogram binning.')

        plot_toolbar.addSeparator()

        self.show_line_action = plot_toolbar.add_action(
            text='Show line plot',
            icon_name='actions/view-plot-line-symbolic.svg',
            tooltip_text='Show line plot',
            is_checkable=True,
            is_checked=True,
            is_exclusive=True,
            receiver=self._on_show_line,
            signal_type='toggled')

        self.show_hist_action = plot_toolbar.add_action(
            text='Show histogram',
            icon_name='actions/view-plot-hist-symbolic.svg',
            tooltip_text='Show histogram',
            is_checkable=True,
            is_exclusive=True,
            receiver=self._on_show_hist,
            signal_type='toggled')

        plot_toolbar.addStretch()

        # figure
        self.figure = Figure()
        self._set_figure_background_color()
        self.canvas = FigureCanvas(self.figure)
        frame = QtGui.QFrame()
        frame.setFrameStyle(QtGui.QFrame.StyledPanel)
        frame_layout = QtGui.QVBoxLayout()
        frame_layout.setContentsMargins(0, 0, 0, 0)
        frame.setLayout(frame_layout)
        frame_layout.addWidget(self.canvas)
        policy = QtGui.QSizePolicy()
        policy.setHorizontalStretch(1)
        policy.setVerticalStretch(1)
        policy.setHorizontalPolicy(QtGui.QSizePolicy.Expanding)
        policy.setVerticalPolicy(QtGui.QSizePolicy.Expanding)
        self.canvas.setSizePolicy(policy)
        self.canvas.setMinimumWidth(300)
        self.axes = self.figure.add_subplot(111)

        # Figure Layout
        layout = QtGui.QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(plot_toolbar)
        layout.addWidget(frame)

        # Default navigation toolbar for matplotlib
        self.mpl_toolbar = sywidgets.SyNavigationToolbar(self.canvas, self)
        layout.addWidget(self.mpl_toolbar)

        self.setLayout(layout)

        self._update_signal_comboboxes()

        self._timeout_after = 500
        self._update_plot_timer = QtCore.QTimer(self)
        self._update_plot_timer.setInterval(self._timeout_after)
        self._update_plot_timer.setSingleShot(True)

        self.x_value.currentIndexChanged[int].connect(self._x_selection_changed)
        self.y_value.currentIndexChanged[int].connect(self._y_selection_changed)
        self.y_value.selectedItemsChanged.connect(self._update_plot_timer.start)
        self.resample_value.valueChanged[int].connect(self._resample_value_changed)
        self.binning_value.valueChanged.connect(self._binning_value_changed)
        self.plot_large_data_check.stateChanged.connect(self._update_plot_timer.start)
        self._update_plot_timer.timeout.connect(self._update_plot)

    def paintEvent(self, event):
        self._draw_canvas()
        super(ViewerPlot, self).paintEvent(event)

    def _set_figure_background_color(self):
        # FIXME: setting the correct facecolor for matplotlib figures embedded
        # in QTabWidgets doesn't work
        color = self.palette().color(self.backgroundRole())
        self.figure.set_facecolor(color.name())

    def _draw_canvas(self):
        self.axes.relim()
        self.axes.autoscale_view(True, True, True)
        self.figure.tight_layout()
        self.canvas.draw()

    def _update_plot(self, redraw=True):
        table = self._model.table()
        if table is None:
            return
        if self._line_legend is not None:
            old_legend_loc = self._line_legend._loc
        else:
            old_legend_loc = 1
        self.axes.cla()  # clear plot

        if (table.number_of_rows() > self._large_data_limit and
                not self.plot_large_data_check.isChecked()):
            return

        # show line plots
        if self._line_plot_active:
            self._y_label_action.setVisible(True)
            self._y_value_action.setVisible(True)
            x_column_name = self.x_value.currentText()
            y_column_names = self.y_value.checkedItemNames()
            for y_column_name in y_column_names:
                self._plot_line(x_column_name, y_column_name)
            if len(y_column_names) == 1:
                y_attr = table.get_column_attributes(y_column_names[0])
                unit = y_attr.get('unit', None)
                y_label = unicode(y_column_names[0])
                if unit is not None:
                    y_label += u' [{}]'.format(unit)
                self.axes.set_ylabel(y_label)
            if len(self.axes.lines):
                self._line_legend = self.axes.legend(loc='upper left')
            else:
                self._line_legend = None
            if self._line_legend is not None:
                self._line_legend.draggable(True, use_blit=True)
                # (Bene) not a good way to use private variables
                self._line_legend._loc = old_legend_loc
        else:
            # show histogram
            self._y_label_action.setVisible(False)
            self._y_value_action.setVisible(False)
            hist_column = self.x_value.currentText()
            self._plot_hist(hist_column)
        if redraw:
            self._draw_canvas()

    def _plot_hist(self, y_column_name):
        table = self._model.table()
        row_slice = slice(0, table.number_of_rows(), int(self.resample_value.value()))
        y_data = table.get_column_to_array(y_column_name)[row_slice]
        y_dtype = table.column_type(y_column_name)
        if y_dtype.kind in ['S', 'U', 'M']:
            return
        # 10 is the maximum number of bins
        if not self._binning_user_set:
            bin_count = min(10, int(np.sqrt(len(y_data))))
        else:
            bin_count = self.binning_value.value()
        hist, bins = np.histogram(y_data, bin_count)

        text_params = {'mean': '{:.2e}'.format(y_data.mean()),
                       'std': '{:.2e}'.format(y_data.std()),
                       'nan': '{}'.format(np.count_nonzero(np.isnan(y_data)))}

        text = "\n".join(["{}: {}".format(k, text_params[k]) for k in ['mean', 'std', 'nan']])
        # TODO: make the textbox draggable like the legend in line plot
        text_box = offsetbox.TextArea(text)
        anchored_offset_box = offsetbox.AnchoredOffsetbox(loc=1,
                                                          child=text_box)
        self.axes.add_artist(anchored_offset_box)

        width = 0.7 * (bins[1] - bins[0])
        center = (bins[:-1] + bins[1:]) / 2
        self.axes.bar(center, hist, align='center', width=width)

    def _plot_line(self, x_column_name, y_column_name):
        table = self._model.table()
        column_names = table.column_names()
        row_slice = slice(0, table.number_of_rows(), int(self.resample_value.value()))
        y_data = table.get_column_to_array(y_column_name)[row_slice]
        y_dtype = table.column_type(y_column_name)
        if x_column_name in column_names:
            x_data = table.get_column_to_array(x_column_name)[row_slice]
            x_dtype = table.column_type(x_column_name)
            x_attr = table.get_column_attributes(x_column_name)
        else:
            x_data = np.arange(len(y_data))
            x_dtype = x_data.dtype
            x_attr = {}
        if len(x_data) == len(y_data):
            xdate = x_dtype.kind == 'M'
            ydate = y_dtype.kind == 'M'
            if xdate or ydate:
                if xdate:
                    x_data = x_data.astype(datetime)
                if ydate:
                    y_data = y_data.astype(datetime)
                self.axes.plot_date(x_data, y_data,
                                    'o', label=y_column_name,
                                    xdate=xdate, ydate=ydate)
                if xdate:
                    self.axes.get_figure().autofmt_xdate()
            else:
                self.axes.plot(x_data, y_data, 'o', label=y_column_name)
            unit = x_attr.get('unit', None)
            x_label = unicode(x_column_name)
            if unit is not None:
                x_label += u' [{}]'.format(unit)
            self.axes.set_xlabel(x_label)

    def _x_selection_changed(self, idx):
        self._update_plot_timer.start()

    def _y_selection_changed(self, idx):
        self._update_plot_timer.start()

    def _resample_value_changed(self, idx):
        self._update_plot_timer.start()

    def _binning_value_changed(self, idx):
        self._binning_user_set = True
        self._update_plot_timer.start()

    def _update_x_combobox(self):
        column_names = self._model.column_names()
        table = self._model.table()
        excluded_type_kinds = ['S', 'U']
        column_names = [name for name in column_names
                        if table.column_type(name).kind not in excluded_type_kinds]
        column_names = ['(index)'] + column_names
        current_selection = self.x_value.currentText()
        self.x_value.clear()
        self.x_value.addItems(column_names)
        idx = 0
        if current_selection in column_names:
            idx = column_names.index(current_selection)
        self.x_value.setCurrentIndex(idx)

    def _update_y_combobox(self):
        column_names = self._model.column_names()
        table = self._model.table()
        excluded_type_kinds = ['S', 'U', 'M']
        column_names = [name for name in column_names
                        if table.column_type(name).kind not in excluded_type_kinds]
        current_selection = self.y_value.checkedItemNames()
        current_text = self.y_value.currentText()
        self.y_value.clear()
        for name in column_names:
            checked = name in current_selection
            self.y_value.add_item(name, checked)
        idx = 0
        if current_text in column_names:
            idx = column_names.index(current_text)
        self.y_value.setCurrentIndex(idx)

    def _update_signal_comboboxes(self):
        self._update_x_combobox()
        self._update_y_combobox()

    def _on_show_line(self):
        self.show_line_action.setChecked(True)
        self.binning_action.setVisible(False)
        if not self._line_plot_active:
            row_idx = self.x_value.findText('(index)')
            if row_idx == -1:
                self.x_value.insertItem(0, '(index)')
            for i in xrange(self._x_model.rowCount()):
                item = self._x_model.item(i)
                item.setEnabled(True)
            if self.x_value.findText(self._selected_x_cache) > -1:
                current_text = self._selected_x_cache
            else:
                current_text = self._model.column_names()[0]
            idx = self.x_value.findText(current_text)
            self.x_value.setCurrentIndex(idx)
            self.x_label.setText('X:')
            self.x_value.setToolTip('Select the column used for the x values')

        self._line_plot_active = True
        self._update_plot()

    def _on_show_hist(self):
        self.show_hist_action.setChecked(True)
        self.binning_action.setVisible(True)
        if self._line_plot_active:
            self._selected_x_cache = self.x_value.currentText()
            row_idx = self.x_value.findText('(index)')
            if row_idx > -1:
                self.x_value.removeItem(row_idx)

            for i in xrange(self._x_model.rowCount()):
                item = self._x_model.item(i)
                column_name = item.text()
                column_type = self._model.table().column_type(column_name)
                if column_type.kind in ['S', 'U', 'M']:
                    item.setEnabled(False)

            current_y_text = self.y_value.currentText()
            item_idx = self.x_value.findText(current_y_text)
            idx = item_idx if item_idx != -1 else 0
            self.x_value.setCurrentIndex(idx)
            self.x_label.setText('Histogram:')
            self.x_value.setToolTip('Select the column to show histogram and statistics for.')

        self._line_plot_active = False
        self._update_plot()

    def add_column_to_plot(self, column_name, as_y=True):
        # idx = self._model.column_names().index(column_name)
        if as_y:
            items = self._y_model.findItems(column_name)
            if len(items):
                idx = items[0].row()
                self.y_value.set_checked_state(idx, True)
            else:
                idx = -1
            self.y_value.setCurrentIndex(idx)
        else:
            items = self._x_model.findItems(column_name)
            if len(items):
                idx = items[0].row()
            else:
                idx = -1
            # plus 1 to current x value since we auto generate an (index) column
            self.x_value.setCurrentIndex(idx)
        self._on_show_line()

    def show_stats_for(self, column_name):
        if self._line_plot_active:
            items = self._y_model.findItems(column_name)
            if len(items):
                column_idx = items[0].row()
            else:
                column_idx = -1
            self.y_value.setCurrentIndex(column_idx)
        else:
            items = self._x_model.findItems(column_name)
            if len(items):
                column_idx = items[0].row()
            else:
                column_idx = -1
            self.x_value.setCurrentIndex(column_idx)
        self._on_show_hist()

    def set_max_data_points(self, value):
        self._max_data_points = int(value)

    def update_model(self, model):
        self._model = model
        # compute a staring value for re-sampling so the
        # number of points per line is not above self._max_data_points
        rows = self._model.rowCount(None)
        if rows > self._max_data_points:
            start_resample_value = int(round(rows / float(self._max_data_points)))
            self.resample_value.setValue(start_resample_value)
        else:
            self.resample_value.setValue(1)

        if (self._model.table() is not None and
                    self._model.table().number_of_rows() > self._large_data_limit):
            self.large_data_action.setVisible(True)
        else:
            self.large_data_action.setVisible(False)
        self._update_signal_comboboxes()
        self._update_plot()
예제 #10
0
class MeshPlot(QtGui.QWidget):
    """
    plotting the mesh
    """    
    
    def __init__(self):
        super(MeshPlot, self).__init__()
        
        self.subplot_right = .99
        self.subplot_left = .12
        self.subplot_top = .92
        self.subplot_bottom = .1
        self.subplot_hspace = .3
        self.subplot_wspace = .3
        
        self.station_marker = 'v'
        self.marker_color = 'b'
        self.marker_size =  2
        
        self.line_color =  'k'
        self.line_width =  .5
        
        self.fs = 10
        
        self.line_mode = 'add_h'
        self._ax = None
        
        self.model_obj = None
        
        self.setup_ui()
        
    def setup_ui(self):
               
        
        self.figure = Figure(dpi=150)
        self.figure.subplots_adjust(left=self.subplot_left,
                                    right=self.subplot_right,
                                    bottom=self.subplot_bottom,
                                    top=self.subplot_top,
                                    hspace=self.subplot_hspace,
                                    wspace=self.subplot_wspace)
        
        
        self.mpl_widget = FigureCanvas(self.figure)

        self.mpl_widget.mpl_connect('pick_event', self.on_pick)
        self.mpl_widget.mpl_connect('axes_enter_event', self.in_axes)
                                     
        self.mpl_widget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                     QtGui.QSizePolicy.Expanding)
        screen = QtGui.QDesktopWidget().screenGeometry()
        self.mpl_widget.setMinimumWidth(screen.width()*(1600./1920))

        self.mpl_toolbar = NavigationToolbar(self.mpl_widget, self)
        
        
        ## --> buttons for removing, adding lines
        self.line_add_h_button = QtGui.QPushButton("Add Horizontal Line")
        self.line_add_h_button.pressed.connect(self.line_set_add_h)
        
        self.line_add_v_button = QtGui.QPushButton("Add Vertical Line")
        self.line_add_v_button.pressed.connect(self.line_set_add_v)
        
        self.line_del_h_button = QtGui.QPushButton("Remove Horizontal Line")
        self.line_del_h_button.pressed.connect(self.line_set_del_h)
        
        self.line_del_v_button = QtGui.QPushButton("Remove Vertical Line")
        self.line_del_v_button.pressed.connect(self.line_set_del_v)
        
        # set the layout for the plot
        line_layout = QtGui.QHBoxLayout()
        line_layout.addWidget(self.line_add_h_button)
        line_layout.addWidget(self.line_add_v_button)
        line_layout.addWidget(self.line_del_h_button)
        line_layout.addWidget(self.line_del_v_button)
        
        mpl_vbox = QtGui.QVBoxLayout()
        mpl_vbox.addWidget(self.mpl_toolbar)
        mpl_vbox.addWidget(self.mpl_widget)
        mpl_vbox.addLayout(line_layout)
        
        self.setLayout(mpl_vbox)
        
        self.mpl_widget.updateGeometry()
        
    def line_set_add_h(self):
        self.line_mode = 'add_h'
        self.line_add_h_button.setStyleSheet("background-color: red")
        self.line_add_v_button.setStyleSheet("background-color: None")
        self.line_del_h_button.setStyleSheet("background-color: None")
        self.line_del_v_button.setStyleSheet("background-color: None")
    
    def line_set_add_v(self):
        self.line_mode = 'add_v'
        self.line_add_h_button.setStyleSheet("background-color: None")
        self.line_add_v_button.setStyleSheet("background-color: red")
        self.line_del_h_button.setStyleSheet("background-color: None")
        self.line_del_v_button.setStyleSheet("background-color: None")
    
    def line_set_del_h(self):
        self.line_mode = 'del_h'
        self.line_add_h_button.setStyleSheet("background-color: None")
        self.line_add_v_button.setStyleSheet("background-color: None")
        self.line_del_h_button.setStyleSheet("background-color: red")
        self.line_del_v_button.setStyleSheet("background-color: None")
    
    def line_set_del_v(self):
        self.line_mode = 'del_v'
        self.line_add_h_button.setStyleSheet("background-color: None")
        self.line_add_v_button.setStyleSheet("background-color: None")
        self.line_del_h_button.setStyleSheet("background-color: None")
        self.line_del_v_button.setStyleSheet("background-color: red")
        
    
    def plot_mesh(self, model_obj, east_limits=None, north_limits=None, 
                  z_limits=None):
                      
        self.model_obj = model_obj
                      
        try:
            self.model_obj.make_mesh()
        except AttributeError:
            QtGui.QMessageBox.warning(self,
                                      'Cannot Make Mesh -- Need EDI Files',
                                      "Please press the 'Get EDI Files' button to get files", 
                                      QtGui.QMessageBox.Cancel)
            return
            
        
        self.figure.clf()
        
        #make a rotation matrix to rotate data
        #cos_ang = np.cos(np.deg2rad(self.mesh_rotation_angle))
        #sin_ang = np.sin(np.deg2rad(self.mesh_rotation_angle))
        
        #turns out ModEM has not accomodated rotation of the grid, so for
        #now we will not rotate anything.
        cos_ang = 1
        sin_ang = 0
        
        gs = gridspec.GridSpec(1, 2, width_ratios=[10, 1])
        
        #--->plot map view    
        self.ax_map = self.figure.add_subplot(gs[0], aspect='equal')
        
        
        #plot station locations
        station_plot_east = self.model_obj.station_locations['rel_east']/1000.
        station_plot_north = self.model_obj.station_locations['rel_north']/1000.
        
        self.plot_grid_east = self.model_obj.grid_east.copy()/1000.
        self.plot_grid_north = self.model_obj.grid_north.copy()/1000.
        self.plot_grid_z = self.model_obj.grid_z.copy()/1000.
        
        self.ax_map.scatter(station_plot_east,
                            station_plot_north, 
                            marker=self.station_marker,
                            c=self.marker_color,
                            s=self.marker_size,
                            picker=3)
                                
        
        # plot vertical lines
        east_line_xlist = []
        east_line_ylist = []   
        north_min = self.plot_grid_north.min()         
        north_max = self.plot_grid_north.max()         
        for xx in self.plot_grid_east:
            east_line_xlist.extend([xx*cos_ang+north_min*sin_ang, 
                                    xx*cos_ang+north_max*sin_ang])
            east_line_xlist.append(None)
            east_line_ylist.extend([-xx*sin_ang+north_min*cos_ang, 
                                    -xx*sin_ang+north_max*cos_ang])
            east_line_ylist.append(None)
        self.ax_map.plot(east_line_xlist,
                         east_line_ylist,
                         lw=self.line_width,
                         color=self.line_color,
                         picker=3)

        north_line_xlist = []
        north_line_ylist = [] 
        east_max = self.plot_grid_east.max()
        east_min = self.plot_grid_east.min()
        for yy in self.plot_grid_north:
            north_line_xlist.extend([east_min*cos_ang+yy*sin_ang,
                                     east_max*cos_ang+yy*sin_ang])
            north_line_xlist.append(None)
            north_line_ylist.extend([-east_min*sin_ang+yy*cos_ang, 
                                     -east_max*sin_ang+yy*cos_ang])
            north_line_ylist.append(None)
        self.ax_map.plot(north_line_xlist,
                         north_line_ylist,
                         lw=self.line_width,
                         color=self.line_color,
                         picker=3)
        
        if east_limits == None:
            self.ax_map.set_xlim(self.plot_grid_east.min(),
                                 self.plot_grid_east.max())
            pass
        else:
            self.ax_map.set_xlim(east_limits)
        
        if north_limits == None:
            self.ax_map.set_ylim(self.plot_grid_north.min(),
                                 self.plot_grid_north.max())
            pass
        else:
            self.ax_map.set_ylim(north_limits)
            
        self.ax_map.set_ylabel('Northing (km)', 
                               fontdict={'size':12, 'weight':'bold'})
        self.ax_map.set_xlabel('Easting (km)', 
                               fontdict={'size':12, 'weight':'bold'})
        
        ##----plot depth view
        self.ax_depth = self.figure.add_subplot(gs[1], aspect='auto')
        

        #plot the grid 
        east_line_xlist = []
        east_line_ylist = []            
        for xx in self.plot_grid_east:
            east_line_xlist.extend([xx, xx])
            east_line_xlist.append(None)
            east_line_ylist.extend([0, 
                                    self.plot_grid_z.max()])
            east_line_ylist.append(None)
            
        self.ax_depth.plot(east_line_xlist,
                           east_line_ylist,
                           lw=self.line_width,
                           color=self.line_color,
                           picker=5)

        z_line_xlist = []
        z_line_ylist = [] 
        for zz in self.plot_grid_z:
            z_line_xlist.extend([self.plot_grid_east.min(),
                                 self.plot_grid_east.max()])
            z_line_xlist.append(None)
            z_line_ylist.extend([zz, zz])
            z_line_ylist.append(None)
            
        self.ax_depth.plot(z_line_xlist,
                           z_line_ylist,
                           lw=self.line_width,
                           color=self.line_color,
                           picker=3)
                      
        
        #--> plot stations
        self.ax_depth.scatter(station_plot_east,
                              [0]*model_obj.station_locations.shape[0],
                                marker=self.station_marker,
                                c=self.marker_color,
                                s=self.marker_size,
                                picker=3)

        
        if z_limits == None:
            self.ax_depth.set_ylim(model_obj.z_target_depth/1000., -1)
        else:
            self.ax_depth.set_ylim(z_limits)
            
        self.ax_depth.set_xlim(-model_obj.cell_size_east/1000*.75, 
                               model_obj.cell_size_east/1000*.75)
        plt.setp(self.ax_depth.xaxis.get_ticklabels(), visible=False)
            
        self.ax_depth.set_ylabel('Depth (km)', fontdict={'size':9, 'weight':'bold'})
#        self.ax_depth.set_xlabel('Easting (m)', fontdict={'size':9, 'weight':'bold'})  
        
        self.mpl_widget.draw()
        
    def on_pick(self, event):
        """
        mask a data point when it is clicked on.  
        """         

        
#        for ii in dir(event.mouseevent):
#            print ii
        if event.mouseevent.button == 1:
            if self.line_mode == 'add_h' and self._ax == self.ax_map:
                data_point = event.mouseevent

                north = np.round(float(data_point.ydata)*1000., -2)

                self.model_obj.grid_north = np.append(self.model_obj.grid_north,
                                                      north)
                self.model_obj.grid_north.sort()
                self.ax_map.plot([self.plot_grid_east.min(), 
                                  self.plot_grid_east.max()],
                                 [north/1000., north/1000.],
                                 lw=self.line_width,
                                 color='r',
                                 picker=3)
                                 
            elif self.line_mode == 'add_h' and self._ax == self.ax_depth:
                data_point = event.mouseevent

                depth = np.round(float(data_point.ydata)*1000., -2)

                self.model_obj.grid_z = np.append(self.model_obj.grid_z,
                                                  depth)
                self.model_obj.grid_z.sort()
                self.ax_depth.plot([self.plot_grid_east.min(), 
                                   self.plot_grid_east.max()],
                                 [depth/1000., depth/1000.],
                                 lw=self.line_width,
                                 color='r',
                                 picker=3)
                                 
            elif self.line_mode == 'add_v' and self._ax == self.ax_map:
                data_point = event.mouseevent

                east = np.round(float(data_point.xdata)*1000, -2)
                
                self.model_obj.grid_east = np.append(self.model_obj.grid_east,
                                                     east)
                self.model_obj.grid_east.sort()
                self.ax_map.plot([east/1000., east/1000.],
                                 [self.plot_grid_north.min(),
                                  self.plot_grid_north.max()],
                                 lw=self.line_width,
                                 color='r',
                                 picker=3)
                                 
            elif self.line_mode == 'del_h' and self._ax == self.ax_map:
                data_point = event.artist
                east = data_point.get_xdata()[event.ind]*1000.
                north = data_point.get_ydata()[event.ind]*1000.
                
                new_ii = np.where(self.model_obj.grid_east != east)
                self.model_obj.grid_east = self.model_obj.grid_east[new_ii]
                self.ax_map.plot([self.plot_grid_east.min(), 
                                  self.plot_grid_east.max()],
                                 [north/1000., north/1000.],
                                 lw=self.line_width,
                                 color='w',
                                 picker=3) 
                                 
            elif self.line_mode == 'del_v' and self._ax == self.ax_depth:
                data_point = event.artist
                east = data_point.get_xdata()[event.ind]*1000.
                depth = data_point.get_ydata()[event.ind]*1000.
                
                new_ii = np.where(self.model_obj.grid_z != depth)
                self.model_obj.grid_z = self.model_obj.grid_z[new_ii]
                self.ax_map.plot([self.plot_grid_east.min(), 
                                  self.plot_grid_east.max()],
                                 [depth/1000., depth/1000.],
                                 lw=self.line_width,
                                 color='w',
                                 picker=3) 
                                 
            elif self.line_mode == 'del_v' and self._ax == self.ax_map:
                data_point = event.artist
                east = data_point.get_xdata()[event.ind]*1000.
                north = data_point.get_ydata()[event.ind]*1000.
                
                new_ii = np.where(self.model_obj.grid_north != north)
                self.model_obj.grid_north = self.model_obj.grid_north[new_ii]
                self.ax_map.plot([east/1000., east/1000.],
                                 [self.plot_grid_north.min(),
                                  self.plot_grid_north.max()],
                                 lw=self.line_width,
                                 color='w',
                                 picker=3) 
        
        self._ax.figure.canvas.draw()

    def in_axes(self, event):
        self._ax = event.inaxes