├── README.md ├── README.md~ ├── Pivot_Tables_Pandas_2014_07_18_GUI_V3_beta.py~ └── Pivot_Tables_Pandas_2014_07_18_GUI_V3_beta.py /README.md: -------------------------------------------------------------------------------- 1 | NOTE - this software is not YET generalized. I will release a fully-working version in the near future. Stay tuned... 2 | 3 | Description: Tool to create pivot tables and make figures, using python and pandas. 4 | 5 | - [ ] Rename match excel convention - filters, columns, rows, values 6 | - [ ] Add filter capability for pivot tables. 7 | - [ ] Ability to change y-axis values in real-time. 8 | - [x] Add list widget - show what you have plotted previously. 9 | - [x] Remove all MPL figures that are real-time. 10 | - [x] Fix it so that every time new file is open, it does not create 3 new tabs. 11 | - [x] Fix how the Plot legend displays (text overlaps) 12 | - [x] Fix how plot legend overwrites old legends (make it clear). 13 | - [x] Fix combo box values that repeat 14 | - [x] Make the check marks display better - use a grid pattern. 15 | - [x] Make real-time plot display, with tabbed interface in GUI. 16 | - [x] Label x-axis in plots. 17 | - [x] Fix axes labeling. 18 | - [x] filled symbols with symbolBrush. 19 | -------------------------------------------------------------------------------- /README.md~: -------------------------------------------------------------------------------- 1 | NOTE - this software is not YET generalized. I will release a fully-working version in the near future. Stay tuned... 2 | 3 | Description: Tool to create pivot tables and make figures, using python and pandas. 4 | 5 | - [ ] Rename match excel convention - filters, columns, rows, values 6 | - [ ] Add filter capability for pivot tables. 7 | - [ ] Ability to change y-axis values in real-time. 8 | - [x] Add list widget - show what you have plotted previously. 9 | - [x] Remove all MPL figures that are real-time. 10 | - [x] Fix it so that every time new file is open, it does not create 3 new tabs. 11 | - [x] Fix how the Plot legend displays (text overlaps) 12 | - [x] Fix how plot legend overwrites old legends (make it clear). 13 | - [x] Fix combo box values that repeat 14 | - [x] Make the check marks display better - use a grid pattern. 15 | - [x] Make real-time plot display, with tabbed interface in GUI. 16 | - [x] Label x-axis in plots. 17 | - [x] Fix axes labeling. 18 | - [x] filled symbols with symbolBrush. 19 | -------------------------------------------------------------------------------- /Pivot_Tables_Pandas_2014_07_18_GUI_V3_beta.py~: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: mdb52 4 | """ 5 | 6 | from __future__ import division 7 | 8 | # These allow mpl in PyQt 9 | from PyQt4.QtGui import QSizePolicy 10 | from PyQt4.QtCore import QSize 11 | 12 | import numpy as np 13 | import seaborn as sb 14 | from pylab import * 15 | import pandas as pd 16 | import itertools 17 | import matplotlib._pylab_helpers 18 | from PyQt4 import * 19 | 20 | import pyqtgraph as pg 21 | 22 | """ 23 | This loads CSV of all fiber data and plots various parameters from pivot tables 24 | 25 | Must use SELF.COMMAND when you want to access that value outside of the function (gets stored to the class) 26 | 27 | GUI V1: beta just barely works 28 | V2: improving the "Real Time capability" 29 | V3: uses pyqtplot -- for real time plot, and fixed GUI layout 30 | started using GIT and GIT-HUB 31 | 32 | """ 33 | 34 | def setSeabornParams(): 35 | # Talk seems to be best choice for font size 36 | sb.set_context("talk") 37 | 38 | # use "cubehelix" colormap for printing; hls is used for SB 39 | # sb.palplot(sb.color_palette("jet", 8)) 40 | sb.set_palette(sb.color_palette("jet", 8)) 41 | sb.set_palette("jet",8) 42 | 43 | def loadData(fname): 44 | data = pd.read_csv(fname) 45 | return data; 46 | 47 | def filterGoodValues(data): 48 | print('Size before filtering: '+repr(np.shape(data))) 49 | print('FILTERING PERFORMED') 50 | # Remove rows that have yes in either column: 51 | # 'Not a new calibration?' and 'Diode Measured Scatter or Cerenov?' 52 | data = data[data.loc[:,'Not a new calibration?'] != 'Yes'] 53 | data = data[data.loc[:,'Diode Measured Scatter or Cerenkov?'] != 'Yes'] 54 | print('Size after filtering: '+repr(np.shape(data))) 55 | return data 56 | 57 | def plotBoxValues(data, value_list, row, col, showMPL): 58 | for xx in value_list: 59 | #Make a pivot table for every value 60 | 61 | table1 = pd.pivot_table(data, values=xx, 62 | rows=row, cols=col, dropna=True) 63 | 64 | # drop if all data is missing in an axis 65 | print('Size before removing nan: '+repr(np.shape(table1))) 66 | table1 = table1.dropna(axis=0, how='all') 67 | table1 = table1.dropna(axis=1, how='all') 68 | print('Size after removing nan: '+repr(np.shape(table1))) 69 | 70 | if showMPL == True: 71 | 72 | # GET N 73 | N_table1 = table1.count(axis=0) 74 | N_table1_T = table1.count(axis=1) 75 | 76 | # Get Avg 77 | meanX = table1.mean() 78 | meanY = table1.T.mean() 79 | 80 | print('Mean x, y: ' + repr(meanX) + ', ' + repr(meanY)) 81 | 82 | p1=figure(figsize=(11,8)) 83 | sb.set_palette("jet",8) 84 | table1.boxplot() 85 | title(xx + ' By '+col) 86 | yscale('log') 87 | xlabel(col, fontsize=12, fontweight='bold') 88 | 89 | locs, labels = xticks() 90 | ymin, ymax = ylim() 91 | 92 | for index in range(len(locs)): 93 | text(locs[index], 1.2*ymin, 'N: '+repr(N_table1.iloc[index]), 94 | horizontalalignment='center') 95 | text(locs[index], 2*ymin, '$\\bar{x}$: ' +'%.2g'%meanX.iloc[index], 96 | horizontalalignment='center') 97 | 98 | 99 | p2=figure(figsize=(11,8)) 100 | sb.set_palette("jet",8) 101 | table1.T.boxplot() 102 | title(xx + ' By '+row) 103 | yscale('log') 104 | xticks(rotation=90) 105 | xlabel(row, fontsize=12, fontweight='bold') 106 | 107 | locs, labels = xticks() 108 | ymin, ymax = ylim() 109 | 110 | for index in range(len(locs)): 111 | text(locs[index], 1.2*ymin, 'N: '+repr(N_table1_T.iloc[index]), 112 | horizontalalignment='center') 113 | 114 | text(locs[index], 2*ymin, '$\\bar{x}$: ' +'%.2g'%meanY.iloc[index], 115 | horizontalalignment='center') 116 | show() 117 | 118 | return table1; 119 | 120 | class Table(QtGui.QDialog): 121 | def __init__(self, parent=None): 122 | super(Table, self).__init__(parent) 123 | layout = QtGui.QGridLayout() 124 | self.table = QtGui.QTableWidget(self) # Parent of table 125 | layout.addWidget(self.table, 0, 0) 126 | self.setLayout(layout) 127 | 128 | class MainWindow(QtGui.QMainWindow): 129 | 130 | def __init__(self): 131 | super(MainWindow, self).__init__() 132 | 133 | self.initUI() 134 | 135 | self.loadedData = [] 136 | self.filteredData = [] 137 | self.checkBoxList = [] 138 | self.pivotData = [] 139 | 140 | def setLoadedData(self, setValue): 141 | self.loadedData = setValue 142 | 143 | def setFilteredData(self, setValue): 144 | self.filteredData = setValue 145 | 146 | def setPivotData(self, setValue): 147 | self.pivotData = setValue 148 | 149 | def initUI(self): 150 | 151 | self.setWindowTitle('Main Program') 152 | 153 | exitAction = QtGui.QAction(QtGui.QIcon('exit.png'), '&Exit', self) 154 | exitAction.triggered.connect(QtGui.qApp.quit) 155 | 156 | self.statusBar() 157 | 158 | # For tabbed widgets, do not specify a parent 159 | mainWidget = QtGui.QWidget() 160 | 161 | # Quit Button 162 | btn_quit = QtGui.QPushButton('Quit', mainWidget) 163 | btn_quit.clicked.connect(QtCore.QCoreApplication.instance().quit) 164 | btn_quit.setToolTip('This is a QPushButton widget') 165 | btn_quit.resize(btn_quit.sizeHint()) 166 | 167 | # Plot data button 168 | btnPlot = QtGui.QPushButton('Plot Data', mainWidget) 169 | btnPlot.setToolTip('This will plot the Displayed Data') 170 | btnPlot.resize(btnPlot.sizeHint()) 171 | 172 | btnFilter = QtGui.QPushButton('Filter Data, Make Pivot', mainWidget) 173 | btnFilter.setToolTip('You can remove types of data from analysis here') 174 | btnFilter.resize(btnFilter.sizeHint()) 175 | 176 | # LOAD DATA AND SAVE TO A VARIABLE 177 | openFile = QtGui.QAction(QtGui.QIcon('open.png'), 'Open', mainWidget) 178 | openFile.setShortcut('Ctrl+O') 179 | openFile.setStatusTip('Open new File') 180 | openFile.triggered.connect(self.openFileDialog) 181 | 182 | # Define what happens when buttons are clicked 183 | btnFilter.clicked.connect(self.filterClicked) 184 | btnPlot.clicked.connect(self.plotClicked) 185 | 186 | # make a list of values already plotted 187 | self.listPlotted = QtGui.QListWidget() 188 | self.listPlotted.resize(256,192) 189 | 190 | 191 | # Drop down select combo box 192 | lbl1 = QtGui.QLabel('Series', mainWidget) 193 | self.combo = QtGui.QComboBox(mainWidget) 194 | 195 | # Drop down select combo box 196 | lbl2 = QtGui.QLabel('X-Axis', mainWidget) 197 | self.combo2 = QtGui.QComboBox(mainWidget) 198 | 199 | # Troubleshooting print button 200 | btn_test = QtGui.QPushButton('Troubleshoot', mainWidget) 201 | btn_test.resize(btn_test.sizeHint()) 202 | btn_test.clicked.connect(self.troubleshootClicked) 203 | 204 | # Check box to show MPL figures in addition to real time 205 | self.checkMPL = QtGui.QCheckBox("Enable MPL") 206 | 207 | # Plot Widget 208 | self.plotWindow = pg.PlotWidget() 209 | self.plotWindow.resize(self.plotWindow.sizeHint()) 210 | 211 | # Grid LAYOUT 4 rows, 8 columns 212 | nRows = 8; nCols = 12 213 | layout = QtGui.QGridLayout() 214 | # addItem (self, QLayoutItem item, int row, 215 | # int column, int rowSpan = 1, int columnSpan = 1, Qt.Alignment alignment = 0) 216 | layout.addWidget(btn_test, 0, 0) # Goes in upper left 217 | layout.addWidget(btnFilter, 1, 0) # Goes in middle left 218 | layout.addWidget(btnPlot, 2, 0) 219 | layout.addWidget(btn_quit, nRows, 0) # Bottom left 220 | layout.addWidget(self.checkMPL, 3, 0) 221 | layout.addWidget(lbl1, 4, 1) 222 | layout.addWidget(self.combo, 4, 0) 223 | layout.addWidget(lbl2, 5, 1) 224 | layout.addWidget(self.combo2, 5, 0) 225 | layout.addWidget(self.listPlotted, 6, 0, 1, 2) 226 | layout.addWidget(self.plotWindow, 0, 2, nRows, nCols) 227 | 228 | mainWidget.setLayout(layout) 229 | 230 | # Add a tab bar with widgets (tab 1 is options and figure, tab 2 is table) 231 | self.tabBar = QtGui.QTabWidget(self) 232 | self.tabBar.addTab(mainWidget, "Plot Settings") 233 | 234 | # Add MENU Bar - goes mainWindow 235 | menuBar = self.menuBar() 236 | fileMenu = menuBar.addMenu('&File') 237 | fileMenu.addAction(openFile) 238 | fileMenu.addAction(exitAction) 239 | 240 | # SET Tabbed WIDGET AS CENTRAL 241 | self.setCentralWidget(self.tabBar) 242 | 243 | self.setGeometry(50, 50, 1200, 600) # x,y for corner and then x-y widths 244 | self.show() 245 | 246 | def plotReal(self, axes): 247 | self.plotWindow.clear() # refresh if old data is here 248 | print(np.asarray(self.pivotData)) 249 | xVals = self.pivotData.columns.tolist() 250 | xVals = [str(x) for x in xVals] 251 | yVals = self.pivotData.index.tolist() 252 | yVals = [str(x) for x in yVals] 253 | 254 | 255 | print('x: '+repr(xVals)) 256 | print('y: '+repr(yVals)) 257 | 258 | # Delete any old legends 259 | try: 260 | legend = self.plotWindow.plotItem.legend 261 | legend.scene().removeItem(legend) 262 | except Exception, err: 263 | print('Error: '+repr(err)) 264 | pass 265 | self.plotWindow.addLegend((100,100)) # This must go above the plot calls 266 | colorValues = ['r','g','b','c','m','y','k','w'] 267 | colorCycles = itertools.cycle(colorValues) 268 | for ind, each in enumerate(np.asarray(self.pivotData)): 269 | color = colorCycles.next() 270 | self.plotWindow.plot(each, name=yVals[ind], symbol='o', symbolPen = color, pen =color, symbolBrush = color) 271 | 272 | self.plotWindow.setLabel('left', self.valuePlot) 273 | self.plotWindow.setLabel('bottom', self.combo2.currentText()) 274 | 275 | # Make tick labels 276 | xAxis = self.plotWindow.getAxis('bottom') 277 | newTicks = zip(range(len(xVals)), (xVals)) 278 | print('New Ticks: '+repr(newTicks)) 279 | # xAxis.setStyle(autoExpandTextSpace = 1) # not out until version 0.9.9 280 | xAxis.setTicks([newTicks]) # 281 | 282 | 283 | def troubleshootClicked(self): 284 | print('Combo text value: '+repr(str(self.combo.currentText()))) 285 | listDataToPlot = [] 286 | for index, each in enumerate(self.checkBoxList): 287 | if each.checkState() > 0: 288 | # append a list of indices where boxes are checked! 289 | listDataToPlot.append(index) 290 | print('Indices of Data to Plot from checkboxes: '+repr(listDataToPlot)) 291 | print('These are the text objects: '+str(self.loadedData.columns[listDataToPlot].tolist())) 292 | 293 | def plotClicked(self): 294 | sender = self.sender() 295 | self.statusBar().showMessage(sender.text() + ' was pressed') 296 | 297 | listDataToPlot = [] 298 | 299 | # Check if we are going to enable Matplotlib 300 | if self.checkMPL.checkState() > 0: 301 | MPLFlag = True; 302 | else: 303 | MPLFlag = False 304 | 305 | for index, each in enumerate(self.checkBoxList): 306 | if each.checkState() > 0: 307 | # append a list of indices where boxes are checked! 308 | listDataToPlot.append(index) 309 | 310 | self.valuePlot =self.loadedData.columns[listDataToPlot].tolist() 311 | try: 312 | self.setPivotData( 313 | plotBoxValues(self.filteredData, 314 | self.valuePlot, 315 | str(self.combo.currentText()), str(self.combo2.currentText()), 316 | MPLFlag)) 317 | 318 | 319 | except Exception, err: 320 | errorWin = QtGui.QMessageBox(self) 321 | errorWin.setText('Error: Try Filtering the data first') 322 | errorWin.show() 323 | print('Failed for this reason: ') 324 | print(repr(err)) 325 | pass 326 | 327 | # PLOT FIGURE 328 | self.plotReal(self) 329 | 330 | # Update running list of whats already plotted 331 | self.listPlotted.addItem(self.combo.currentText()+', '+self.combo2.currentText()) 332 | 333 | 334 | def filterClicked(self): 335 | 336 | sender = self.sender() 337 | self.statusBar().showMessage(sender.text() + ' was pressed') 338 | try: 339 | self.setFilteredData(filterGoodValues(self.loadedData)) 340 | except: 341 | errorWin = QtGui.QMessageBox(self) 342 | errorWin.setText('Error: Try loading data first') 343 | errorWin.show() 344 | 345 | def openFileDialog(self): 346 | # SELF IS ALWAYS THE NAME OF THE CLASS 347 | fname = QtGui.QFileDialog.getOpenFileName(self, 'Open file', 348 | '/home') 349 | print('Opening File: '+repr(fname)) 350 | data = loadData(str(fname)) 351 | 352 | # Store the values 353 | self.setLoadedData(data); 354 | 355 | # Create a checkbox WIDGET to store this data 356 | self.checkWidget = QtGui.QWidget() 357 | self.filterWidget = QtGui.QWidget() 358 | 359 | checkWidgetList = [self.checkWidget, self.filterWidget] 360 | nameWidgetList = ["Plot Values", "Filter Values"] 361 | 362 | # Delete the old tabs, if there are more than 3 tabs total now 363 | if self.tabBar.count() >= 4: 364 | # First try to delete existing tabs from previous runs 365 | # Tabs are numbers 1, 2 366 | self.tabBar.removeTab(1) 367 | self.tabBar.removeTab(1) 368 | 369 | # Combo box for FILTERING choices 370 | counts =0; 371 | # Reset any values that may have been set before 372 | try: 373 | del self.checkBoxList[:] 374 | except: 375 | pass 376 | self.combo.clear(); self.combo2.clear(); 377 | for number, widget in enumerate(checkWidgetList): 378 | layout = QtGui.QGridLayout() 379 | for index, each in enumerate(data.columns): 380 | # Fill combo boxes, only once 381 | if number == 1: 382 | self.combo.addItem(each) 383 | self.combo2.addItem(each) 384 | 385 | # Make checkboxes for values - first half belowng to "Plot Values", second half "Filter" 386 | self.checkBoxList.append(QtGui.QCheckBox(each, widget)) 387 | self.checkBoxList[counts].sizeHint() 388 | # make a grid, with 2 columns 389 | layout.addWidget(self.checkBoxList[counts], floor(counts/2), counts % 2) 390 | counts+=1; 391 | 392 | widget.setLayout(layout) 393 | 394 | # add a tab showing these values -- 2 tabs total 395 | self.tabBar.insertTab(number+1, widget, nameWidgetList[number]) 396 | 397 | # Make a TABLE 398 | t = Table() # Do not put a parent here? 399 | t.table.setColumnCount(len(data.columns)) 400 | t.table.setRowCount(len(data.index)) 401 | for i in range(len(data.index)): 402 | for j in range(len(data.columns)): 403 | t.table.setItem(i,j, 404 | QtGui.QTableWidgetItem(str(data.iget_value(i, j)))) 405 | for i, value in enumerate(data.columns): 406 | t.table.setHorizontalHeaderItem(i, QtGui.QTableWidgetItem(str(value))) 407 | 408 | # Show the table 409 | if self.tabBar.count() >= 4: 410 | self.tabBar.removeTab(3) 411 | self.tabBar.addTab(t, "Updated Table") 412 | else: 413 | # Set for first time 414 | self.tabBar.addTab(t, "Table") # Add Table Tab 415 | 416 | 417 | # Message Window 418 | multiPickWin = QtGui.QMessageBox(self) 419 | multiPickWin.setText('You can only choose ONE check box at a time') 420 | multiPickWin.show() 421 | 422 | if __name__ == '__main__': 423 | import sys 424 | app = QtGui.QApplication(sys.argv) 425 | 426 | setSeabornParams() 427 | 428 | w = MainWindow() 429 | 430 | sys.exit(app.exec_()) 431 | 432 | -------------------------------------------------------------------------------- /Pivot_Tables_Pandas_2014_07_18_GUI_V3_beta.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: mdb52 4 | """ 5 | 6 | from __future__ import division 7 | 8 | # These allow mpl in PyQt 9 | from PyQt4.QtGui import QSizePolicy 10 | from PyQt4.QtCore import QSize 11 | 12 | import numpy as np 13 | import seaborn as sb 14 | from pylab import * 15 | import pandas as pd 16 | import itertools 17 | import matplotlib._pylab_helpers 18 | from PyQt4 import * 19 | 20 | import pyqtgraph as pg 21 | 22 | """ 23 | This loads CSV of all fiber data and plots various parameters from pivot tables 24 | 25 | Must use SELF.COMMAND when you want to access that value outside of the function (gets stored to the class) 26 | 27 | GUI V1: beta just barely works 28 | V2: improving the "Real Time capability" 29 | V3: uses pyqtplot -- for real time plot, and fixed GUI layout 30 | started using GIT and GIT-HUB 31 | 32 | """ 33 | 34 | def setSeabornParams(): 35 | # Talk seems to be best choice for font size 36 | sb.set_context("talk") 37 | 38 | # use "cubehelix" colormap for printing; hls is used for SB 39 | # sb.palplot(sb.color_palette("jet", 8)) 40 | sb.set_palette(sb.color_palette("jet", 8)) 41 | sb.set_palette("jet",8) 42 | 43 | def loadData(fname): 44 | data = pd.read_csv(fname) 45 | return data; 46 | 47 | def filterGoodValues(data): 48 | print('Size before filtering: '+repr(np.shape(data))) 49 | print('FILTERING PERFORMED') 50 | # Remove rows that have yes in either column: 51 | # 'Not a new calibration?' and 'Diode Measured Scatter or Cerenov?' 52 | data = data[data.loc[:,'Not a new calibration?'] != 'Yes'] 53 | data = data[data.loc[:,'Diode Measured Scatter or Cerenkov?'] != 'Yes'] 54 | print('Size after filtering: '+repr(np.shape(data))) 55 | return data 56 | 57 | def plotBoxValues(data, value_list, row, col, showMPL): 58 | for xx in value_list: 59 | #Make a pivot table for every value 60 | 61 | table1 = pd.pivot_table(data, values=xx, 62 | rows=row, cols=col, dropna=True) 63 | 64 | # drop if all data is missing in an axis 65 | print('Size before removing nan: '+repr(np.shape(table1))) 66 | table1 = table1.dropna(axis=0, how='all') 67 | table1 = table1.dropna(axis=1, how='all') 68 | print('Size after removing nan: '+repr(np.shape(table1))) 69 | 70 | if showMPL == True: 71 | 72 | # GET N 73 | N_table1 = table1.count(axis=0) 74 | N_table1_T = table1.count(axis=1) 75 | 76 | # Get Avg 77 | meanX = table1.mean() 78 | meanY = table1.T.mean() 79 | 80 | print('Mean x, y: ' + repr(meanX) + ', ' + repr(meanY)) 81 | 82 | p1=figure(figsize=(11,8)) 83 | sb.set_palette("jet",8) 84 | table1.boxplot() 85 | title(xx + ' By '+col) 86 | yscale('log') 87 | xlabel(col, fontsize=12, fontweight='bold') 88 | 89 | locs, labels = xticks() 90 | ymin, ymax = ylim() 91 | 92 | for index in range(len(locs)): 93 | text(locs[index], 1.2*ymin, 'N: '+repr(N_table1.iloc[index]), 94 | horizontalalignment='center') 95 | text(locs[index], 2*ymin, '$\\bar{x}$: ' +'%.2g'%meanX.iloc[index], 96 | horizontalalignment='center') 97 | 98 | 99 | p2=figure(figsize=(11,8)) 100 | sb.set_palette("jet",8) 101 | table1.T.boxplot() 102 | title(xx + ' By '+row) 103 | yscale('log') 104 | xticks(rotation=90) 105 | xlabel(row, fontsize=12, fontweight='bold') 106 | 107 | locs, labels = xticks() 108 | ymin, ymax = ylim() 109 | 110 | for index in range(len(locs)): 111 | text(locs[index], 1.2*ymin, 'N: '+repr(N_table1_T.iloc[index]), 112 | horizontalalignment='center') 113 | 114 | text(locs[index], 2*ymin, '$\\bar{x}$: ' +'%.2g'%meanY.iloc[index], 115 | horizontalalignment='center') 116 | show() 117 | 118 | return table1; 119 | 120 | class Table(QtGui.QDialog): 121 | def __init__(self, parent=None): 122 | super(Table, self).__init__(parent) 123 | layout = QtGui.QGridLayout() 124 | self.table = QtGui.QTableWidget(self) # Parent of table 125 | layout.addWidget(self.table, 0, 0) 126 | self.setLayout(layout) 127 | 128 | class MainWindow(QtGui.QMainWindow): 129 | 130 | def __init__(self): 131 | super(MainWindow, self).__init__() 132 | 133 | self.initUI() 134 | 135 | self.loadedData = [] 136 | self.filteredData = [] 137 | self.checkBoxList = [] 138 | self.pivotData = [] 139 | 140 | def setLoadedData(self, setValue): 141 | self.loadedData = setValue 142 | 143 | def setFilteredData(self, setValue): 144 | self.filteredData = setValue 145 | 146 | def setPivotData(self, setValue): 147 | self.pivotData = setValue 148 | 149 | def initUI(self): 150 | 151 | self.setWindowTitle('Main Program') 152 | 153 | exitAction = QtGui.QAction(QtGui.QIcon('exit.png'), '&Exit', self) 154 | exitAction.triggered.connect(QtGui.qApp.quit) 155 | 156 | self.statusBar() 157 | 158 | # For tabbed widgets, do not specify a parent 159 | mainWidget = QtGui.QWidget() 160 | 161 | # Quit Button 162 | btn_quit = QtGui.QPushButton('Quit', mainWidget) 163 | btn_quit.clicked.connect(QtCore.QCoreApplication.instance().quit) 164 | btn_quit.setToolTip('This is a QPushButton widget') 165 | btn_quit.resize(btn_quit.sizeHint()) 166 | 167 | # Plot data button 168 | btnPlot = QtGui.QPushButton('Plot Data', mainWidget) 169 | btnPlot.setToolTip('This will plot the Displayed Data') 170 | btnPlot.resize(btnPlot.sizeHint()) 171 | 172 | btnFilter = QtGui.QPushButton('Filter Data, Make Pivot', mainWidget) 173 | btnFilter.setToolTip('You can remove types of data from analysis here') 174 | btnFilter.resize(btnFilter.sizeHint()) 175 | 176 | # LOAD DATA AND SAVE TO A VARIABLE 177 | openFile = QtGui.QAction(QtGui.QIcon('open.png'), 'Open', mainWidget) 178 | openFile.setShortcut('Ctrl+O') 179 | openFile.setStatusTip('Open new File') 180 | openFile.triggered.connect(self.openFileDialog) 181 | 182 | # Define what happens when buttons are clicked 183 | btnFilter.clicked.connect(self.filterClicked) 184 | btnPlot.clicked.connect(self.plotClicked) 185 | 186 | # make a list of values already plotted 187 | self.listPlotted = QtGui.QListWidget() 188 | self.listPlotted.resize(256,192) 189 | 190 | 191 | # Drop down select combo box 192 | lbl1 = QtGui.QLabel('Series', mainWidget) 193 | self.combo = QtGui.QComboBox(mainWidget) 194 | 195 | # Drop down select combo box 196 | lbl2 = QtGui.QLabel('X-Axis', mainWidget) 197 | self.combo2 = QtGui.QComboBox(mainWidget) 198 | 199 | # Troubleshooting print button 200 | btn_test = QtGui.QPushButton('Troubleshoot', mainWidget) 201 | btn_test.resize(btn_test.sizeHint()) 202 | btn_test.clicked.connect(self.troubleshootClicked) 203 | 204 | # Check box to show MPL figures in addition to real time 205 | self.checkMPL = QtGui.QCheckBox("Enable MPL") 206 | 207 | # Plot Widget 208 | self.plotWindow = pg.PlotWidget() 209 | self.plotWindow.resize(self.plotWindow.sizeHint()) 210 | 211 | # Grid LAYOUT 4 rows, 8 columns 212 | nRows = 8; nCols = 12 213 | layout = QtGui.QGridLayout() 214 | # addItem (self, QLayoutItem item, int row, 215 | # int column, int rowSpan = 1, int columnSpan = 1, Qt.Alignment alignment = 0) 216 | layout.addWidget(btn_test, 0, 0) # Goes in upper left 217 | layout.addWidget(btnFilter, 1, 0) # Goes in middle left 218 | layout.addWidget(btnPlot, 2, 0) 219 | layout.addWidget(btn_quit, nRows, 0) # Bottom left 220 | layout.addWidget(self.checkMPL, 3, 0) 221 | layout.addWidget(lbl1, 4, 1) 222 | layout.addWidget(self.combo, 4, 0) 223 | layout.addWidget(lbl2, 5, 1) 224 | layout.addWidget(self.combo2, 5, 0) 225 | layout.addWidget(self.listPlotted, 6, 0, 1, 2) 226 | layout.addWidget(self.plotWindow, 0, 2, nRows, nCols) 227 | 228 | mainWidget.setLayout(layout) 229 | 230 | # Add a tab bar with widgets (tab 1 is options and figure, tab 2 is table) 231 | self.tabBar = QtGui.QTabWidget(self) 232 | self.tabBar.addTab(mainWidget, "Plot Settings") 233 | 234 | # Add MENU Bar - goes mainWindow 235 | menuBar = self.menuBar() 236 | fileMenu = menuBar.addMenu('&File') 237 | fileMenu.addAction(openFile) 238 | fileMenu.addAction(exitAction) 239 | 240 | # SET Tabbed WIDGET AS CENTRAL 241 | self.setCentralWidget(self.tabBar) 242 | 243 | self.setGeometry(50, 50, 1200, 600) # x,y for corner and then x-y widths 244 | self.show() 245 | 246 | def plotReal(self, axes): 247 | self.plotWindow.clear() # refresh if old data is here 248 | print(np.asarray(self.pivotData)) 249 | xVals = self.pivotData.columns.tolist() 250 | xVals = [str(x) for x in xVals] 251 | yVals = self.pivotData.index.tolist() 252 | yVals = [str(x) for x in yVals] 253 | 254 | 255 | print('x: '+repr(xVals)) 256 | print('y: '+repr(yVals)) 257 | 258 | # Delete any old legends 259 | try: 260 | legend = self.plotWindow.plotItem.legend 261 | legend.scene().removeItem(legend) 262 | except Exception, err: 263 | print('Error: '+repr(err)) 264 | pass 265 | self.plotWindow.addLegend((100,100)) # This must go above the plot calls 266 | colorValues = ['r','g','b','c','m','y','k','w'] 267 | colorCycles = itertools.cycle(colorValues) 268 | for ind, each in enumerate(np.asarray(self.pivotData)): 269 | color = colorCycles.next() 270 | self.plotWindow.plot(each, name=yVals[ind], symbol='o', symbolPen = color, pen =color, symbolBrush = color) 271 | 272 | self.plotWindow.setLabel('left', self.valuePlot[0]) 273 | self.plotWindow.setLabel('bottom', self.combo2.currentText()) 274 | 275 | # Make tick labels 276 | xAxis = self.plotWindow.getAxis('bottom') 277 | newTicks = zip(range(len(xVals)), (xVals)) 278 | print('New Ticks: '+repr(newTicks)) 279 | # xAxis.setStyle(autoExpandTextSpace = 1) # not out until version 0.9.9 280 | xAxis.setTicks([newTicks]) # 281 | 282 | 283 | def troubleshootClicked(self): 284 | print('Combo text value: '+repr(str(self.combo.currentText()))) 285 | listDataToPlot = [] 286 | for index, each in enumerate(self.checkBoxList): 287 | if each.checkState() > 0: 288 | # append a list of indices where boxes are checked! 289 | listDataToPlot.append(index) 290 | print('Indices of Data to Plot from checkboxes: '+repr(listDataToPlot)) 291 | print('These are the text objects: '+str(self.loadedData.columns[listDataToPlot].tolist())) 292 | 293 | def plotClicked(self): 294 | sender = self.sender() 295 | self.statusBar().showMessage(sender.text() + ' was pressed') 296 | 297 | listDataToPlot = [] 298 | 299 | # Check if we are going to enable Matplotlib 300 | if self.checkMPL.checkState() > 0: 301 | MPLFlag = True; 302 | else: 303 | MPLFlag = False 304 | 305 | for index, each in enumerate(self.checkBoxList): 306 | if each.checkState() > 0: 307 | # append a list of indices where boxes are checked! 308 | listDataToPlot.append(index) 309 | 310 | self.valuePlot =self.loadedData.columns[listDataToPlot].tolist() 311 | try: 312 | self.setPivotData( 313 | plotBoxValues(self.filteredData, 314 | self.valuePlot, 315 | str(self.combo.currentText()), str(self.combo2.currentText()), 316 | MPLFlag)) 317 | 318 | 319 | except Exception, err: 320 | errorWin = QtGui.QMessageBox(self) 321 | errorWin.setText('Error: Try Filtering the data first') 322 | errorWin.show() 323 | print('Failed for this reason: ') 324 | print(repr(err)) 325 | pass 326 | 327 | # PLOT FIGURE 328 | self.plotReal(self) 329 | 330 | # Update running list of whats already plotted 331 | self.listPlotted.addItem(self.combo.currentText()+', '+self.combo2.currentText()) 332 | 333 | 334 | def filterClicked(self): 335 | 336 | sender = self.sender() 337 | self.statusBar().showMessage(sender.text() + ' was pressed') 338 | try: 339 | self.setFilteredData(filterGoodValues(self.loadedData)) 340 | except: 341 | errorWin = QtGui.QMessageBox(self) 342 | errorWin.setText('Error: Try loading data first') 343 | errorWin.show() 344 | 345 | def openFileDialog(self): 346 | # SELF IS ALWAYS THE NAME OF THE CLASS 347 | fname = QtGui.QFileDialog.getOpenFileName(self, 'Open file', 348 | '/home') 349 | print('Opening File: '+repr(fname)) 350 | data = loadData(str(fname)) 351 | 352 | # Store the values 353 | self.setLoadedData(data); 354 | 355 | # Create a checkbox WIDGET to store this data 356 | self.checkWidget = QtGui.QWidget() 357 | self.filterWidget = QtGui.QWidget() 358 | 359 | checkWidgetList = [self.checkWidget, self.filterWidget] 360 | nameWidgetList = ["Plot Values", "Filter Values"] 361 | 362 | # Delete the old tabs, if there are more than 3 tabs total now 363 | if self.tabBar.count() >= 4: 364 | # First try to delete existing tabs from previous runs 365 | # Tabs are numbers 1, 2 366 | self.tabBar.removeTab(1) 367 | self.tabBar.removeTab(1) 368 | 369 | # Combo box for FILTERING choices 370 | counts =0; 371 | # Reset any values that may have been set before 372 | try: 373 | del self.checkBoxList[:] 374 | except: 375 | pass 376 | self.combo.clear(); self.combo2.clear(); 377 | for number, widget in enumerate(checkWidgetList): 378 | layout = QtGui.QGridLayout() 379 | for index, each in enumerate(data.columns): 380 | # Fill combo boxes, only once 381 | if number == 1: 382 | self.combo.addItem(each) 383 | self.combo2.addItem(each) 384 | 385 | # Make checkboxes for values - first half belowng to "Plot Values", second half "Filter" 386 | self.checkBoxList.append(QtGui.QCheckBox(each, widget)) 387 | self.checkBoxList[counts].sizeHint() 388 | # make a grid, with 2 columns 389 | layout.addWidget(self.checkBoxList[counts], floor(counts/2), counts % 2) 390 | counts+=1; 391 | 392 | widget.setLayout(layout) 393 | 394 | # add a tab showing these values -- 2 tabs total 395 | self.tabBar.insertTab(number+1, widget, nameWidgetList[number]) 396 | 397 | # Make a TABLE 398 | t = Table() # Do not put a parent here? 399 | t.table.setColumnCount(len(data.columns)) 400 | t.table.setRowCount(len(data.index)) 401 | for i in range(len(data.index)): 402 | for j in range(len(data.columns)): 403 | t.table.setItem(i,j, 404 | QtGui.QTableWidgetItem(str(data.iget_value(i, j)))) 405 | for i, value in enumerate(data.columns): 406 | t.table.setHorizontalHeaderItem(i, QtGui.QTableWidgetItem(str(value))) 407 | 408 | # Show the table 409 | if self.tabBar.count() >= 4: 410 | self.tabBar.removeTab(3) 411 | self.tabBar.addTab(t, "Updated Table") 412 | else: 413 | # Set for first time 414 | self.tabBar.addTab(t, "Table") # Add Table Tab 415 | 416 | 417 | # Message Window 418 | multiPickWin = QtGui.QMessageBox(self) 419 | multiPickWin.setText('You can only choose ONE check box at a time') 420 | multiPickWin.show() 421 | 422 | if __name__ == '__main__': 423 | import sys 424 | app = QtGui.QApplication(sys.argv) 425 | 426 | setSeabornParams() 427 | 428 | w = MainWindow() 429 | 430 | sys.exit(app.exec_()) 431 | 432 | --------------------------------------------------------------------------------