def __init__(self, *args, **kwargs): QWidget.__init__(self, *args, **kwargs) self.simulationInterval = None self.updateInterval = None self.runTime = None self.modelRoot = None self.dataRoot = None self.runner = Runner() self.resetAndRunAction = None self.stopAction = None self.continueAction = None self.preferences = preferences self.currentSimulationRuntime = None self.modelType = None self.simulationRuntime = None self.schedulerToolBar = self.getSchedulerToolBar() self.runner.simulationProgressed.connect( self.updateCurrentSimulationRuntime) self.continueFlag = False self.preferences.applyChemicalSettings.connect(self.resetSimulation)
def __init__(self, *args, **kwargs): QtGui.QWidget.__init__(self, *args, **kwargs) self.simulationInterval = None self.updateInterval = None self.runTime = None self.modelRoot = None self.dataRoot = None self.runner = Runner() self.resetAndRunAction = None self.stopAction = None self.continueAction = None self.preferences = preferences self.currentSimulationRuntime = None self.modelType = None self.simulationRuntime = None self.schedulerToolBar = self.getSchedulerToolBar() self.runner.simulationProgressed.connect(self.updateCurrentSimulationRuntime) self.continueFlag = False self.preferences.applyChemicalSettings.connect(self.resetSimulation)
class SchedulingWidget(QtGui.QWidget): """Widget for scheduling. Important member fields: runner - object to run/pause/continue simulation. Whenever `updateInterval` time has been simulated this object sends an `update()` signal. This can be connected to other objects to update their data. SIGNALS: resetAndRun(tickDt, tickTargets, simtime, updateInterval) tickDt: dict mapping tick nos to dt tickTargets: dict mapping ticks to target paths simtime: total simulation runtime updateInterval: interval between update signals are to be emitted. simtimeExtended(simtime) emitted when simulation time is increased by user. """ resetAndRun = QtCore.pyqtSignal(dict, dict, float, float, name='resetAndRun') simtimeExtended = QtCore.pyqtSignal(float, name='simtimeExtended') continueRun = QtCore.pyqtSignal(float, float, name='continueRun') def __init__(self, *args, **kwargs): QtGui.QWidget.__init__(self, *args, **kwargs) self.simulationInterval = None self.updateInterval = None self.runTime = None self.modelRoot = None self.dataRoot = None self.runner = Runner() self.resetAndRunAction = None self.stopAction = None self.continueAction = None self.preferences = preferences self.currentSimulationRuntime = None self.modelType = None self.simulationRuntime = None self.schedulerToolBar = self.getSchedulerToolBar() self.runner.simulationProgressed.connect(self.updateCurrentSimulationRuntime) self.continueFlag = False self.preferences.applyChemicalSettings.connect(self.resetSimulation) def updateCurrentSimulationRuntime(self, time): self.currentSimulationRuntime.setText(str(time)) def getToolBars(self): return [self.schedulerToolBar] def getSchedulerToolBar(self): bar = QToolBar("Run", self) self.resetAction = bar.addAction( QIcon( os.path.join( config.MOOSE_ICON_DIR, 'reset.png' ) ) , 'Reset' , self.resetSimulation ) self.resetAction.setToolTip('Reset simulation.') self.runAction = bar.addAction( QIcon( os.path.join( config.MOOSE_ICON_DIR, 'run.png') ) , 'Run' , self.runSimulation ) self.runAction.setToolTip('Run simulation.') self.stopAction = bar.addAction( QIcon( os.path.join( config.MOOSE_ICON_DIR, 'stop.png') ) , 'Stop' , self.runner.togglePauseSimulation ) self.stopAction.setToolTip('Stop simulation.') bar.addSeparator() runtimeLabel = QLabel('Run for') self.simulationRuntime = QLineEdit() self.simulationRuntime.setValidator(QDoubleValidator()) self.simulationRuntime.setFixedWidth(75) bar.addWidget(runtimeLabel) bar.addWidget(self.simulationRuntime) bar.addWidget(QLabel(' (s)')) bar.addSeparator() #: current time self.currentSimulationRuntime = QLineEdit() # 6 digits self.currentSimulationRuntime.setToolTip('Current simulation runtime.') self.currentSimulationRuntime.setFixedWidth(75) self.currentSimulationRuntime.setValidator(QDoubleValidator()) self.currentSimulationRuntime.setText("0.0") self.currentSimulationRuntime.setReadOnly(True) # self.runner.currentTime.connect(self.currentTimeWidget.display) bar.addWidget(QLabel("Current Time : ")) bar.addWidget(self.currentSimulationRuntime) bar.addWidget(QLabel(" (s)")) bar.addSeparator() self.preferencesButton = QToolButton() self.preferencesButton.setText("Preferences") self.preferencesButton.clicked.connect(self.preferencesToggler) bar.addWidget(self.preferencesButton) return bar def continueSimulation(self): self.runner.continueSimulation( self.runTime , self.updateInterval , self.simulationInterval ) self.simulationRuntime.setText(str(float(self.simulationRuntime.text()) + self.runTime)) def resetSimulation(self): self.setParameters() try: self.runtime = float(runtime) except: self.runtime = 100.0 # print(self.runTime) # print(self.updateInterval) # print(self.simulationInterval) self.currentSimulationRuntime.setText("0.0") self.checkConsistency() # self.preferences.setChemicalClocks() self.simulationRuntime.setText(str(self.runTime)) self.runner.resetSimulation( self.runTime , self.updateInterval , self.simulationInterval ) self.continueFlag = False def runSimulation(self): if self.modelType == CHEMICAL_MODEL: compt = moose.wildcardFind(self.modelRoot+'/##[ISA=ChemCompt]') if not moose.exists(compt[0].path+'/stoich'): chemPref = self.preferences.getChemicalPreferences() solver = chemPref["simulation"]["solver"] addSolver(self.modelRoot,solver) status = self.solverStatus() #print "status ",status # if status != 0 or status == -1: # return if status == None or int(status) == -1 or int(status) == 0: #allow the model to Run pass else: # if something is dangling or solver is not set then return return runtime = str(self.simulationRuntime.text()) try: self.runtime = float(runtime) except: self.runtime = 100.0 self.simulationRuntime.setText("100.0") self.checkConsistency() self.continueSimulation = True self.runner.runSimulation(self.runtime) def setParameters(self): if self.modelType == ELECTRICAL_MODEL: self.setElectricalParameters() elif self.modelType == CHEMICAL_MODEL: self.setChemicalParameters() def setChemicalParameters(self): chemicalPreferences = self.preferences.getChemicalPreferences() self.preferences.initializeChemicalClocks() self.updateInterval = chemicalPreferences["simulation"]["gui-update-interval"] self.simulationInterval = chemicalPreferences["simulation"]["simulation-dt"] if str(self.simulationRuntime.text()) == "": self.simulationRuntime.setText(str(chemicalPreferences["simulation"]["default-runtime"])) self.runTime = float(self.simulationRuntime.text()) self.solver = chemicalPreferences["simulation"]["solver"] def setElectricalParameters(self): electricalPreferences = self.preferences.getElectricalPreferences() self.preferences.initializeElectricalClocks() self.updateInterval = electricalPreferences["simulation"]["gui-update-interval"] self.simulationInterval = electricalPreferences["simulation"]["simulation-dt"] if str(self.simulationRuntime.text()) == "": self.simulationRuntime.setText(str(electricalPreferences["simulation"]["default-runtime"])) self.runTime = float(self.simulationRuntime.text()) self.solver = electricalPreferences["simulation"]["solver"] def checkConsistency(self): if self.updateInterval < self.simulationInterval : self.updateInterval = self.simulationInterval if self.runTime < self.updateInterval : self.runTime = self.updateInterval return True def solverStatus(self): compt = moose.wildcardFind(self.modelRoot+'/##[ISA=ChemCompt]') if not moose.exists(compt[0].path+'/stoich'): return None else: stoich = moose.Stoich(compt[0].path+'/stoich') status = int(stoich.status) # print("Status =>", status) if status == -1: QtGui.QMessageBox.warning(None,"Could not Run the model","Warning: Reaction path not yet assigned.\n ") return -1 if status == 1: QtGui.QMessageBox.warning(None,"Could not Run the model","Warning: Missing a reactant in a Reac or Enz.\n ") return 1 elif status == 2: QtGui.QMessageBox.warning(None,"Could not Run the model","Warning: Missing a substrate in an MMenz.\n ") return 2 elif status == 3: QtGui.QMessageBox.warning(None,"Could not Run the model","Warning: Missing substrates as well as reactants.\n ") return 3 elif status == 4: QtGui.QMessageBox.warning(None,"Could not Run the model"," Warning: Compartment not defined.\n ") return 4 elif status == 8: QtGui.QMessageBox.warning(None,"Could not Run the model","Warning: Neither Ksolve nor Dsolve defined.\n ") return 8 elif status == 16: QtGui.QMessageBox.warning(None,"Could not Run the model","Warning: No objects found on path.\n ") return 16 elif status == 0: print("Successfully built stoichiometry matrix.\n ") # moose.reinit() return 0 def __getAdvanceOptionsButton(self): icon = QtGui.QIcon(os.path.join(config.settings[config.KEY_ICON_DIR],'arrow.png')) # self.advancedOptionsButton.setIcon(QtGui.QIcon(icon)) # self.advancedOptionsButton.setToolButtonStyle( Qt.ToolButtonTextBesideIcon ); return self.advancedOptionsButton def preferencesToggler(self): visibility = not self.preferences.getView().isVisible() self.preferences.getView().setVisible(visibility) def continueSlot(self): pass def updateCurrentTime(self): sys.stdout.flush() self.currentTimeWidget.dispay(str(moose.Clock('/clock').currentTime)) def updateTextFromTick(self, tickNo): tick = moose.vector('/clock/tick')[tickNo] widget = self.tickListWidget.layout().itemAtPosition(tickNo + 1, 1).widget() if widget is not None and isinstance(widget, QtGui.QLineEdit): widget.setText(str(tick.dt)) def updateFromMoose(self): """Update the tick dt from the tick objects""" ticks = moose.vector('/clock/tick') # Items at position 0 are the column headers, hence ii+1 for ii in range(ticks[0].localNumField): self.updateTextFromTick(ii) self.updateCurrentTime() def getSimTime(self): try: time = float(str(self.simtimeEdit.text())) return time except ValueError as e: QtGui.QMessageBox.warning(self, 'Invalid value', 'Specified runtime was meaningless.') return 0 def setDataRoot(self, root='/data'): self.dataRoot = moose.element(root).path def setModelRoot(self, root='/model'): self.modelRoot = moose.element(root).path self.setModelType() def setModelType(self): if moose.exists(self.modelRoot + "/model/cells"): self.modelType = ELECTRICAL_MODEL else: self.modelType = CHEMICAL_MODEL self.resetSimulation()
class SchedulingWidget(QWidget): """Widget for scheduling. Important member fields: runner - object to run/pause/continue simulation. Whenever `updateInterval` time has been simulated this object sends an `update()` signal. This can be connected to other objects to update their data. SIGNALS: resetAndRun(tickDt, tickTargets, simtime, updateInterval) tickDt: dict mapping tick nos to dt tickTargets: dict mapping ticks to target paths simtime: total simulation runtime updateInterval: interval between update signals are to be emitted. simtimeExtended(simtime) emitted when simulation time is increased by user. """ resetAndRun = QtCore.pyqtSignal(dict, dict, float, float, name='resetAndRun') simtimeExtended = QtCore.pyqtSignal(float, name='simtimeExtended') continueRun = QtCore.pyqtSignal(float, float, name='continueRun') def __init__(self, *args, **kwargs): QWidget.__init__(self, *args, **kwargs) self.simulationInterval = None self.updateInterval = None self.runTime = None self.modelRoot = None self.dataRoot = None self.runner = Runner() self.resetAndRunAction = None self.stopAction = None self.continueAction = None self.preferences = preferences self.currentSimulationRuntime = None self.modelType = None self.simulationRuntime = None self.schedulerToolBar = self.getSchedulerToolBar() self.runner.simulationProgressed.connect( self.updateCurrentSimulationRuntime) self.continueFlag = False self.preferences.applyChemicalSettings.connect(self.resetSimulation) def updateCurrentSimulationRuntime(self, time): self.currentSimulationRuntime.setText(str(time)) def getToolBars(self): return [self.schedulerToolBar] def getSchedulerToolBar(self): bar = QToolBar("Run", self) self.resetAction = bar.addAction( QtGui.QIcon(os.path.join(config.MOOSE_ICON_DIR, 'reset.png')), 'Reset', self.resetSimulation) self.resetAction.setToolTip('Reset simulation.') self.runAction = bar.addAction( QtGui.QIcon(os.path.join(config.MOOSE_ICON_DIR, 'run.png')), 'Run', self.runSimulation) self.runAction.setToolTip('Run simulation.') self.stopAction = bar.addAction( QtGui.QIcon(os.path.join(config.MOOSE_ICON_DIR, 'stop.png')), 'Stop', self.runner.togglePauseSimulation) self.stopAction.setToolTip('Stop simulation.') bar.addSeparator() runtimeLabel = QLabel('Run for') self.simulationRuntime = QLineEdit() self.simulationRuntime.setValidator(QtGui.QDoubleValidator()) self.simulationRuntime.setFixedWidth(75) bar.addWidget(runtimeLabel) bar.addWidget(self.simulationRuntime) bar.addWidget(QLabel(' (s)')) bar.addSeparator() #: current time self.currentSimulationRuntime = QLineEdit() # 6 digits self.currentSimulationRuntime.setToolTip('Current simulation runtime.') self.currentSimulationRuntime.setFixedWidth(75) self.currentSimulationRuntime.setValidator(QtGui.QDoubleValidator()) self.currentSimulationRuntime.setText("0.0") self.currentSimulationRuntime.setReadOnly(True) # self.runner.currentTime.connect(self.currentTimeWidget.display) bar.addWidget(QLabel("Current Time : ")) bar.addWidget(self.currentSimulationRuntime) bar.addWidget(QLabel(" (s)")) bar.addSeparator() self.preferencesButton = QToolButton() self.preferencesButton.setText("Preferences") self.preferencesButton.clicked.connect(self.preferencesToggler) bar.addWidget(self.preferencesButton) return bar def continueSimulation(self): self.runner.continueSimulation(self.runTime, self.updateInterval, self.simulationInterval) self.simulationRuntime.setText( str(float(self.simulationRuntime.text()) + self.runTime)) def resetSimulation(self): self.setParameters() try: self.runtime = float(runtime) except: self.runtime = 100.0 # print(self.runTime) # print(self.updateInterval) # print(self.simulationInterval) self.currentSimulationRuntime.setText("0.0") self.checkConsistency() # self.preferences.setChemicalClocks() self.simulationRuntime.setText(str(self.runTime)) self.runner.resetSimulation(self.runTime, self.updateInterval, self.simulationInterval) self.continueFlag = False def runSimulation(self): if self.modelType == CHEMICAL_MODEL: compt = moose.wildcardFind(self.modelRoot + '/##[ISA=ChemCompt]') if not moose.exists(compt[0].path + '/stoich'): chemPref = self.preferences.getChemicalPreferences() solver = chemPref["simulation"]["solver"] mooseAddChemSolver(self.modelRoot, solver) status = self.solverStatus() #print "status ",status # if status != 0 or status == -1: # return if status == None or int(status) == -1 or int(status) == 0: #allow the model to Run pass else: # if something is dangling or solver is not set then return return runtime = str(self.simulationRuntime.text()) try: self.runtime = float(runtime) except: self.runtime = 100.0 self.simulationRuntime.setText("100.0") self.checkConsistency() self.continueSimulation = True self.runner.runSimulation(self.runtime) def setParameters(self): if self.modelType == ELECTRICAL_MODEL: self.setElectricalParameters() elif self.modelType == CHEMICAL_MODEL: self.setChemicalParameters() def setChemicalParameters(self): chemicalPreferences = self.preferences.getChemicalPreferences() self.preferences.initializeChemicalClocks() self.updateInterval = chemicalPreferences["simulation"][ "gui-update-interval"] self.simulationInterval = chemicalPreferences["simulation"][ "simulation-dt"] if str(self.simulationRuntime.text()) == "": self.simulationRuntime.setText( str(chemicalPreferences["simulation"]["default-runtime"])) self.runTime = float(self.simulationRuntime.text()) self.solver = chemicalPreferences["simulation"]["solver"] def setElectricalParameters(self): electricalPreferences = self.preferences.getElectricalPreferences() self.preferences.initializeElectricalClocks() self.updateInterval = electricalPreferences["simulation"][ "gui-update-interval"] self.simulationInterval = electricalPreferences["simulation"][ "simulation-dt"] if str(self.simulationRuntime.text()) == "": self.simulationRuntime.setText( str(electricalPreferences["simulation"]["default-runtime"])) self.runTime = float(self.simulationRuntime.text()) self.solver = electricalPreferences["simulation"]["solver"] def checkConsistency(self): if self.updateInterval < self.simulationInterval: self.updateInterval = self.simulationInterval if self.runTime < self.updateInterval: self.runTime = self.updateInterval return True def solverStatus(self): compt = moose.wildcardFind(self.modelRoot + '/##[ISA=ChemCompt]') if not moose.exists(compt[0].path + '/stoich'): return None else: stoich = moose.Stoich(compt[0].path + '/stoich') status = int(stoich.status) # Flag to track status of Stoich object. # -1: No path yet assigned. # 0: Success # 1: Warning: Missing reactant in Reac or Enz # 2: Warning: Missing substrate in MMenz # 4: Warning: Compartment not defined # 8: Warning: Neither Ksolve nor Dsolve defined # 16: Warning: No objects found on path # print("Status =>", status) if status == 1 or status == 2: nameRE = "\n\nclassName --> parentName/groupName --> name " for res in moose.wildcardFind(self.modelRoot + '/##[ISA=ReacBase],' + self.modelRoot + '/##[ISA=EnzBase]'): if not len(res.neighbors["sub"]) or not len( res.neighbors["prd"]): nameRE = nameRE + "\n " + res.className + " --> " + res.parent.name + " --> " + res.name if status == -1: QMessageBox.warning( None, "Could not Run the model", "Warning: Reaction path not yet assigned.\n ") return -1 if status == 1: #QMessageBox.warning(None,"Could not Run the model","Warning: Missing a reactant in a Reac or Enz.\n ") QMessageBox.warning( None, "Could not Run the model", "Warning: Missing a reactant in %s " % (nameRE)) return 1 elif status == 2: QMessageBox.warning( None, "Could not Run the model", "Warning: Missing a substrate in an MMenz %s " % (nameRE)) #QMessageBox.warning(None,"Could not Run the model","Warning: Missing a substrate in an MMenz.\n ") return 2 elif status == 4: QMessageBox.warning(None, "Could not Run the model", " Warning: Compartment not defined.\n ") return 4 elif status == 8: QMessageBox.warning( None, "Could not Run the model", "Warning: Neither Ksolve nor Dsolve defined.\n ") return 8 elif status == 16: QMessageBox.warning(None, "Could not Run the model", "Warning: No objects found on path.\n ") return 16 elif status == 0: print("Successfully built stoichiometry matrix.\n ") # moose.reinit() return 0 def preferencesToggler(self): visibility = not self.preferences.getView().isVisible() self.preferences.getView().setVisible(visibility) def continueSlot(self): pass def updateCurrentTime(self): sys.stdout.flush() self.currentTimeWidget.dispay(str(moose.Clock('/clock').currentTime)) def updateTextFromTick(self, tickNo): tick = moose.vector('/clock/tick')[tickNo] widget = self.tickListWidget.layout().itemAtPosition(tickNo + 1, 1).widget() if widget is not None and isinstance(widget, QLineEdit): widget.setText(str(tick.dt)) def updateFromMoose(self): """Update the tick dt from the tick objects""" ticks = moose.vector('/clock/tick') # Items at position 0 are the column headers, hence ii+1 for ii in range(ticks[0].localNumField): self.updateTextFromTick(ii) self.updateCurrentTime() def getSimTime(self): try: time = float(str(self.simtimeEdit.text())) return time except ValueError: QMessageBox.warning(self, 'Invalid value', 'Specified runtime was meaningless.') return 0.0 def setDataRoot(self, root='/data'): self.dataRoot = moose.element(root).path def setModelRoot(self, root='/model'): self.modelRoot = moose.element(root).path self.setModelType() def setModelType(self): if moose.exists(self.modelRoot + "/model/cells"): self.modelType = ELECTRICAL_MODEL else: self.modelType = CHEMICAL_MODEL self.resetSimulation()