Package dsc_suite :: Package gui :: Module dsc
[hide private]
[frames] | no frames]

Source Code for Module dsc_suite.gui.dsc

   1  """module dsc 
   2   
   3  This module is the main class of the GUI interface. 
   4  It contains the class DSC. If you create an object from this class the GUI will be started. 
   5  The GUI uses the PyQt4 Framework, so this must be installed on your computer. 
   6  This module has only been tested under windows OS. 
   7  It should work under different OS as well, but minor parts could need to be changed. 
   8   
   9  @author: Tobias Heimpold 
  10  @version: 1.7 
  11  """ 
  12   
  13  #main uses modules 
  14  import os, sys, time 
  15  from PyQt4 import QtGui, QtCore 
  16  from scipy.io.wavfile import read 
  17  path_cwd = os.getcwd() 
  18  path_cwd = os.path.split(path_cwd)[0] 
  19  path_cwd = os.path.split(path_cwd)[0] 
  20  sys.path.append(path_cwd) 
  21   
  22  #used to set the right paths --> for change edit module toolpaths 
  23  from dsc_suite.tools.toolpaths import FOLDER_FOR_DATA as FFDATA 
  24  from dsc_suite.tools.toolpaths import FOLDER_FOR_PLOTS as FFPLOTS 
  25  #information about content in the GUI 
  26  #these modules contain the import for the specific modules related to the content 
  27  from dsc_suite.gui.config import DATA_STRUCTURE_LIST, BENCHMARK_LIST, OPTIMIZATION_LIST, EVALUATION_PLOT_LIST 
  28  from dsc_suite.gui.config import HEADER_LIST, PARAMETER_LIST, DATATYPE_LIST, LIMITFUNCTION_LIST, READFUNCTION_LIST 
  29  from dsc_suite.gui.config import DIAGRAM_PARAMETER_LIST 
  30  from dsc_suite.ds.data_structure import COST_CRITERIA_LIST as COST_LIST 
  31  #classes used to generate or save data 
  32  from dsc_suite.gui.xmlpars import XMLParser 
  33  from dsc_suite.gui.generator import Generator 
  34  #only for old files 
  35  #from dsc_suite.analyses.characteristics import get_statistic_characteristics 
  36   
  37   
38 -class DSC(QtGui.QMainWindow):
39 """class DSC(QMainWindow) 40 This class is the main part of the GUI. It contains all functions to create the GUI interface. 41 It is the only class in the project, which uses the PyQT Framework. 42 The interfaces to other classes is based on Python standard data types as dictionary, list, etc. 43 To start the GUI create an object of the DSC class and the GUI will start. 44 45 Attention: 46 The DSC starts an event bases loop. So the python programm which started the GUI will be terminated when the GUI is closed! 47 An interactive console mode in the GUI is planned but not yet implemented. 48 """ 49
50 - def __init__(self):
51 """__init__ 52 This function is the constructor of the DSC class. 53 It calls the build up functions for the GUI and sets same basic configurations. 54 It also launches the event loop. 55 Attention: The constructor will not be leaved. 56 """ 57 #application must be initialized before creating widgets 58 self.__app = QtGui.QApplication(sys.argv) 59 60 #create MainWindow, set title and make it central widget 61 QtGui.QMainWindow.__init__(self) 62 self.setWindowTitle("DSC") 63 self.__central = QtGui.QWidget() 64 self.setCentralWidget(self.__central) 65 self.setMinimumHeight(500) 66 self.setMinimumWidth(1024) 67 68 #create main layout for automatic fitting on window size 69 self.__mainlayout = QtGui.QHBoxLayout(self.__central) 70 71 #create a TabWidget 72 self.__main_tab = QtGui.QTabWidget(self.__central) 73 74 #create tabs 75 list = ["Planer", "Evaluator"] 76 #Managing Tab only for old files 77 #"Managing"] 78 self.__tabs = {} 79 for string in list: 80 tab = QtGui.QWidget(self.__main_tab) 81 tab.setAutoFillBackground(True) 82 tab.setMinimumWidth(400) 83 self.__main_tab.addTab(tab, string) 84 self.__tabs.update({string : tab}) 85 86 #integrating MenuBar at top of window with tree structure 87 self.__menubar = self.menuBar() 88 self.__file = self.__menubar.addMenu("File") 89 self.__action_new = self.__file.addMenu("New...") 90 self.__action_new_data = self.__action_new.addAction("XML for data") 91 self.__action_new_plot = self.__action_new.addAction("XML for plots") 92 self.__action_open = self.__file.addAction("Open...") 93 self.__action_exit = self.__file.addAction("Exit") 94 95 #adding StatusBar for information messages 96 self.__statusbar = self.statusBar() 97 98 #setting up default font 99 self.__font = QtGui.QFont() 100 self.__font.setPointSize(9) 101 #fill tabs with content 102 self.__createDataView() 103 104 self.__createPlaner() 105 106 #was just for old files 107 #self.__createManaging() 108 109 #adding main widget to main layout 110 self.__mainlayout.addWidget(self.__main_tab) 111 112 #set main layout to MainWindow 113 self.__central.setLayout(self.__mainlayout) 114 115 #connecting slots and signals 116 self.__connect() 117 118 #setting standard XML File Paths 119 self.__dataxml = FFDATA+"/data.xml" 120 self.__plotxml = FFPLOTS+"/plots.xml" 121 122 #creating new xml files if not existing 123 if not os.path.exists(self.__dataxml): 124 XMLParser(self.__dataxml, "datafile") 125 if not os.path.exists(self.__plotxml): 126 XMLParser(self.__plotxml, "plot") 127 128 #create algorithm change criteria 129 self.__current_algotihm = "" 130 131 #load standard data file 132 self.__refreshBrowser() 133 #window ready 134 self.__statusbar.showMessage("Ready") 135 136 #show application and enter event routine 137 self.showMaximized() 138 sys.exit(self.__app.exec_())
139
140 - def __str__(self):
141 """__str___ 142 - returns a string with ID of the GUI object 143 """ 144 return "MainWindow with ID="+str(id(self))+" of " + str(self.__class__)
145
146 - def keyPressEvent(self, event):
147 """keyPressEvent(QEvent) 148 - overrides original keyPressEvent() 149 - used to perform actions when user presses specific keys 150 151 - example implementation as a "how to" 152 - not used in this version of the GUI because mouse control dominates 153 - standard windows key function need not to be implemented 154 example Alt+F4 closes the GUI without be implemented directly 155 """ 156 if event.key() == QtCore.Qt.Key_F12: 157 self.__statusbar.showMessage("Programmed by Tobias Heimpold")
158
159 - def timerEvent(self, event):
160 """timerEvent(QEvent) 161 - overrides original timerEvent() 162 - used for threading the calculation 163 """ 164 #check if calculation ready 165 Generator.LockObject.acquire() 166 flag = bool(self.__generator.isAlive()) 167 time_check = self.__generator.time_check 168 self.__runDialog.setValue(self.__generator.current) 169 Generator.LockObject.release() 170 #if not ready leave... 171 if flag: 172 return 173 else: 174 #stop timer 175 self.__timer.stop() 176 if time_check: 177 self.__showTimeEstimation() 178 else: 179 self.__finishCalc()
180
181 - def __createDataView(self):
182 """__createDataView() 183 - builds the content of the Evaluator tab 184 """ 185 186 #create data file browser with group box 187 self.__d_data_brow = QtGui.QGroupBox() 188 self.__d_data_brow.setTitle("data file browser") 189 self.__d_data_brow.setFont(self.__font) 190 191 self.__d_data_browser = QtGui.QTreeWidget() 192 self.__d_data_browser.setHeaderLabels(["data files", "runtime"]) 193 self.__d_data_browser.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) 194 self.__d_data_browser.setMinimumWidth(700) 195 196 #create information part for the single files 197 self.__d_data_info = QtGui.QGroupBox() 198 self.__d_data_info.setTitle("information") 199 self.__d_data_info.setFont(self.__font) 200 201 self.__d_data_params = QtGui.QTreeWidget() 202 self.__d_data_params.setHeaderLabels(["parameter", "value"]) 203 self.__d_data_params.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) 204 205 self.__d_data_char = QtGui.QTreeWidget() 206 self.__d_data_char.setHeaderLabels(["characteristic", "value"]) 207 self.__d_data_char.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) 208 209 #create evaluation part --> in this version a row of buttons 210 self.__d_data_eval = QtGui.QGroupBox() 211 self.__d_data_eval.setTitle("Evaluation options") 212 self.__d_data_eval.setFont(self.__font) 213 214 self.__eval_buttons = [] 215 216 #use data from config file to create the single buttons for evaluation 217 for string in EVALUATION_PLOT_LIST.keys(): 218 button = QtGui.QPushButton() 219 button.setFont(self.__font) 220 button.setText(string) 221 button.setToolTip(EVALUATION_PLOT_LIST[string][1]) 222 self.__eval_buttons.append(button) 223 224 #linking evaluation function to button 225 self.__eval_button_func = [] 226 for string in EVALUATION_PLOT_LIST.keys(): 227 self.__eval_button_func.append(self.__gen_eval_func(string)) 228 #linking click event of button to function 229 for i in range(0,len(self.__eval_buttons),1): 230 self.connect(self.__eval_buttons[i], QtCore.SIGNAL("clicked()"), self.__eval_button_func[i]) 231 232 #adding buttons to a row 233 self.__evalbut_layout = QtGui.QHBoxLayout() 234 self.__evalbut_layout.addStretch() 235 for button in self.__eval_buttons: 236 self.__evalbut_layout.addWidget(button) 237 self.__evalbut_layout.addStretch() 238 self.__d_data_eval.setLayout(self.__evalbut_layout) 239 240 #putting the single parts together to the end layout 241 self.__d_data_brow_layout = QtGui.QVBoxLayout() 242 self.__d_data_brow.setLayout(self.__d_data_brow_layout) 243 self.__d_data_brow_layout.addWidget(self.__d_data_browser) 244 245 self.__d_data_info_layout = QtGui.QHBoxLayout() 246 self.__d_data_info.setLayout(self.__d_data_info_layout) 247 self.__d_data_info_layout.addWidget(self.__d_data_params) 248 self.__d_data_info_layout.addWidget(self.__d_data_char) 249 250 self.__d_right_layout = QtGui.QVBoxLayout() 251 self.__d_right_layout.addWidget(self.__d_data_info) 252 self.__d_right_layout.addWidget(self.__d_data_eval) 253 254 self.__viewlayout = QtGui.QHBoxLayout(self.__tabs["Evaluator"]) 255 self.__viewlayout.addWidget(self.__d_data_brow) 256 self.__viewlayout.addLayout(self.__d_right_layout)
257
258 - def __createPlaner(self):
259 """__createPlaner() 260 - builds the content of the Planer tab 261 """ 262 #setting up default font 263 self.__font.setPointSize(10) 264 265 #creating groupboxes with lists 266 list = ["benchmarks", "datastructures", "algorithms"] 267 dict = {"benchmarks" : BENCHMARK_LIST, "datastructures" : DATA_STRUCTURE_LIST , "algorithms" : OPTIMIZATION_LIST} 268 infotext = {} 269 #getting position of info text in config lsits 270 for string in dict: 271 for key in dict[string]: 272 for item in dict[string][key]: 273 if type(item) == str: 274 infotext.update({string : dict[string][key].index(item)}) 275 break 276 break 277 278 #ListWidgets with GroupBoxes and info text connection 279 self.__p_groupboxes = {} 280 self.__p_lists = {} 281 282 for string in list: 283 groupbox = QtGui.QGroupBox() 284 groupbox.setTitle(string) 285 groupbox.setFont(self.__font) 286 groupbox.setMaximumHeight(250) 287 layout = QtGui.QHBoxLayout() 288 groupbox.setLayout(layout) 289 listwid = QtGui.QListWidget() 290 listwid.setMouseTracking(True) 291 listwid.setFont(self.__font) 292 layout.addWidget(listwid) 293 for key in dict[string].keys(): 294 listwid.addItems([key]) 295 listwid.sortItems() 296 #linking the information from config to the information part of the GUI 297 self.connect(listwid, QtCore.SIGNAL("itemSelectionChanged ()"), self.__gen_info_func(listwid, dict[string], infotext[string])) 298 self.__p_lists.update({string : listwid}) 299 self.__p_groupboxes.update({string : groupbox }) 300 301 #other GroupBoxes but with different layout 302 list = ["settings", "information", "process priority", "planned trials"] 303 layouts = {"settings" : QtGui.QHBoxLayout , "information" : QtGui.QHBoxLayout, "process priority" : QtGui.QHBoxLayout, 304 "planned trials": QtGui.QVBoxLayout} 305 306 self.__p_groupboxes_layout = {} 307 for string in list: 308 groupbox = QtGui.QGroupBox() 309 groupbox.setTitle(string) 310 groupbox.setFont(self.__font) 311 layout = layouts[string]() 312 groupbox.setLayout(layout) 313 self.__p_groupboxes.update({string : groupbox}) 314 self.__p_groupboxes_layout.update({string : layout}) 315 316 #planned trials table 317 self.__p_planned_trials = QtGui.QTreeWidget() 318 self.__p_planned_trials.setColumnCount(len(HEADER_LIST)) 319 self.__p_planned_trials.setHeaderLabels(HEADER_LIST) 320 self.__p_planned_trials.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) 321 #dictionary behind planned trials 322 #used as interface to generator module !!! 323 self.__generated_trials = {} 324 325 self.__p_groupboxes_layout["planned trials"].addWidget(self.__p_planned_trials) 326 327 #defines a function to change the header of the planned trials table 328 #opens a dialog with all parameters to choose from 329 def changeHeader(): 330 dialog = QtGui.QDialog(self.__central) 331 layout = QtGui.QVBoxLayout() 332 dialog.setLayout(layout) 333 checkboxes = [] 334 label = "global" 335 groupbox = QtGui.QGroupBox(label) 336 layout.addWidget(groupbox) 337 sub_layout = QtGui.QHBoxLayout() 338 groupbox.setLayout(sub_layout) 339 list = HEADER_LIST 340 current_header = [] 341 for column in range(self.__p_planned_trials.headerItem().columnCount()): 342 current_header.append(str(self.__p_planned_trials.headerItem().text(column))) 343 344 for string in list: 345 box = QtGui.QCheckBox(string) 346 sub_layout.addWidget(box) 347 checkboxes.append(box) 348 if string in current_header: 349 box.setChecked(True) 350 351 for algorithm in OPTIMIZATION_LIST.keys(): 352 groupbox = QtGui.QGroupBox(algorithm) 353 layout.addWidget(groupbox) 354 sub_layout = QtGui.QHBoxLayout() 355 groupbox.setLayout(sub_layout) 356 for parameter in PARAMETER_LIST[algorithm].keys(): 357 box = QtGui.QCheckBox(parameter) 358 sub_layout.addWidget(box) 359 checkboxes.append(box) 360 if parameter in current_header: 361 box.setChecked(True) 362 sub_layout.addStretch() 363 button = QtGui.QPushButton("Ok") 364 button.setMaximumWidth(50) 365 layout.addWidget(button) 366 def change(): 367 dialog.close() 368 new_header = [] 369 for box in checkboxes: 370 if box.isChecked(): 371 new_header.append(box.text()) 372 self.__p_planned_trials.setHeaderLabels(new_header) 373 self.__p_planned_trials.setColumnCount(len(new_header)) 374 for col in range(self.__p_planned_trials.columnCount()): 375 self.__p_planned_trials.resizeColumnToContents(col) 376 self.__refreshPlaner()
377 378 379 self.connect(button, QtCore.SIGNAL("clicked()"), change) 380 dialog.show()
381 382 #Buttons with tool tip and their functions 383 list = ["Generate","Edit table view", "Start", "Remove", "Up", "Down"] 384 dict = {"Generate": "Adds current selection to list", 385 "Start": "Starts the calculation", 386 "Edit table view" : "Changes the header of the table", 387 "Remove" : "Removes selected item from list", 388 "Up" : "Moves item up in list", 389 "Down" : "Moves item down in list"} 390 func_dict = {"Generate" : self.__generate, 391 "Start" : self.__startCalc, 392 "Edit table view" : changeHeader, 393 "Remove" : self.__gen_index_change_func("Remove"), 394 "Up" : self.__gen_index_change_func("Up"), 395 "Down" :self.__gen_index_change_func("Down")} 396 397 #create buttons 398 self.__p_pushbuttons = {} 399 for string in list: 400 button = QtGui.QPushButton() 401 button.setText(string) 402 button.setFont(self.__font) 403 button.setToolTip(dict[string]) 404 button.setEnabled(True) 405 self.__p_pushbuttons.update({string: button}) 406 self.connect(button, QtCore.SIGNAL("clicked()"), func_dict[string]) 407 408 self.__p_pushbuttons["Start"].setEnabled(False) 409 410 #InfoText label --> views information from config file 411 self.__plabel_infotext = QtGui.QLabel() 412 self.__plabel_infotext.setFont(self.__font) 413 self.__plabel_infotext.setMaximumHeight(100) 414 415 #Radio Buttons for priority choise in GroupBox 416 #just works with windows OS at the moment --> see generator module for information 417 list = ["Low", "Less normal", "Normal"] 418 dict = {"Low": "using idle processor time", "Less normal" : "background" , "Normal" : ""} 419 self.__p_radiobuttons = {} 420 self.__radiobutton_group = QtGui.QButtonGroup() 421 for string in list: 422 button = QtGui.QRadioButton() 423 button.setText(string) 424 button.setToolTip(dict[string]) 425 button.setFont(self.__font) 426 self.__p_radiobuttons.update({string : button}) 427 self.__radiobutton_group.addButton(button, list.index(string)) 428 self.__p_groupboxes_layout["process priority"].addWidget(button) 429 430 self.__p_radiobuttons["Normal"].setChecked(True) 431 432 #vertical layout (mainlayout for planer tab) 433 self.__hmainbox = QtGui.QHBoxLayout(self.__tabs["Planer"]) 434 self.__tabs["Planer"].setLayout(self.__hmainbox) 435 436 #horizontal sub-layouts (left and right) with line 437 self.__vmainbox_r = QtGui.QVBoxLayout() 438 self.__vmainbox_l = QtGui.QVBoxLayout() 439 self.__vline = QtGui.QFrame() 440 self.__vline.setFrameShape(QtGui.QFrame.VLine) 441 self.__vline.setFrameShadow(QtGui.QFrame.Sunken) 442 443 #horizontal sub-widgets 444 self.__vmainwid_l = QtGui.QWidget() 445 self.__vmainwid_l.setLayout(self.__vmainbox_l) 446 self.__vmainwid_l.setMaximumWidth(450) 447 self.__vmainwid_r = QtGui.QWidget() 448 self.__vmainwid_r.setLayout(self.__vmainbox_r) 449 450 451 #adding sub-layouts to main layout 452 self.__hmainbox.addWidget(self.__vmainwid_l) 453 self.__hmainbox.addWidget(self.__vline) 454 self.__hmainbox.addWidget(self.__vmainwid_r) 455 456 #grid-layout for left side 457 self.__grid = QtGui.QGridLayout() 458 self.__grid.setSizeConstraint(QtGui.QLayout.SetMinimumSize) 459 self.__vmainbox_l.addLayout(self.__grid) 460 461 #Buttons 462 self.__p_button_layout = QtGui.QHBoxLayout() 463 list = ["Edit table view","","Remove", "Up", "Down", "Start"] 464 for string in list: 465 if string == "": 466 self.__p_button_layout.addStretch() 467 else: 468 self.__p_button_layout.addWidget(self.__p_pushbuttons[string]) 469 470 #adding widgets and filled layouts 471 #adding in-grid layouts to grid-layout 472 self.__grid.addWidget(self.__p_groupboxes["benchmarks"],0,0) 473 self.__grid.addWidget(self.__p_groupboxes["datastructures"],0,1) 474 self.__grid.addWidget(self.__p_groupboxes["algorithms"],0,2) 475 476 #self.__p_groupboxes_layout["parameters"].addWidget(self.__p_pushbuttons["Generate"]) 477 self.__p_groupboxes_layout["information"].addWidget(self.__plabel_infotext) 478 479 480 self.__vmainbox_r.addWidget(self.__p_groupboxes["planned trials"]) 481 self.__vmainbox_r.addLayout(self.__p_button_layout) 482 483 self.__vmainbox_l.addWidget(self.__p_groupboxes["settings"]) 484 self.__vmainbox_l.addWidget(self.__p_groupboxes["information"]) 485 self.__vmainbox_l.addWidget(self.__p_groupboxes["process priority"]) 486 487 #separated function to better the reading of code --> changes of parameter must only be considered there 488 self.__createSettingSection() 489
490 - def __createSettingSection(self):
491 """__createSettingSection() 492 - builds the content of the parameter section of the Planer Tab 493 - changes of parameters must be only considered here 494 - creates different layouts for the specific parameters of the algorithms 495 - it links the parameters with their name with an dictionary 496 --> to get the parameter inserted by the user --> use that dictionary 497 """ 498 499 #create scroll area for settings sector 500 scroll_area = QtGui.QScrollArea() 501 scroll_area.setFrameStyle(QtGui.QFrame.NoFrame) 502 widget = QtGui.QWidget() 503 widget.setMinimumSize(2, 2) 504 scroll_area.setWidget(widget) 505 area_layout = QtGui.QGridLayout() 506 area_layout.setSizeConstraint(QtGui.QLayout.SetMinAndMaxSize) 507 widget.setLayout(area_layout) 508 self.__p_groupboxes_layout["settings"].addWidget(scroll_area) 509 510 #differs in general and algorithm specific paramters 511 list = ["general" , "individual"] 512 dict = {"general" : QtGui.QVBoxLayout, "individual" : QtGui.QStackedLayout} 513 514 self.__p_setting_boxes_layout = {} 515 516 for string in list: 517 box = QtGui.QGroupBox() 518 box.setTitle(string) 519 layout = dict[string]() 520 box.setLayout(layout) 521 self.__p_setting_boxes_layout.update({string : layout}) 522 area_layout.addWidget(box,0,list.index(string)) 523 area_layout.addWidget(self.__p_pushbuttons["Generate"],1,1, alignment = QtCore.Qt.AlignBottom) 524 525 self.__p_general_settings = {} 526 527 #list of general parameters 528 list = ["trial name", "z-D" , "cost criteria" , "weight factors", "norm values", "samples for norm values"] 529 tool = {"trial name" : "the name for the trial", 530 "z-D" : "third dimension of block, auto generated or specific value", 531 "cost criteria": "choose at least one cost criteria to experiment", 532 "weight factors": "set the influence of cost criteria above to cost function", 533 "norm values" : "used to normalize the values of the cost criteria, loaded from database or estimated from samples", 534 "samples for norm values" : "samples used to calculate the mean values of the cost criteria"} 535 536 self.__p_general_set_boxes_layouts = {} 537 538 for string in list: 539 box = QtGui.QGroupBox() 540 layout = QtGui.QHBoxLayout() 541 box.setLayout(layout) 542 box.setTitle(string) 543 box.setToolTip(tool[string]) 544 self.__p_setting_boxes_layout["general"].addWidget(box) 545 self.__p_general_set_boxes_layouts.update({string : layout}) 546 547 #trial name 548 tnline =QtGui.QLineEdit() 549 self.__p_general_set_boxes_layouts["trial name"].addWidget(tnline) 550 self.__p_general_set_boxes_layouts["trial name"].addWidget(tnline) 551 self.__p_general_settings.update({"trial name":tnline}) 552 553 #third dimension component for 2D benchmarks 554 zcheck = QtGui.QCheckBox("auto") 555 zline = QtGui.QLineEdit() 556 self.__p_general_set_boxes_layouts["z-D"].addWidget(zcheck) 557 self.__p_general_set_boxes_layouts["z-D"].addWidget(zline) 558 self.__p_general_settings.update({"z-D":zline}) 559 560 def auto3D(): 561 if zcheck.isChecked(): 562 zline.setEnabled(False) 563 else: 564 zline.setEnabled(True)
565 self.connect(zcheck, QtCore.SIGNAL("stateChanged (int)"),auto3D) 566 zcheck.setChecked(True) 567 568 #cost criteria which are implemented in data structure module 569 #also added an weight factor for optimization functions 570 #factors should be checked if their sum=1 ! 571 for criteria in COST_LIST.keys(): 572 check_box = QtGui.QCheckBox() 573 check_box.setText(criteria) 574 spin_box = QtGui.QDoubleSpinBox() 575 spin_box.setRange(0.0,1.0) 576 spin_box.setValue(0.5) 577 spin_box.setDecimals(2) 578 spin_box.setSingleStep(0.05) 579 spin_box.setEnabled(False) 580 self.__p_general_set_boxes_layouts["cost criteria"].addWidget(check_box) 581 self.__p_general_set_boxes_layouts["weight factors"].addWidget(spin_box) 582 self.__p_general_settings.update({criteria : check_box}) 583 self.__p_general_settings.update({"weight_"+criteria : spin_box}) 584 def defineEnableFunction(criteria): 585 def enableBox(): 586 if self.__p_general_settings[criteria].isChecked(): 587 self.__p_general_settings["weight_"+criteria].setEnabled(True) 588 else: 589 self.__p_general_settings["weight_"+criteria].setEnabled(False) 590 return enableBox 591 self.connect(self.__p_general_settings[criteria], QtCore.SIGNAL("stateChanged (int)"), defineEnableFunction(criteria)) 592 593 #mean value of the cost criteria for normalization of cost function 594 #mean values can be uses from Monte Carlo results or can be estimated with a short run of Monte Carlo 595 load_button = QtGui.QRadioButton("database") 596 new_button = QtGui.QRadioButton("estimate") 597 radio_but_gro = QtGui.QButtonGroup() 598 radio_but_gro.addButton(load_button,0) 599 radio_but_gro.addButton(new_button,1) 600 spin_box = QtGui.QSpinBox() 601 spin_box.setRange(100,10000) 602 spin_box.setValue(5000) 603 spin_box.setSingleStep(100) 604 self.__p_general_set_boxes_layouts["samples for norm values"].addWidget(spin_box) 605 self.__p_general_settings.update({"mean_samples" : spin_box, 606 "estimate_button" : new_button}) 607 #mean samples for estimation should only be enables when button is really "estimate" 608 def buttonchange(): 609 a = radio_but_gro.checkedId() 610 if a == 0: 611 spin_box.setEnabled(False) 612 if a == 1: 613 spin_box.setEnabled(True) 614 615 self.connect(load_button, QtCore.SIGNAL("clicked ()"), buttonchange) 616 self.connect(new_button, QtCore.SIGNAL("clicked ()"), buttonchange) 617 load_button.click() 618 619 self.__p_general_set_boxes_layouts["norm values"].addWidget(load_button) 620 self.__p_general_set_boxes_layouts["norm values"].addWidget(new_button) 621 622 #creating algorithm specific parameter --> uses actual selected algorithm 623 #config file contains the different parameters, their data type, the class of uses PyQt interface and the functions which changes the parameter configurations 624 # --> see config file to understand the next parts !!! 625 self.__p_individual_settings= {} 626 for key in PARAMETER_LIST.keys(): 627 self.__p_individual_settings.update({key: {}}) 628 self.__p_individual_widgets = {} 629 no_widget = self.__p_setting_boxes_layout["individual"].addWidget(QtGui.QWidget()) 630 for algorithm in PARAMETER_LIST.keys(): 631 widget = QtGui.QWidget() 632 top_layout = QtGui.QVBoxLayout() 633 widget.setLayout(top_layout) 634 a = self.__p_setting_boxes_layout["individual"].addWidget(widget) 635 self.__p_individual_widgets.update({algorithm : a}) 636 637 for parameter in PARAMETER_LIST[algorithm].keys(): 638 datatype = PARAMETER_LIST[algorithm][parameter][0] 639 tooltip = PARAMETER_LIST[algorithm][parameter][1] 640 limits = PARAMETER_LIST[algorithm][parameter][2] 641 box = QtGui.QGroupBox() 642 box.setTitle(parameter.replace("_"," ")) 643 box.setToolTip(tooltip) 644 top_layout.addWidget(box) 645 layout = QtGui.QVBoxLayout() 646 box.setLayout(layout) 647 widget = eval(DATATYPE_LIST[datatype]) 648 layout.addWidget(widget) 649 function_list = LIMITFUNCTION_LIST[datatype] 650 651 self.__p_individual_settings[algorithm].update({parameter : widget}) 652 653 for index in range(len(function_list)): 654 func = "widget."+function_list[index] 655 eval(func)(limits[index]) 656 657 top_layout.addStretch() 658 self.__p_setting_boxes_layout["individual"].setCurrentIndex(no_widget) 659 660
661 - def __changeParamLayout(self):
662 """__changeParamLayout() 663 - switches between the different algorithm parameter layouts 664 """ 665 a = str(self.__p_lists["algorithms"].currentItem().text()) 666 self.__p_setting_boxes_layout["individual"].setCurrentIndex(self.__p_individual_widgets[a])
667 '''only for old files 668 def __createManaging(self): 669 """__ccreatesManaging 670 - this section was implemented to import old data files into an XML file 671 - the work has been halted after the important files were integrated 672 673 The documentation of this part is still missing. 674 The basis structure is: 675 - get file name 676 - try to find information in the file name --> present them to user for check 677 - calculate the statistic data from the file content for XML file 678 - create new entry in XML file 679 680 Attention: 681 Because of a different method to save information in the data file name, this function must be adjusted by hand and is very buggy ! 682 It also works only for one file only. For new files use the Planer Part of the GUI ! 683 """ 684 self.__m_mainlayout = QtGui.QGridLayout() 685 self.__tabs["Managing"].setLayout(self.__m_mainlayout) 686 687 list = ["Import old datafiles", "Edit parameters", "benchmark", "datastructure", "algorithm", "samples", "cost criteria", "runtime", 688 "z-D", "Characteristics", "Update datafile", "How to use"] 689 layouts = {"Import old datafiles" : QtGui.QVBoxLayout, "Edit parameters" : QtGui.QVBoxLayout, "benchmark" : QtGui.QVBoxLayout, 690 "datastructure": QtGui.QVBoxLayout, "algorithm": QtGui.QVBoxLayout, "samples": QtGui.QVBoxLayout, "cost criteria" : QtGui.QVBoxLayout, 691 "runtime": QtGui.QVBoxLayout, "z-D": QtGui.QVBoxLayout, "Characteristics" : QtGui.QVBoxLayout, "Update datafile" : QtGui.QHBoxLayout, 692 "How to use": QtGui.QVBoxLayout} 693 694 self.__m_groupboxes = {} 695 self.__m_groupboxes_layouts = {} 696 697 for string in list: 698 groupbox = QtGui.QGroupBox() 699 groupbox.setTitle(string) 700 groupbox.setFont(self.__font) 701 layout = layouts[string]() 702 groupbox.setLayout(layout) 703 self.__m_groupboxes.update({string:groupbox}) 704 self.__m_groupboxes_layouts.update({string: layout}) 705 706 list = ["filename", "benchmark", "datastructure", "algorithm", "samples","cost criteria", "runtime", "z-D"] 707 708 self.__m_inputElements = {} 709 710 for string in list: 711 widget = QtGui.QLineEdit() 712 widget.setMaximumWidth(200) 713 widget.setFont(self.__font) 714 self.__m_inputElements.update({string : widget}) 715 716 list = ["benchmark", "datastructure", "algorithm", "samples","cost criteria", "runtime", "z-D"] 717 718 for string in list: 719 self.__m_groupboxes_layouts[string].addWidget(self.__m_inputElements[string]) 720 self.__m_groupboxes_layouts["Edit parameters"].addWidget(self.__m_groupboxes[string]) 721 722 list = ["Select file", "Characteristics", "Write to XML"] 723 dict = {"Select file" : "Opens a dialog to select datafile", "Characteristics" : "Calculates the characteristics", "Write to XML" : "Writes the information into the selected XML file"} 724 725 self.__m_pushbuttons = {} 726 for string in list: 727 widget = QtGui.QPushButton() 728 widget.setFont(self.__font) 729 widget.setText(string) 730 widget.setMaximumWidth(150) 731 widget.setToolTip(dict[string]) 732 self.__m_pushbuttons.update({string : widget}) 733 734 self.__m_charact_groupboxes = {} 735 self.__m_charact_labels = {} 736 737 def getcharacts(): 738 739 path = os.path.split(str(self.__m_inputElements["filename"].text()))[1] 740 result = get_statistic_characteristics(path) 741 for key in result.keys(): 742 if key in self.__m_charact_groupboxes.keys(): 743 self.__m_charact_labels[key].setText(str(result[key])) 744 continue 745 self.__m_charact_groupboxes.update({key: QtGui.QGroupBox()}) 746 self.__m_charact_groupboxes[key].setFont(self.__font) 747 self.__m_charact_groupboxes[key].setTitle(key) 748 layout = QtGui.QHBoxLayout() 749 self.__m_charact_groupboxes[key].setLayout(layout) 750 self.__m_charact_labels.update({key : QtGui.QLabel()}) 751 self.__m_charact_labels[key].setFont(self.__font) 752 self.__m_charact_labels[key].setText(str(result[key])) 753 layout.addWidget(self.__m_charact_labels[key]) 754 self.__m_groupboxes_layouts["Characteristics"].addWidget(self.__m_charact_groupboxes[key]) 755 756 self.__m_guide_label = QtGui.QLabel() 757 string = ("1. Use 'Select file' button to choose a datafile.\n" 758 "2. The program tries to auto-complete the parameter lines on the right site.\n" 759 "3. Check the found parameters.\n" 760 "4. (Optional) Correct or complete missing parameters.\n" 761 "5. (Optional) You can calculate the characteristics by pressing the 'Characteristics button'.\n" 762 "6. Click the 'Write to XML' button to link the file with the current XML database.\n" 763 "\n" 764 "Addition:\n" 765 "If the 'z-D' field is left blank, the programm will set the parameter to 'auto'.\n" 766 "The 'runtime' field need not to be filled.") 767 768 self.__m_guide_label.setText(string) 769 770 771 self.connect(self.__m_pushbuttons["Characteristics"], QtCore.SIGNAL("clicked()"), getcharacts) 772 773 self.__m_groupboxes_layouts["Import old datafiles"].addWidget(self.__m_inputElements["filename"]) 774 self.__m_groupboxes_layouts["Import old datafiles"].addWidget(self.__m_pushbuttons["Select file"]) 775 self.__m_groupboxes_layouts["Import old datafiles"].addWidget(self.__m_groupboxes["How to use"]) 776 self.__m_groupboxes_layouts["Import old datafiles"].addStretch() 777 778 self.__m_groupboxes_layouts["Update datafile"].addWidget(self.__m_pushbuttons["Characteristics"]) 779 self.__m_groupboxes_layouts["Update datafile"].addWidget(self.__m_pushbuttons["Write to XML"]) 780 781 self.__m_groupboxes_layouts["How to use"].addWidget(self.__m_guide_label) 782 783 self.__m_mainlayout.addWidget(self.__m_groupboxes["Import old datafiles"],0,0) 784 self.__m_mainlayout.addWidget(self.__m_groupboxes["Edit parameters"], 0,1) 785 self.__m_mainlayout.addWidget(self.__m_groupboxes["Characteristics"],1,0) 786 self.__m_mainlayout.addWidget(self.__m_groupboxes["Update datafile"],1,1) 787 '''
788 - def __connect(self):
789 """__connect() 790 - connects the widgets with signals and slots 791 792 Attention: Not every signals and slots can be connected in this global way. But those who can should be done here ! 793 If not the code gets very difficult to read. 794 """ 795 #connecting Slots and Signals with function - menu 796 self.connect(self.__action_exit, QtCore.SIGNAL("triggered()"), QtGui.qApp, QtCore.SLOT("quit()")) 797 self.connect(self.__action_open, QtCore.SIGNAL("triggered()"), self.__openFile) 798 self.connect(self.__action_new_data, QtCore.SIGNAL("triggered()"), self.__newXMLDataFile) 799 self.connect(self.__action_new_plot, QtCore.SIGNAL("triggered()"), self.__newXMLPlotFile) 800 801 #connecting Slots and Signals with function - planer area 802 self.connect(self.__p_lists["algorithms"], QtCore.SIGNAL("itemClicked (QListWidgetItem *)"), self.__changeParamLayout) 803 804 #connecting Slots and Signals with function - data area 805 self.connect(self.__d_data_browser, QtCore.SIGNAL("itemSelectionChanged ()"), self.__datainfo) 806 self.connect(self.__d_data_browser, QtCore.SIGNAL("itemExpanded (QTreeWidgetItem *)"), self.__dataview_fit) 807 self.connect(self.__d_data_browser, QtCore.SIGNAL("itemCollapsed (QTreeWidgetItem *)"), self.__dataview_fit)
808 809 #connecting Slots and Signals with function - manager area 810 #only for old files 811 #self.connect(self.__m_pushbuttons["Select file"], QtCore.SIGNAL("clicked ()"), self.__openFile) 812 #self.connect(self.__m_pushbuttons["Write to XML"], QtCore.SIGNAL("clicked ()"), self.__updateXML) 813
814 - def __newFile(self, string):
815 """__newFile(string) 816 - this function creates a new XML file either for datafiles or plots 817 - it also changes the current XML files to the new ones just created 818 """ 819 filedialog = QtGui.QFileDialog(self) 820 path = "" 821 if string == "datafile": 822 path = str(filedialog.getSaveFileName(self, "Save File", FFDATA, "XML (*.xml)")) 823 self.__dataxml = path 824 if string == "plot": 825 path = str(filedialog.getSaveFileName(self, "Save File", FFPLOTS, "XML (*.xml)")) 826 self.__plotxml = path 827 if path == "": 828 return 829 XMLParser(path, string) 830 self.__refreshBrowser()
831
832 - def __newXMLDataFile(self):
833 """__newXMLDateFile() 834 - a transmission function for correct call of __newFile(string) 835 """ 836 self.__newFile("datafile")
837
838 - def __newXMLPlotFile(self):
839 """__newXMLPlotFile() 840 - a transmission function for correct call of __newFile(string) 841 """ 842 self.__newFile("plot")
843
844 - def __openFile(self):
845 """___openFile() 846 - opens a XML file into the GUI 847 848 Old version: There was an option to save the generated trials to an text file. 849 This feature is not yet implemented after the complete planer tool was re-designed 850 """ 851 #using QFileDialog 852 filedialog = QtGui.QFileDialog(self) 853 #just allow data files for current tab 854 tabtext = self.__main_tab.tabText(self.__main_tab.currentIndex()) 855 if tabtext == "Evaluator": 856 self.__openXMLFile(str(filedialog.getOpenFileName(self, "Open File", FFDATA, "XML (*.xml)" ))) 857 if tabtext == "Planer": 858 path = (str(filedialog.getOpenFileName(self, "Open File", FFDATA, "XML (*xml);;SCHED (*.sched)" ))) 859 if os.path.splitext(path)[1] == ".xml": 860 self.__openXMLFile(path) 861 if os.path.splitext(path)[1] == ".SCHED": 862 self.__openSCHEDfile(path) 863 if tabtext == "Managing": 864 path = (str(filedialog.getOpenFileName(self, "Open File", FFDATA))) 865 if path == "": 866 return 867 self.__import(path)
868
869 - def __openXMLFile(self, path):
870 """__openXMLFile(path) 871 - opens the XMLFile under path 872 - updates the file browser in evaluator area 873 874 Attention: Large file will take same time to load. 875 The new thread avoids the freeze of the GUI and a terminate proposal of the OS. 876 In later versions there will be a loading progress bar. 877 """ 878 #if canceled abort 879 if path == "": 880 return 881 parser = XMLParser(path, "") 882 if parser.getRootName() == "datafiles": 883 self.__refreshBrowser() 884 self.__dataxml = path 885 elif parser.getRootName() == "plots": 886 self.__plotxml = path 887 else: 888 self.__popUp("XML file could not be loaded.\nThe rootname differs from the defaults.") 889 self.__statusbar.showMessage("XML File loaded")
890
891 - def __infoText(self, str):
892 """__infoText(string) 893 - shows the string in the information area in planer tab 894 """ 895 self.__plabel_infotext.setText(str)
896
897 - def __generate(self):
898 """__generate() 899 - generates a table entry in planer tab with the selected parameters 900 - it creates a dictionary which is used as interface for the generator module 901 """ 902 #no dictionary --> create new 903 try: 904 self.__generated_trials.keys() 905 except: 906 self.__generated_trials = {} 907 908 #items in list selected 909 new_index = len(self.__generated_trials.keys()) 910 911 self.__generated_trials.update({new_index : {"init_params" : {}, 912 "individual_params" : {}}}) 913 914 self.__current_index_dict = self.__generated_trials[new_index] 915 916 #check selection --> something missing --> error 917 try: 918 data = str(self.__p_lists["datastructures"].currentItem().text()) 919 except AttributeError: 920 del(self.__generated_trials[new_index]) 921 self.__popUp("Missing data structure") 922 return 923 try: 924 bench = str(self.__p_lists["benchmarks"].currentItem().text()) 925 except AttributeError: 926 del(self.__generated_trials[new_index]) 927 self.__popUp("Missing benchmark") 928 return 929 try: 930 algorithm = str(self.__p_lists["algorithms"].currentItem().text()) 931 except AttributeError: 932 del(self.__generated_trials[new_index]) 933 self.__popUp("Missing algorithm") 934 return 935 936 #add information to dictionary 937 self.__current_index_dict["init_params"].update({"benchmark" : bench, 938 "datastructure" : data, 939 "algorithm" : algorithm, 940 "cost_criteria" : {"SUM" : {}}}) 941 #add trial name 942 try: 943 name = str(self.__p_general_settings["trial name"].text()) 944 if name=="": 945 self.__popUp("No name given. Data files will be named with time stamp.") 946 name= time.strftime("%Y-%m-%d") 947 if "\\"in name or "/"in name or ":"in name or "*"in name or "?"in name or "\""in name or "<"in name or ">"in name or "|"in name: 948 self.__popUp("Name must not have litarals: \\ / : * ? \" < > |") 949 return 950 except: 951 self.__popUp("Name not readable. Data files will be named with time stamp.") 952 name=time.strftime("%Y-%m-%d") 953 self.__current_index_dict["init_params"].update({"trial_name" : name}) 954 955 #add trial date 956 self.__current_index_dict["init_params"].update({"trial_date" : time.strftime("%Y-%m-%d")}) 957 958 #add 3D info for 2D benchmarks 959 if self.__p_general_settings["z-D"].isEnabled(): 960 try: 961 value = float(self.__p_general_settings["z-D"].text()) 962 except: 963 self.__popUp("Can not evaluate z-D parameter") 964 self.__current_index_dict["init_params"].update({"z-Dimension" : value}) 965 else: 966 self.__current_index_dict["init_params"].update({"z-Dimension" : "auto"}) 967 968 #getting information about cost criteria and their weight factors 969 sum = 0.0 970 for criteria in COST_LIST.keys(): 971 if self.__p_general_settings[criteria].isChecked(): 972 self.__current_index_dict["init_params"]["cost_criteria"].update({criteria : {}}) 973 factor = round(float(self.__p_general_settings["weight_"+criteria].value()),2) 974 self.__current_index_dict["init_params"]["cost_criteria"]["SUM"].update({"weight_factor_"+criteria: factor}) 975 sum += factor 976 sum = round(sum, 2) 977 978 #checking sum of weight factors, should be 1 979 if sum != 1.0: 980 self.__popUp("sum of weight factors not equal 1.0") 981 del(self.__generated_trials[new_index]) 982 return 983 #checking for database of Monte Carlo results 984 if not os.path.exists(FFDATA+"\mean_values.xml"): 985 self.__p_general_settings["estimate_button"].click() 986 self.__p_general_settings["mean_samples"].setValue(5000) 987 988 if self.__p_general_settings["mean_samples"].isEnabled(): 989 value = int(self.__p_general_settings["mean_samples"].value()) 990 self.__current_index_dict["init_params"].update({"mean_samples" : value}) 991 else: 992 keys = set(self.__current_index_dict["init_params"]["cost_criteria"].keys()) 993 cost_criteria = list(keys & set(COST_LIST.keys())) 994 self.__current_index_dict["init_params"].update({"mean_samples" : None}) 995 parser = XMLParser(FFDATA+"\mean_values.xml") 996 dict = parser.getCharacteristic(data, "Monte Carlo", bench, cost_criteria, ["mean_value"]) 997 if dict == {}: 998 self.__popUp("Can not find combination of data structure and benchmark in database") 999 del(self.__generated_trials[new_index]) 1000 return 1001 for criteria in cost_criteria: 1002 value = float(dict[criteria]["mean_value"]) 1003 self.__current_index_dict["init_params"]["cost_criteria"]["SUM"].update({"norm_value_"+criteria : value}) 1004 #getting specific parameters for algorithm 1005 #no error correction --> config file should provide a basis configuration of these parameters 1006 #read function of the parameter also defined in config file 1007 for parameter in PARAMETER_LIST[algorithm].keys(): 1008 datatype = PARAMETER_LIST[algorithm][parameter][0] 1009 function = READFUNCTION_LIST[datatype] 1010 widget = self.__p_individual_settings[algorithm][parameter] 1011 string = datatype+"(widget."+function+"())" 1012 value = eval(string) 1013 self.__current_index_dict["individual_params"].update({parameter : value}) 1014 1015 #refresh the table of created trials 1016 self.__refreshPlaner() 1017 #setting the start button to enabled 1018 self.__p_pushbuttons["Start"].setEnabled(True) 1019 1020 self.__statusbar.showMessage("Trial added")
1021
1022 - def __refreshPlaner(self):
1023 """__refreshPlaner() 1024 - this function is used to display the generated trials in the table of the planer tab 1025 """ 1026 1027 #clearing actuall table 1028 self.__p_planned_trials.clear() 1029 #setting header 1030 current_header = self.__p_planned_trials.headerItem() 1031 #generate new entries for table 1032 #uses header as basis and gets information from dict and transforms them into pretty print 1033 for index in self.__generated_trials.keys(): 1034 new_item = QtGui.QTreeWidgetItem() 1035 self.__p_planned_trials.addTopLevelItem(new_item) 1036 init_params = self.__generated_trials[index]["init_params"] 1037 individual_params = self.__generated_trials[index]["individual_params"] 1038 cost_criteria = self.__generated_trials[index]["init_params"]["cost_criteria"] 1039 sum_criteria = self.__generated_trials[index]["init_params"]["cost_criteria"]["SUM"] 1040 1041 for col in range(current_header.columnCount()): 1042 text = str(current_header.text(col)) 1043 if text == "#": 1044 new_item.setText(col, str(index)) 1045 elif text.replace(" ","_") in init_params: 1046 new_item.setText(col, str(init_params[text.replace(" ","_")])) 1047 elif text in individual_params: 1048 new_item.setText(col, str(individual_params[text])) 1049 elif text.replace(" ","_") in sum_criteria: 1050 new_item.setText(col, str(sum_criteria[text.replace(" ","_")])) 1051 elif text in cost_criteria: 1052 new_item.setText(col, "+") 1053 new_item.setTextAlignment(col, QtCore.Qt.AlignCenter) 1054 #resize the columns to fit to data 1055 for col in range(self.__p_planned_trials.columnCount()): 1056 self.__p_planned_trials.resizeColumnToContents(col)
1057
1058 - def __plannedChangeIndex(self, string):
1059 """__plannedChangeIndex(string) 1060 - this function is used to change the order in the table of the planer tab 1061 - it edits the dictionary not the table ! 1062 - string must be one of the following: 1063 - Remove : removes selected entry 1064 - Up: moves the entry up --> lower index 1065 - Down: moves the entry down --> higher index 1066 """ 1067 #check if something is selected 1068 try: 1069 item = self.__p_planned_trials.selectedItems()[0] 1070 index = int(str(item.text(0))) 1071 last_index = len(self.__generated_trials.keys())-1 1072 except: 1073 self.__popUp("No item selected") 1074 return 1075 #remove item 1076 if string == "Remove": 1077 for i in range(index,len(self.__generated_trials.keys())-1, 1): 1078 self.__generated_trials[i] = self.__generated_trials[i+1] 1079 del(self.__generated_trials[last_index]) 1080 #switch positions --> decrement index 1081 elif string == "Up" and index > 0: 1082 temp = self.__generated_trials[index-1] 1083 self.__generated_trials[index-1] = self.__generated_trials[index] 1084 self.__generated_trials[index] = temp 1085 index -= 1 1086 #switch positions --> increment index 1087 elif string == "Down" and index < last_index: 1088 temp = self.__generated_trials[index+1] 1089 self.__generated_trials[index+1] = self.__generated_trials[index] 1090 self.__generated_trials[index] = temp 1091 index += 1 1092 self.__refreshPlaner() 1093 if len(self.__generated_trials.keys()) > 0: 1094 item = self.__p_planned_trials.topLevelItem(index) 1095 self.__p_planned_trials.setItemSelected(item, True) 1096 #disable Start button if table empty 1097 else: 1098 self.__p_pushbuttons["Start"].setEnabled(False)
1099
1100 - def __refreshBrowser(self):
1101 """__refreshBrowser(parser) 1102 - this function is used to read the data from the given XML file as parser 1103 - it reads the data and creates entries to a TreeWidget 1104 - it also generates dictionaries with the statistic information of every file 1105 - this dictionary will be displayed when the file is selected in the browser 1106 1107 Attention: Larger datafiles need time to load --> very big files need several minutes 1108 This function should be called in an extra thread or the OS will register a hang up of the GUI. 1109 """ 1110 #clear old data 1111 self.__d_data_browser.clear() 1112 self.__d_data_params.clear() 1113 self.__d_data_char.clear() 1114 parser = XMLParser(self.__dataxml, "datafile") 1115 1116 #dictionaries for tree 1117 #top level of tree are data structures 1118 #second level are algorithms 1119 #third level are benchmarks 1120 #last level are the single files 1121 self.__d_datastructure_items = {} 1122 self.__d_algorithm_items = {} 1123 self.__d_benchmark_items = {} 1124 self.__d_trial_name_items = {} 1125 self.__d_file_items = {} 1126 self.__dtreeinfotext = {} 1127 self.__dtreeparamtext = {} 1128 self.__d_file_information = {} 1129 1130 #getting entries from XML file 1131 for i in range(parser.countTopLevelTags()): 1132 dict = parser.nextTopLevelTag(i) 1133 #get main information 1134 try: 1135 datastructure = dict["datastructure"] 1136 algorithm = dict["algorithm"] 1137 benchmark = dict["benchmark"] 1138 trial_name = dict["trial_name"] 1139 cost_criteria = dict["cost_criteria"] 1140 trial_date = dict["trial_date"] 1141 runtime = dict["runtime"] 1142 z_dimension = dict["z-Dimension"] 1143 except: 1144 self.__popUp("Error! XML file could not be read!") 1145 return 1146 #create entries for dictionaries 1147 #avoids doubled entries 1148 if datastructure not in self.__d_datastructure_items.keys(): 1149 toplevelitem = QtGui.QTreeWidgetItem() 1150 toplevelitem.setText(0, datastructure) 1151 self.__d_data_browser.addTopLevelItem(toplevelitem) 1152 self.__d_datastructure_items.update({datastructure : toplevelitem}) 1153 if datastructure+algorithm not in self.__d_algorithm_items.keys(): 1154 item = QtGui.QTreeWidgetItem() 1155 item.setText(0, algorithm) 1156 self.__d_datastructure_items[datastructure].addChild(item) 1157 self.__d_algorithm_items.update({datastructure+algorithm : item}) 1158 if datastructure+algorithm+benchmark not in self.__d_benchmark_items.keys(): 1159 item = QtGui.QTreeWidgetItem() 1160 item.setText(0, benchmark) 1161 self.__d_algorithm_items[datastructure+algorithm].addChild(item) 1162 self.__d_benchmark_items.update({datastructure+algorithm+benchmark : item}) 1163 if datastructure+algorithm+benchmark+trial_name not in self.__d_trial_name_items.keys(): 1164 item = QtGui.QTreeWidgetItem() 1165 item.setText(0, trial_name) 1166 self.__d_benchmark_items[datastructure+algorithm+benchmark].addChild(item) 1167 self.__d_trial_name_items.update({datastructure+algorithm+benchmark+trial_name : item}) 1168 1169 #build last level of tree --> files 1170 for criteria in cost_criteria.keys(): 1171 1172 criteria_dict = cost_criteria[criteria] 1173 filename = criteria_dict["filename"] 1174 item = QtGui.QTreeWidgetItem() 1175 identification_name = os.path.basename(filename) 1176 #set information for tree 1177 item.setText(0, identification_name) 1178 #change runtime time stamp 1179 item.setText(1,time.strftime("%H:%M:%S", time.gmtime(float(runtime)))) 1180 self.__d_trial_name_items[datastructure+algorithm+benchmark+trial_name].addChild(item) 1181 self.__d_file_items.update({identification_name : filename}) 1182 self.__d_file_information.update({filename : dict}) 1183 1184 #get parameter information about the algorithm and save them into dictionary for this file 1185 param_keys = list(set(dict.keys()) & set(PARAMETER_LIST[algorithm].keys())) 1186 param_names =[] 1187 param_values = [] 1188 param_names += ["z-Dimension"] 1189 param_values += [z_dimension] 1190 for key in param_keys: 1191 param_names.append(key) 1192 param_values.append(dict[key]) 1193 self.__dtreeparamtext.update({filename : [param_names, param_values]}) 1194 1195 #get statistic data for the file and save them 1196 #seperate mean_samples which need only be displayed for SUM criteria 1197 char_names = [] 1198 char_values = [] 1199 try: 1200 mean_samples = dict["mean_samples"] 1201 if mean_samples != None and criteria == "SUM": 1202 char_names.append("mean_samples") 1203 char_values.append(mean_samples) 1204 except: 1205 pass 1206 for key in criteria_dict: 1207 char_names.append(key) 1208 char_values.append(criteria_dict[key]) 1209 self.__dtreeinfotext.update({filename : [char_names, char_values]}) 1210 #sort the complete tree alphabetic 1211 self.__d_data_browser.sortItems(0, QtCore.Qt.AscendingOrder)
1212
1213 - def __dataview_fit(self):
1214 """__dataview_fit() 1215 - fits the data explorer column size to content 1216 - a pretty print function for user 1217 """ 1218 for col in range(0,self.__d_data_browser.columnCount(),1): 1219 self.__d_data_browser.resizeColumnToContents(col)
1220
1221 - def __datainfo(self):
1222 """__datainfo() 1223 - this function shows the information about a datafile 1224 - it reads the selected data file in the browser and shows the information from the XML file 1225 """ 1226 #clear the trees 1227 self.__d_data_char.clear() 1228 self.__d_data_params.clear() 1229 item = self.__d_data_browser.currentItem() 1230 #get filename 1231 ident = str(item.text(0)) 1232 try: 1233 filename = self.__d_file_items[ident] 1234 except KeyError: 1235 #self.__popUp("No information available!") 1236 return 1237 1238 #get information from dictionaries 1239 try: 1240 char_lists = self.__dtreeinfotext[filename] 1241 param_lists = self.__dtreeparamtext[filename] 1242 1243 for i in range(0,len(char_lists[0]),1): 1244 item = QtGui.QTreeWidgetItem() 1245 item.setText(0,char_lists[0][i].replace("_", " ")) 1246 item.setText(1,char_lists[1][i]) 1247 self.__d_data_char.addTopLevelItem(item) 1248 for i in range(0,len(param_lists[0]),1): 1249 item = QtGui.QTreeWidgetItem() 1250 item.setText(0,param_lists[0][i].replace("_", " ")) 1251 item.setText(1,param_lists[1][i]) 1252 self.__d_data_params.addTopLevelItem(item) 1253 #fit column size to content 1254 for i in range(0,self.__d_data_char.columnCount(),1): 1255 self.__d_data_char.resizeColumnToContents(i) 1256 for i in range(0,self.__d_data_params.columnCount(),1): 1257 self.__d_data_params.resizeColumnToContents(i) 1258 #sort items alphabetic 1259 self.__d_data_char.sortItems(0, QtCore.Qt.AscendingOrder) 1260 self.__d_data_params.sortItems(0, QtCore.Qt.AscendingOrder) 1261 except: 1262 #self.__popUp("No information available!") 1263 return
1264
1265 - def __popUp(self, warn_text):
1266 """__popUp(warn_text) 1267 - displays a dialog with the text given by warn_text 1268 - closed by an OK button 1269 - is used to inform user about a problem 1270 """ 1271 1272 #create dialog, layout, label an button 1273 popup = QtGui.QDialog(self) 1274 popup.setWindowTitle("Warning") 1275 poplayout = QtGui.QVBoxLayout() 1276 popup.setLayout(poplayout) 1277 poplabel = QtGui.QLabel() 1278 poplabel.setText(warn_text) 1279 popok = QtGui.QPushButton() 1280 popok.setText("Ok") 1281 popbl = QtGui.QHBoxLayout() 1282 popbl.addStretch() 1283 popbl.addWidget(popok) 1284 popbl.addStretch() 1285 poplabel.setFont(self.__font) 1286 popok.setFont(self.__font) 1287 poplayout.addWidget(poplabel) 1288 poplayout.addLayout(popbl) 1289 #link button with closing event for dialog 1290 self.connect(popok, QtCore.SIGNAL("clicked()"), popup.close) 1291 poplabel.setAlignment(QtCore.Qt.AlignCenter) 1292 popok.setMaximumWidth(50) 1293 popup.show()
1294
1295 - def __startCalc(self):
1296 """__startCalc() 1297 - starts the preparation for the calculation of data files 1298 - estimates time for calculation 1299 """ 1300 #getting process priority 1301 priotity = self.__radiobutton_group.checkedId() 1302 self.__generator = Generator(self.__generated_trials, priotity, time_check = True) 1303 #start time estimation 1304 self.__generator.start() 1305 self.__runDialog = QtGui.QProgressDialog("Calculation running...", "Cancel", 0,self.__generator.total, self) 1306 self.__runDialog.setWindowTitle("DSC") 1307 self.__runDialog.setValue(0) 1308 self.__runDialog.show() 1309 self.__timer = QtCore.QBasicTimer() 1310 self.__timer.start(100, self) 1311 return
1312
1313 - def __showTimeEstimation(self):
1314 """__showTimeEstimation() 1315 - shows time dialog 1316 - called after startCalc() 1317 """ 1318 #close run dialog 1319 self.__runDialog.close() 1320 del(self.__runDialog) 1321 #time estimation in pretty format 1322 string = " Time estimation for calculation\n\n" 1323 string +="Task \t\t Time\n" 1324 for i in range(1,len(self.__generator.printabletimes)+1,1): 1325 if i < len(self.__generator.printabletimes): 1326 string += str(i)+"\t\t"+self.__generator.printabletimes[i-1]+"\n" 1327 else: 1328 string += "\nTotal time: \t\t"+self.__generator.printabletimes[i-1] 1329 del(self.__generator) 1330 #open dialog for time estimation 1331 try: 1332 self.__calcDialog.close() 1333 except AttributeError: 1334 pass 1335 #Dialog 1336 self.__calcDialog = QtGui.QDialog(self) 1337 self.__calcDialog.setWindowTitle("Time estimation") 1338 calcLayout = QtGui.QVBoxLayout() 1339 self.__calcDialog.setLayout(calcLayout) 1340 #Label 1341 dlabel = QtGui.QLabel() 1342 dlabel.setText(string) 1343 calcLayout.addWidget(dlabel) 1344 #Buttons 1345 dblayout = QtGui.QHBoxLayout() 1346 dbcancel = QtGui.QPushButton() 1347 dbcancel.setText("Cancel") 1348 dbok = QtGui.QPushButton() 1349 dbok.setText("Run") 1350 dblayout.addWidget(dbcancel) 1351 dblayout.addWidget(dbok) 1352 calcLayout.addLayout(dblayout) 1353 #connecting buttons 1354 self.connect(dbcancel, QtCore.SIGNAL("clicked()"), self.__calcDialog.close) 1355 self.connect(dbok, QtCore.SIGNAL("clicked()") , self.__runCalc) 1356 self.__calcDialog.show() 1357 self.__statusbar.showMessage("Time estimated")
1358
1359 - def __runCalc(self):
1360 """__runCalc() 1361 - runs calculation in seperate thread 1362 - shows dialog 1363 - starts event timer (is stopped when thread for calculation is no longer alive --> see override timerEvent) 1364 """ 1365 #new Generator without time_check 1366 priotity = self.__radiobutton_group.checkedId() 1367 self.__generator = Generator(self.__generated_trials, priotity, time_check = False) 1368 #close Dialog 1369 self.__calcDialog.close() 1370 self.__statusbar.showMessage("Calculation started") 1371 #start thread 1372 self.__generator.start() 1373 #show run dialog 1374 self.__runDialog = QtGui.QProgressDialog("Calculation running...", "Cancel", 0,self.__generator.total, self) 1375 self.__runDialog.setWindowTitle("DSC") 1376 self.__runDialog.setValue(0) 1377 self.__runDialog.show() 1378 #starts event timer 1379 self.__timer = QtCore.QBasicTimer() 1380 self.__timer.start(500, self)
1381
1382 - def __finishCalc(self):
1383 """__finishCalc() 1384 - writes new content into XML file 1385 - clears the table 1386 """ 1387 #write data to XML file 1388 #uses the same dictionary form as generated trials but with additional data from generator 1389 self.__runDialog.setLabelText("Writing new datafiles to database") 1390 data_to_write = self.__generator.todo 1391 dict = {} 1392 #clear planer table 1393 self.__p_planned_trials.clear() 1394 for index in data_to_write.keys(): 1395 dict.update({index : {}}) 1396 dict[index].update(data_to_write[index]["individual_params"]) 1397 dict[index].update(data_to_write[index]["init_params"]) 1398 #write new data to XML 1399 parser = XMLParser(self.__dataxml, "datafile") 1400 parser.writeNewData(dict) 1401 #clear memory to avoid overlapping of different runs 1402 del(dict) 1403 del self.__generator 1404 del self.__generated_trials 1405 self.__runDialog.close() 1406 self.__statusbar.showMessage("Calculation finished") 1407 #refresh data browser 1408 self.__refreshBrowser()
1409
1410 - def __evaluate(self, buttonname):
1411 """__evaluate(buttonname) 1412 - in this version it shows a dialog to adjust diagram option 1413 - prepares the evaluation 1414 - supports only diagrams at the moment 1415 1416 Attention: this part of the program is still under development and can cause problems 1417 """ 1418 #Attention: 1419 #The evaluation part of the program is beta version only 1420 #This function must be re-designed as the function __showDiagram() 1421 1422 #getting selected files 1423 selected_entries = self.__d_data_browser.selectedItems() 1424 self.__evaluable_entries = [] 1425 for item in selected_entries: 1426 if item.childCount() == 0: 1427 self.__evaluable_entries.append(item) 1428 1429 if len(self.__evaluable_entries) == 0: 1430 self.__popUp("No evaluable entries selected!") 1431 return 1432 1433 #show dialog for diagram adjustment 1434 dialog = QtGui.QDialog(self.__central) 1435 dialog.setWindowTitle("Choose diagram options") 1436 layout = QtGui.QVBoxLayout() 1437 dialog.setLayout(layout) 1438 tabs = QtGui.QTabWidget() 1439 layout.addWidget(tabs) 1440 1441 #create dialog tabs and options 1442 button_layout = QtGui.QHBoxLayout() 1443 ok = QtGui.QPushButton("Ok") 1444 ok.setMaximumWidth(150) 1445 cancel = QtGui.QPushButton("Cancel") 1446 cancel.setMaximumWidth(150) 1447 button_layout.addWidget(ok) 1448 button_layout.addWidget(cancel) 1449 layout.addLayout(button_layout) 1450 self.connect(cancel, QtCore.SIGNAL("clicked ()"), dialog.close) 1451 self.connect(ok, QtCore.SIGNAL("clicked ()"), self.__showDiagram) 1452 self.connect(ok, QtCore.SIGNAL("clicked ()"), dialog.close) 1453 1454 self.__d_diagramoptions = {} 1455 1456 def create_structure(tab_entry, layout, saving_key): 1457 if type(tab_entry) == dict: 1458 for key in tab_entry.keys(): 1459 box = QtGui.QGroupBox(key) 1460 box_layout = QtGui.QHBoxLayout() 1461 box.setLayout(box_layout) 1462 layout.addWidget(box) 1463 create_structure(tab_entry[key], box_layout, saving_key+key) 1464 elif type(tab_entry) == list: 1465 datatype = tab_entry[0] 1466 widget = eval(DATATYPE_LIST[datatype]) 1467 widget.setToolTip(tab_entry[1]) 1468 layout.addWidget(widget) 1469 self.__d_diagramoptions.update({saving_key : widget}) 1470 function_list = LIMITFUNCTION_LIST[datatype] 1471 i = 0 1472 for i in range(0,len(function_list),1): 1473 eval("widget."+function_list[i]+"(tab_entry[i+2])") 1474 else: 1475 self.__popUp("Warning! Check %s in config file." % (tab))
1476 1477 for tab in DIAGRAM_PARAMETER_LIST.keys(): 1478 widget = QtGui.QWidget() 1479 layout = QtGui.QVBoxLayout() 1480 widget.setLayout(layout) 1481 tabs.addTab(widget, tab) 1482 create_structure(DIAGRAM_PARAMETER_LIST[tab], layout, tab) 1483 1484 self.__eval_func = EVALUATION_PLOT_LIST[buttonname][0] 1485 dialog.show() 1486
1487 - def __showDiagram(self):
1488 """__showDiagram() 1489 - calls the evaluation function 1490 - displayes the diagram 1491 1492 Attention: this part of the program is still under development and can cause problems 1493 In this version it is only designed to display diagrams. But it is planed to extend this function 1494 to a greater field of evaluation possibilities - even a interactive console mode for direct python interface 1495 """ 1496 1497 #read out the parameters for diagram adjustment 1498 #read out information from the XML file about the given files 1499 filenames = [] 1500 information = {} 1501 for item in self.__evaluable_entries: 1502 ident = str(item.text(0)) 1503 filename = self.__d_file_items[ident] 1504 filenames.append(filename) 1505 information.update({filename : self.__d_file_information[filename]}) 1506 1507 parameter = {} 1508 def load_parameter(tab_entry, load_key, current_key, sav_dict): 1509 if type(tab_entry) == dict: 1510 for key in tab_entry.keys(): 1511 if type(tab_entry[key]) == dict: 1512 sav_dict.update({key : {}}) 1513 load_parameter(tab_entry[key], load_key+key, key, sav_dict[key]) 1514 else: 1515 load_parameter(tab_entry[key], load_key+key, key, sav_dict) 1516 elif type(tab_entry) == list: 1517 datatype = tab_entry[0] 1518 function = READFUNCTION_LIST[datatype] 1519 widget = self.__d_diagramoptions[load_key] 1520 param = eval(datatype+"(widget."+function+"())") 1521 sav_dict.update({current_key : param}) 1522 else: 1523 self.__popUp("Warning! Check %s in config file." % (tab))
1524 1525 for tab in DIAGRAM_PARAMETER_LIST.keys(): 1526 parameter.update({tab : {}}) 1527 load_parameter(DIAGRAM_PARAMETER_LIST[tab], tab, tab, parameter[tab]) 1528 #try to create diagram 1529 #try: 1530 file = self.__eval_func(filenames, information, parameter, create_png = True) 1531 #except: 1532 # self.__popUp("Failure!") 1533 # return 1534 #show diagram in a dialog with scolbars 1535 graphic_dialog = QtGui.QDialog(self.__central) 1536 pixmap = QtGui.QPixmap(FFPLOTS+"/"+file) 1537 graphic_view = QtGui.QGraphicsView() 1538 graphic_scene = QtGui.QGraphicsScene() 1539 graphic_scene.addPixmap(pixmap) 1540 graphic_view.setScene(graphic_scene) 1541 graphic_dialog_layout = QtGui.QHBoxLayout() 1542 graphic_dialog_layout.addWidget(graphic_view) 1543 graphic_dialog.setLayout(graphic_dialog_layout) 1544 graphic_dialog.show() 1545 1546 '''Just for old files 1547 def __import(self, path): 1548 """__import(path) 1549 - gets an file name with path 1550 - tries to extract information from the filename about the trial 1551 - user must check the extracted information for correctness 1552 1553 Attention: 1554 This function will be erased from later versions and is only for import old files. 1555 """ 1556 #split filename 1557 for key in self.__m_inputElements.keys(): 1558 self.__m_inputElements[key].clear() 1559 1560 self.__m_inputElements["filename"].setText(path) 1561 file = os.path.split(path)[1] 1562 name = os.path.splitext(file)[0] 1563 list = name.split("-") 1564 for word in list: 1565 if word.isupper(): 1566 list[list.index(word)] = word.strip() 1567 continue 1568 list[list.index(word)] = word.replace("_", " ").title().strip() 1569 #defines the extract function 1570 def tryImport(list): 1571 i = 0 1572 for key in OPTIMIZATION_LIST.keys(): 1573 if key in list: 1574 self.__m_inputElements["algorithm"].setText(key) 1575 i +=1 1576 break 1577 1578 for key in BENCHMARK_LIST.keys(): 1579 key = key.rstrip(".yal").capitalize() 1580 if key in list: 1581 key = key.lower()+".yal" 1582 self.__m_inputElements["benchmark"].setText(key) 1583 i +=1 1584 break 1585 1586 for key in DATA_STRUCTURE_LIST.keys(): 1587 nkey = key.replace("-"," ") 1588 if nkey in list: 1589 self.__m_inputElements["datastructure"].setText(key) 1590 i +=1 1591 break 1592 nkey = key.replace("-","") 1593 nkey = nkey.title() 1594 if nkey in list: 1595 self.__m_inputElements["datastructure"].setText(key) 1596 i +=1 1597 break 1598 1599 for key in COST_LIST.keys(): 1600 if key in list: 1601 self.__m_inputElements["cost criteria"].setText(key) 1602 i +=1 1603 break 1604 1605 for word in list: 1606 if "Samples" in word: 1607 self.__m_inputElements["samples"].setText(word.strip("Samples")) 1608 return i 1609 #if import did not work try another split method 1610 if tryImport(list) < 3: 1611 for key in self.__m_inputElements.keys(): 1612 self.__m_inputElements[key].clear() 1613 self.__m_inputElements["filename"].setText(path) 1614 list = name.split(" ") 1615 list[0] = list.pop(0)+ " " +list.pop(0) 1616 for word in list: 1617 if word.isupper(): 1618 continue 1619 list[list.index(word)] = word.title() 1620 if word.isdigit(): 1621 list[list.index(word)] = word + " Samples" 1622 if tryImport(list) < 3: 1623 for key in self.__m_inputElements.keys(): 1624 self.__m_inputElements[key].clear() 1625 1626 def __updateXML(self): 1627 """__updateXML() 1628 - writes the data from the managing tab into the XML file 1629 1630 Attention: 1631 This function will be erased from later versions and is only for import old files. 1632 """ 1633 1634 #generate statistic data 1635 self.__m_pushbuttons["Characteristics"].click() 1636 #getting information from managing tab 1637 dict = {} 1638 for key in self.__m_inputElements.keys(): 1639 if key == "filename" or key == "runtime": 1640 continue 1641 if str(self.__m_inputElements[key].text()) == "" and key != "z-D": 1642 self.__popUp("Missing parameters") 1643 return 1644 if str(self.__m_inputElements[key].text()) == "" and key == "z-D": 1645 self.__m_inputElements[key].setText("auto") 1646 dict.update({key.replace(" ", "_"): str(self.__m_inputElements[key].text())}) 1647 if key == "cost criteria": 1648 innerdict = {str(self.__m_inputElements[key].text()): {}} 1649 dict.update({key.replace(" ", "_"): innerdict}) 1650 1651 for key in self.__m_charact_labels.keys(): 1652 tag = key.replace(" ", "_") 1653 value = str(self.__m_charact_labels[key].text()) 1654 dict["cost_criteria"][str(self.__m_inputElements["cost criteria"].text())].update({tag : value}) 1655 #write data 1656 filename = str(self.__m_inputElements["filename"].text()) 1657 filename = os.path.split(filename)[1] 1658 dict["cost_criteria"][str(self.__m_inputElements["cost criteria"].text())].update({"filename": filename}) 1659 filename = str(self.__m_inputElements["runtime"].text()) 1660 dict["cost_criteria"][str(self.__m_inputElements["cost criteria"].text())].update({"runtime": filename}) 1661 XMLParser(self.__dataxml).writeNewData({0:dict}, "datafile") 1662 1663 self.__refreshBrowser() 1664 '''
1665 - def __gen_info_func(self, viewwidget, LOOK_IN_LIST, position):
1666 """__gen_info_func(string) 1667 - defines a dynamic function for the call of __infoText(string) 1668 - gets the text of the current item of the viewwidget (Table, Tree, List) 1669 - gets an dictionary from config --> text of item must be key in this dict 1670 - position defines the position of the infoText in list in config dict 1671 Usage only for viewwidgets and in planer area tab !! 1672 """ 1673 def click(): 1674 text = str(viewwidget.currentItem().text()) 1675 self.__infoText(str(LOOK_IN_LIST[text][position]))
1676 return click 1677
1678 - def __gen_eval_func(self, string):
1679 """__gen_eval_func(string) 1680 - defines a dynamic function for the call of __evaluate(string) 1681 - string is passed over to __evaluate() 1682 - designed for dynamic creation of different evaluation plots 1683 """ 1684 a = string 1685 def click(): 1686 self.__evaluate(a)
1687 return click 1688
1689 - def __gen_index_change_func(self, string):
1690 """__gen_index_change_func(string) 1691 - defines a dynamic function for the call of plannedChangeIndex(string) 1692 - string is passed over to __plannedChangeIndex(string) 1693 """ 1694 a = string 1695 def index_change(): 1696 self.__plannedChangeIndex(a)
1697 return index_change 1698 1699 dsc = DSC() 1700