def _import_from_directory(self, fname): try: try: self.data = DirectoryData(unicode(fname)) except IOError as e: em = QtGui.QErrorMessage(self) em.setModal(True) em.showMessage( ("Failed to open directory (%s).\n" % str(e)) + "I will try now to import files in deprecated format.") # If we do not call exec_ here, two dialogs may appear at # the same time, confusing the user. em.exec_() self.data = OldDirectoryData(unicode(fname)) self.set_location(fname) self.update_lists() self.clear() except IOError as e: em = QtGui.QErrorMessage(self) em.setModal(True) em.exec_() em.showMessage( "Failed to open directory (%s).\n" % str(e))
class DesignerMainWindow(QtGui.QMainWindow, Ui_MainWindow): """Customization for Qt Designer created window""" def __init__(self, parent = None): # initialization of the superclass super(DesignerMainWindow, self).__init__(parent) # setup the GUI --> function generated by pyuic4 self.setupUi(self) # In some lists we can select more than one item self.speciesList.setSelectionMode( QtGui.QAbstractItemView.ExtendedSelection) self.reactList.setSelectionMode( QtGui.QAbstractItemView.ExtendedSelection) for w in [self.reactList, self.speciesList, self.speciesSourceList, self.condList]: w.horizontalHeader().setVisible(True) self.plot_widgets = [self.condWidget, self.densWidget, self.reactWidget, self.sourceWidget] self.update_timer = QtCore.QTimer() self.latest_dir = "." # connect the signals with the slots QtCore.QObject.connect(self.condButton, QtCore.SIGNAL("clicked()"), self.update_cond_graph) QtCore.QObject.connect(self.plotButton, QtCore.SIGNAL("clicked()"), self.update_spec_graph) QtCore.QObject.connect(self.sourceButton, QtCore.SIGNAL("clicked()"), self.update_source_graph) QtCore.QObject.connect(self.reactButton, QtCore.SIGNAL("clicked()"), self.update_react_graph) QtCore.QObject.connect(self.actionOpen, QtCore.SIGNAL('triggered()'), self.select_file) QtCore.QObject.connect(self.actionStart_a_simulation, QtCore.SIGNAL('triggered()'), self.start_a_simulation) QtCore.QObject.connect(self.actionImport_from_directory, QtCore.SIGNAL('triggered()'), self.import_from_directory) QtCore.QObject.connect(self.actionUpdate, QtCore.SIGNAL('triggered()'), self.data_update) QtCore.QObject.connect(self.actionExport_data, QtCore.SIGNAL('triggered()'), self.export_data) QtCore.QObject.connect(self.actionSave, QtCore.SIGNAL('triggered()'), self.save_to_file) QtCore.QObject.connect(self.actionLog_scale_in_time, QtCore.SIGNAL('triggered()'), self.action_set_logtime) QtCore.QObject.connect(self.actionQuit, QtCore.SIGNAL('triggered()'), QtGui.qApp, QtCore.SLOT("quit()")) QtCore.QObject.connect(self.update_timer, QtCore.SIGNAL("timeout()"), self.data_update) # Drag'n'Drop. Implemented by Marc Foletto. def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.acceptProposedAction() # Drag'n'Drop. def dropEvent(self, event): if event.mimeData().hasUrls(): for url in event.mimeData().urls(): fname = url.toLocalFile() self.import_file_or_dir(fname) event.acceptProposedAction() #Chose if drop is a file or a directory def import_file_or_dir(self, path): if os.path.exists(path): if os.path.isdir(path): self._import_from_directory(path) else: # Let us allow the user to import files with any extension: # if they are not in hdf5 format and exception will be raised # anyhow. self.load_h5file(path) def set_location(self, location): """ Sets the opened location. """ self.setWindowTitle("%s - QtPlaskin" % location) self.location = location @property def xscale(self): if self.actionLog_scale_in_time.isChecked(): return 'log' else: return 'linear' def update_cond_graph(self): """Updates the graph with densities""" try: condition = list(iter_2_selected(self.condList))[0][0] except AttributeError: return # clear the Axes if not self.condWidget.axes: self.condWidget.init_axes() else: self.condWidget.clear() QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.WaitCursor)) y = array(self.data.condition(condition)) condition_name = self.data.conditions[condition - 1] flt = y > 0 label = CONDITIONS_PRETTY_NAMES.get(condition_name, condition_name) self.condWidget.axes[0].plot(self.data.t[flt], y[flt], lw=LINE_WIDTH, label=label, zorder=10) self.condWidget.set_scales(yscale='linear', xscale=self.xscale) self.condWidget.axes[0].set_xlabel("t [s]") self.condWidget.axes[0].set_ylabel(label) # force an image redraw self.condWidget.draw() self.condWidget.add_data(self.data.t, y, label) QtGui.QApplication.restoreOverrideCursor() def update_spec_graph(self): """Updates the graph with densities""" # clear the Axes if not self.speciesList.selectedItems(): return if not self.densWidget.axes: self.densWidget.init_axes() else: self.densWidget.clear() QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.WaitCursor)) self.data.flush() citer = cycle(COLOR_SERIES) for item in iter_2_selected(self.speciesList): name = item[1] dens = self.data.density(item[0]) flt = dens > DENS_THRESHOLD self.densWidget.axes[0].plot(self.data.t[flt], dens[flt], lw=LINE_WIDTH, c=citer.next(), label=name, zorder=10) self.densWidget.add_data(self.data.t, dens, name) self.densWidget.set_scales(yscale='log', xscale=self.xscale) self.densWidget.axes[0].set_xlabel("t [s]") self.densWidget.axes[0].set_ylabel("Density [cm$^\mathdefault{-3}$]") self.densWidget.axes[0].legend(loc=(1.05, 0.0), prop=dict(size=11)) # force an image redraw self.densWidget.draw() QtGui.QApplication.restoreOverrideCursor() def update_source_graph(self): """Updates the graph with sources rates""" try: species = list(iter_2_selected(self.speciesSourceList))[0] except AttributeError: return # clear the Axes if not self.sourceWidget.axes: self.sourceWidget.init_axes() else: self.sourceWidget.clear() QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.WaitCursor)) dreactions = self.data.sources(species[0]) reactions = dreactions.keys() r = zeros((len(reactions), len(self.data.t))) for i, react in enumerate(reactions): r[i, :] = dreactions[react] # Find the reactions that are at some point at least a delta of the total filters = {0: (0.1, -1), 1: (0.01, -1), 2: (0.001, -1), 3: (1e-4, -1), 4: (0.0, -1)} delta, max_rates = filters[self.Combo_filter.currentIndex()] spos = nanmax(where(r > 0, r, 0), axis=0) fpos = r / spos # This is b.c. numpy does not provide a nanargsort fpos = where(isfinite(fpos), fpos, 0) sneg = nanmin(where(r < 0, r, 0), axis=0) fneg = r / sneg # This is b.c. numpy does not provide a nanargsort fneg = where(isfinite(fneg), fneg, 0) icreation = select_rates(fpos, delta, max_rates=max_rates) idestruct = select_rates(fneg, delta, max_rates=max_rates) citer = cycle(COLOR_SERIES) for i in icreation: name = self.data.reactions[reactions[i]] flt = abs(r[i, :]) > RATE_THRESHOLD label = "[%d] %s" % (reactions[i] + 1, name) self.sourceWidget.creationAx.plot(self.data.t[flt], abs(r[i, flt]), c=citer.next(), lw=LINE_WIDTH, label=label, zorder=10) self.sourceWidget.add_data(self.data.t, r[i, :], label) citer = cycle(COLOR_SERIES) for i in idestruct: name = self.data.reactions[reactions[i]] flt = abs(r[i, :]) > RATE_THRESHOLD label = "[%d] %s" % (reactions[i] + 1, name) self.sourceWidget.removalAx.plot(self.data.t[flt], abs(r[i, flt]), c=citer.next(), lw=LINE_WIDTH, label=label, zorder=10) self.sourceWidget.add_data(self.data.t, r[i, :], "- " + label) self.sourceWidget.creationAx.set_ylabel( "Production [cm$^\mathdefault{-3}$s$^\mathdefault{-1}$]") self.sourceWidget.creationAx.legend(loc=(1.05, 0.0), prop=dict(size=9)) self.sourceWidget.removalAx.set_ylabel( "Losses [cm$^\mathdefault{-3}$s$^\mathdefault{-1}$]") self.sourceWidget.removalAx.set_xlabel("t [s]") self.sourceWidget.removalAx.legend(loc=(1.05, 0.0), prop=dict(size=9)) self.sourceWidget.set_scales(yscale='log', xscale=self.xscale) # force an image redraw self.sourceWidget.draw() QtGui.QApplication.restoreOverrideCursor() def update_react_graph(self): """Updates the graph with reaction rates""" if not self.reactList.selectedItems(): return # clear the Axes if not self.reactWidget.axes: self.reactWidget.init_axes() else: self.reactWidget.clear() QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.WaitCursor)) citer = cycle(COLOR_SERIES) for item in iter_2_selected(self.reactList): name = item[1] rate = array(self.data.rate(item[0])) flt = rate > RATE_THRESHOLD label = "[%d] %s" % (item[0], name) self.reactWidget.axes[0].plot(self.data.t[flt], rate[flt], c=citer.next(), lw=LINE_WIDTH, label=label, zorder=10) self.reactWidget.add_data(self.data.t, rate, label) self.reactWidget.set_scales(yscale='log', xscale=self.xscale) self.reactWidget.axes[0].set_xlabel("t [s]") self.reactWidget.axes[0].set_ylabel( "Rate [cm$^\mathdefault{-3}$s$^\mathdefault{-1}$]") self.reactWidget.axes[0].legend(loc=(1.025, 0.0), prop=dict(size=8)) # force an image redraw self.reactWidget.draw() QtGui.QApplication.restoreOverrideCursor() def select_file(self): """opens a file select dialog""" # open the dialog and get the selected file file = QtGui.QFileDialog.getOpenFileName(self, "Open data file", ".", "HDF5 files (*.h5 *.hdf5);;" "All files (*)") # if a file is selected if file: try: self.load_h5file(unicode(file)) self.set_location(file) self.update_lists() self.clear() except IOError as e: QtGui.QErrorMessage(self).showMessage( "Failed to open file. Incorrect format? <%s>" % e) def start_a_simulation(self): self.data = RealtimeData('fpr_1', 'init_species.dat', 'field_constant.tsv', max_dt=10e-3) self.update_lists() def import_from_directory(self): fname = QtGui.QFileDialog.getExistingDirectory( self, "Import data from directory", self.latest_dir, QtGui.QFileDialog.ShowDirsOnly) self._import_from_directory(fname) self.latest_dir = fname def _import_from_directory(self, fname): try: try: self.data = DirectoryData(unicode(fname)) except IOError as e: em = QtGui.QErrorMessage(self) em.setModal(True) em.showMessage( ("Failed to open directory (%s).\n" % str(e)) + "I will try now to import files in deprecated format.") # If we do not call exec_ here, two dialogs may appear at # the same time, confusing the user. em.exec_() self.data = OldDirectoryData(unicode(fname)) self.set_location(fname) self.update_lists() self.clear() except IOError as e: em = QtGui.QErrorMessage(self) em.setModal(True) em.exec_() em.showMessage( "Failed to open directory (%s).\n" % str(e)) def data_update(self): self.data.update() self.update_cond_graph() self.update_spec_graph() self.update_source_graph() self.update_react_graph() def save_to_file(self): """opens a file select dialog""" # open the dialog and get the selected file fname = QtGui.QFileDialog.getSaveFileName(self, "Save to file", ".", "HDF5 files (*.h5 *.hdf5);;" "All files (*)") # if a file is selected if fname: self.data.save(unicode(fname)) def export_data(self): """opens a file select dialog""" # open the dialog and get the selected file fname = QtGui.QFileDialog.getSaveFileName(self, "Export data to file", ".", "TSV files (*.tsv);;" "TXT files (*.txt);;" "DAT files (*.dat);;" "All files (*)") # if a file is selected if fname: fname = unicode(fname) self.plot_widgets[self.tabWidget.currentIndex()]\ .savedata(fname, self.location) def action_set_logtime(self): for w in self.plot_widgets: w.set_scales(xscale=self.xscale, redraw=True) def load_h5file(self, file): self.data = HDF5Data(file) self.update_lists() self.clear() def update_lists(self): #self.species = sorted(self.data.species) #self.reactions = sorted(self.data.reactions) #self.conditions = sorted(self.data.conditions) def _populate(qtable, list, pretty_names={}): for i in xrange(qtable.rowCount()): qtable.removeRow(0) for n, item in enumerate(list): row = qtable.rowCount() qtable.insertRow(row) # The + 1 is to move to the FORTRAN/ZdPlaskin convention nitem = QtGui.QTableWidgetItem(u'%4d' % (n + 1)) nitem.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) nitem.setTextColor(QtGui.QColor(160, 160, 160)) qtable.setItem(row, 0, nitem) showed_item = pretty_names.get(item, item) sitem = QtGui.QTableWidgetItem(showed_item) sitem.setTextAlignment(Qt.AlignLeft | Qt.AlignVCenter) qtable.setItem(row, 1, sitem) _populate(self.speciesList, self.data.species) _populate(self.speciesSourceList, self.data.species) _populate(self.reactList, self.data.reactions) _populate(self.condList, self.data.conditions, pretty_names=CONDITIONS_PRETTY_NAMES) def clear(self): for w in self.plot_widgets: w.clear() def parse_file(self, filename): pass
def start_a_simulation(self): self.data = RealtimeData('fpr_1', 'init_species.dat', 'field_constant.tsv', max_dt=10e-3) self.update_lists()