Skip to content
Snippets Groups Projects
mgui.py 63.1 KiB
Newer Older
    def reportCoreBug(self):
        QtGui.QDesktopServices.openUrl(QtCore.QUrl(config.MOOSE_CORE_BUG_URL))
    '''        
    def reportBug(self):
        QtGui.QDesktopServices.openUrl(QtCore.QUrl(config.MOOSE_REPORT_BUG_URL))
    '''
    def showBuiltInDocumentation(self):
        self.showDocumentation('moose_builtins.html')

    # openEditorView, openPlotView and openRunView are identical
    # except the view they ask from the plugin. Consider using a
    # mapper.
    def openEditorView(self):
        """Switch to the editor view of current plugin. If there is
        already a subwindow for this, make that the active
        one. Otherwise create a new one.

        """
        self.setCurrentView('editor')

    def openPlotView(self):
        self.setCurrentView('plot')

    def openRunView(self):
        self.setCurrentView('run')

    def resetAndStartSimulation(self):
        """TODO this should provide a clean scheduling through all kinds
        of simulation or default scheduling should be implemented in MOOSE
        itself. We need to define a policy for handling scheduling. It can
        be pushed to the plugin-developers who should have knowledge of
        the scheduling criteria for their domain."""
        settings = config.MooseSetting()
        try:
            simdt_kinetics = float(settings[config.KEY_KINETICS_SIMDT])
        except ValueError:
            simdt_kinetics = 0.1
        try:
            simdt_electrical = float(settings[config.KEY_ELECTRICAL_SIMDT])
        except ValueError:
            simdt_electrical = 0.25e-4
        try:
            plotdt_kinetics = float(settings[config.KEY_KINETICS_PLOTDT])
        except ValueError:
            plotdt_kinetics = 0.1
        try:
            plotdt_electrical = float(settings[config.KEY_ELECTRICAL_PLOTDT])
        except ValueError:
            plotdt_electrical = 0.25e-3
        try:
            simtime = float(settings[config.KEY_SIMTIME])
        except ValueError:
            simtime = 1.0
        moose.reinit()
        view = self.plugin.getRunView()
        moose.start(simtime)

        if view.getCentralWidget().plotAll:
            view.getCentralWidget().plotAllData()
        self.setCurrentView('run')

    def pauseSimulation(self):
        moose.stop()
    '''
    def continueSimulation(self):
        """TODO implement this somewhere else"""
        try:
            simtime = float(config.MooseSetting()[config.KEY_SIMTIME])
        except ValueError:
            simtime = 1.0
        moose.start(simtime)
    '''
    #Harsha: added visible=True so that loadModelDialogSlot and NewModelDialogSlot call this function
    #        to clear out object path
    def objectEditSlot(self, mobj, visible=True):
        """Slot for switching the current object in object editor."""
        self.objectEditDockWidget.setObject(mobj)
        self.objectEditDockWidget.setVisible(visible)

    # def objectEditClearSlot(self):
    #     #clearning the views which is stored
    #     self.objectEditDockWidget.clearDict()


    def loadedModelsAction(self,modelPath,pluginName):
        #Harsha: added under file Menu, Recently Loaded Models
        #All the previously loaded chemical models, solver's and table's ticks are made -1
        for model in self._loadedModels:
            self.disableModel(model[0])

        action = QAction(modelPath[1:],self)
        action.triggered.connect(lambda : self.setPlugin(pluginName, modelPath))
        compt = moose.wildcardFind(modelPath + '/##[ISA=ChemCompt]')
        c = moose.Clock('/clock')
        self.simulationdt = c.tickDt[7]
        self.plotdt = c.tickDt[8]
        if compt:
            self.simulationdt = c.tickDt[11]
            self.plotdt = c.tickDt[16]
        #index = [(ind, self._loadedModels[ind].index(modelPath)) for ind in xrange(len(self.loadedModels)) if item in self._loadedModels[ind]]
        # for i,j in enumerate(self._loadedModels):
        #     if j[0] == modelPath:
        #         #del(self._loadedModels[i])
        #         pass
        #         break

        self._loadedModels.append([modelPath,pluginName,action,self.simulationdt,self.plotdt])
        if len(self._loadedModels)>5:
            self._loadedModels.pop(0)

    def disableModel(self, modelPath):
        compt = moose.wildcardFind(modelPath + '/##[ISA=ChemCompt]')
        if compt:
            if moose.exists(compt[0].path+'/ksolve'):
                ksolve = moose.Ksolve( compt[0].path+'/ksolve' )
                ksolve.tick = -1
            if moose.exists(compt[0].path+'/gsolve'):
                gsolve = moose.Gsolve( compt[0].path+'/gsolve' )
                gsolve.tick = -1
            if moose.exists(compt[0].path+'/stoich'):
                stoich = moose.Stoich( compt[0].path+'/stoich' )
                stoich.tick = -1
        
        else :
            neurons = moose.wildcardFind(modelPath + "/model/cells/##[ISA=Neuron]")
            for neuron in neurons:
                solver = moose.element(neuron.path + "/hsolve")
                solver.tick = -1
        for table in moose.wildcardFind( modelPath+'/data/graph#/#' ):
            table.tick = -1

    def loadModelDialogSlot(self):
        """Start a file dialog to choose a model file.

        Once the dialog succeeds, we should hand-over the duty of
        actual model loading to something else. Then refresh the
        views. Things to check from the user:

        1) The file type

        2) Target element

        3) Whether we should update the current window or start a new
        window.

        4) Plugin to use for displaying this model (can be automated
        by looking into the model file for a regular expression)

        """
        self.popup.close()
        activeWindow = None # This to be used later to refresh the current widget with newly loaded model
        dialog = LoaderDialog(self,
                              self.tr('Load model from file'))

        if dialog.exec_():
            valid = False
            ret = []
            ret,pluginName = self.checkPlugin(dialog)
            if pluginName == 'kkit':
                if (ret['subtype'] == 'sbml' and ret['foundlib'] == False):
                    reply = QtGui.QMessageBox.question(self, "python-libsbml is not found.","\n Read SBML is not possible.\n This can be installed using \n \n pip python-libsbml  or \n apt-get install python-libsbml",
                                               QtGui.QMessageBox.Ok)
                    if reply == QtGui.QMessageBox.Ok:
                        QtGui.QApplication.restoreOverrideCursor()
                    if ret['loaderror'] != "":
                        reply = QtGui.QMessageBox.question(self, "Model can't be loaded", ret['loaderror']+" \n \n Do you want another file",
                                                   QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
                        if reply == QtGui.QMessageBox.Yes:
                            dialog = LoaderDialog(self,self.tr('Load model from file'))
                            if dialog.exec_():
                                valid = False
                                ret = []
                                pluginName = None
                                ret,pluginName = self.checkPlugin(dialog)

                                valid, ret = self.dialog_check(ret)
                        else:
                            QtGui.QApplication.restoreOverrideCursor()
                            return valid
                    else:

                        valid = True
                modelAnno = moose.Annotator(ret['model'].path+'/info')
                if ret['subtype']:
                    modelAnno.modeltype = ret['subtype']
                else:
                    modelAnno.modeltype = ret['modeltype']
                modelAnno.dirpath = str(dialog.directory().absolutePath())
                self.loadedModelsAction(ret['model'].path,pluginName)
                self.setPlugin(pluginName, ret['model'].path)
                if pluginName == 'kkit':
                    QtCore.QCoreApplication.sendEvent(self.plugin.getEditorView().getCentralWidget().view, QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Qt.Key_A, Qt.Qt.NoModifier))
                    
                    noOfCompt = len(moose.wildcardFind(ret['model'].path+'/##[ISA=ChemCompt]'))
                    grp = 0
                    for c in moose.wildcardFind(ret['model'].path+'/##[ISA=ChemCompt]'):
                        noOfGrp   = moose.wildcardFind(moose.element(c).path+'/#[TYPE=Neutral]')
                        grp = grp+len(noOfGrp)

                    noOfPool  = len(moose.wildcardFind(ret['model'].path+'/##[ISA=PoolBase]'))
                    noOfFunc  = len(moose.wildcardFind(ret['model'].path+'/##[ISA=Function]'))
                    noOfReac  = len(moose.wildcardFind(ret['model'].path+'/##[ISA=ReacBase]'))
                    noOfEnz   = len(moose.wildcardFind(ret['model'].path+'/##[ISA=EnzBase]'))
                    noOfStimtab  = len(moose.wildcardFind(ret['model'].path+'/##[ISA=StimulusTable]'))
                    
                    reply = QtGui.QMessageBox.information(self,"Model Info","Model has : \n %s Compartment \t \n %s Group \t \n %s Pool  \t \n %s Function \t \n %s reaction \t \n %s Enzyme \t \n %s StimulusTable" %(noOfCompt, grp, noOfPool, noOfFunc, noOfReac, noOfEnz, noOfStimtab))
                    if reply == QtGui.QMessageBox.Ok:
                        QtGui.QApplication.restoreOverrideCursor()
                        return
                    
    def checkPlugin(self,dialog):
        fileNames = dialog.selectedFiles()
        for fileName in fileNames:
            modelName = dialog.getTargetPath()
            if '/' in modelName:
                raise mexception.ElementNameError('Model name cannot contain `/`')
            ret = loadFile(str(fileName),'%s' %(modelName),merge=False)
            #ret = loadFile(str(fileName), '/model/%s' % (modelName), merge=False)
            #This will clear out object editor's objectpath and make it invisible
            self.objectEditSlot('/',False)
            #if subtype is None, in case of cspace then pluginLookup = /cspace/None
            #     which will not call kkit plugin so cleaning to /cspace
            #pluginLookup = '%s/%s' % (ret['modeltype'], ret['subtype'])
            try:
                pluginName = subtype_plugin_map['%s/%s' % (ret['modeltype'], ret['subtype'])]
            except KeyError:
                pluginName = 'default'
            if ret['foundlib']:
                print ('Loaded model %s' %(ret['model']))
            return ret,pluginName

    def dialog_check(self,ret):
        pluginLookup = '%s/%s' % (ret['modeltype'], ret['subtype'])
        try:
            pluginName = subtype_plugin_map['%s/%s' % (ret['modeltype'], ret['subtype'])]
        except KeyError:
            pluginName = 'default'
        if pluginName == 'kkit':
            if (ret['subtype'] == 'sbml' and ret['foundlib'] == False):
                reply = QtGui.QMessageBox.question(self, "python-libsbml is not found.","\n Read SBML is not possible.\n This can be installed using \n \n pip python-libsbml  or \n apt-get install python-libsbml",
                                           QtGui.QMessageBox.Ok)
                if reply == QtGui.QMessageBox.Ok:
                    QtGui.QApplication.restoreOverrideCursor()
                    return valid, ret
                if ret['loaderror'] != "":
                    reply = QtGui.QMessageBox.question(self, "Model can't be loaded", ret['loaderror']+" \n \n Do you want another file",
                                               QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
                    if reply == QtGui.QMessageBox.Yes:
                        dialog = LoaderDialog(self,self.tr('Load model from file'))
                        if dialog.exec_():
                            pluginName = None
                            ret,pluginName = self.checkPlugin(dialog)
                            valid,ret = self.dialog_check(ret)
                    else:
                        QtGui.QApplication.restoreOverrideCursor()
                        return valid,ret
                else:
                    valid = True
        return valid,ret

    def newModelDialogSlot(self):
        #Harsha: Create a new dialog widget for model building
        self.popup.close()
        newModelDialog = DialogWidget()
        if newModelDialog.exec_():
            modelPath = str(newModelDialog.modelPathEdit.text()).strip()
            if len(modelPath) == 0:
                raise mexception.ElementNameError('Model path cannot be empty')
            if re.search('[ /]',modelPath) is not None:
                raise mexception.ElementNameError('Model path should not containe / or whitespace')
            #plugin = str(newModelDialog.submenu.currentText())
            plugin = str(newModelDialog.getcurrentRadioButton())
            #Harsha: All model will be forced to load/build under /model,
            #2014 sep 10: All the model will be forced to load/build model under /modelName/model
            '''
            modelContainer = moose.Neutral('/model')
            modelRoot = moose.Neutral('%s/%s' % (modelContainer.path, modelPath))
            '''
            if moose.exists(modelPath+'/model'):
                moose.delete(modelPath)

            modelContainer = moose.Neutral('%s' %(modelPath))
            modelRoot = moose.Neutral('%s/%s' %(modelContainer.path,"model"))
            if not moose.exists(modelRoot.path+'/info'):
                moose.Annotator(modelRoot.path+'/info')
            
            modelAnno = moose.element(modelRoot.path+'/info')
            modelAnno.modeltype = "new_kkit"
            modelAnno.dirpath = " "
            self.loadedModelsAction(modelRoot.path,plugin)
            self.setPlugin(plugin, modelRoot.path)
            #Harsha: This will clear out object editor's objectpath and make it invisible
            self.objectEditSlot('/', False)

def main():
    # create the GUI application
    app = QtGui.QApplication(sys.argv)
    QtGui.qApp = app
    #icon = QtGui.QIcon(os.path.join(config.KEY_ICON_DIR,'moose_icon.png'))
    #app.setWindowIcon(icon)
    # instantiate the main window
    #moose.loadModel('../Demos/Genesis_files/Kholodenko.g','/kho')
    mWindow =  MWindow()
    mWindow.setWindowState(QtCore.Qt.WindowMaximized)
    sys.excepthook = mWindow.handleException
    # show it
    mWindow.show()
    # start the Qt main loop execution, exiting from this script
    #http://code.google.com/p/subplot/source/browse/branches/mzViewer/PyMZViewer/mpl_custom_widget.py
    #http://eli.thegreenplace.net/files/prog_code/qt_mpl_bars.py.txt
    #http://lionel.textmalaysia.com/a-simple-tutorial-on-gui-programming-using-qt-designer-with-pyqt4.html
    #http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg13241.html
    # with the same return code of Qt application
    config.settings[config.KEY_FIRSTTIME] = 'False' # string not boolean
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

#
# mgui.py ends here