Skip to content
Snippets Groups Projects
kkit.py 54.6 KiB
Newer Older

__author__      =   "HarshaRani"
__credits__     =   ["Upi Lab"]
__license__     =   "GPL3"
__version__     =   "1.0.0"
__maintainer__  =   "HarshaRani"
__email__       =   "hrani@ncbs.res.in"
__status__      =   "Development"
__updated__     =   "Oct 18 2017"
'''

'''
import sys
from PyQt4 import QtGui, QtCore, Qt
from default import *
from moose import *
from moose import SBML
from moose.genesis.writeKkit import mooseWriteKkit
from mplugin import *
from kkitUtil import *
from kkitQGraphics import *
from kkitViewcontrol import *
from kkitCalcArrow import *
from kkitOrdinateUtil import *
import posixpath
from mtoolbutton import MToolButton
from PyQt4.QtGui import QWidget
from PyQt4.QtGui import QGridLayout
from PyQt4.QtGui import QColor
import RunWidget
from os.path import expanduser
from setsolver import *

class KkitPlugin(MoosePlugin):
    """Default plugin for MOOSE GUI"""
    def __init__(self, *args):
        #print args
        MoosePlugin.__init__(self, *args)
        self.view = None
        #self.plotView = PlotView(self)
        #self.getRunView()
        #self.plotView.dataTable = self.view._centralWidget.dataTable
        #self.plotView.updateCallback = self.view._centralWidget.legendUpdate
        #self.view._centralWidget.legendUpdate()
        #self.dataTable = DataTable(self.dataRoot)
        self.fileinsertMenu = QtGui.QMenu('&File')
        if not hasattr(self,'SaveModelAction'):
            #self.fileinsertMenu.addSeparator()
            self.saveModelAction = QtGui.QAction('Save', self)
            self.saveModelAction.setShortcut(QtGui.QApplication.translate("MainWindow", "Ctrl+S", None, QtGui.QApplication.UnicodeUTF8))
            self.connect(self.saveModelAction, QtCore.SIGNAL('triggered()'), self.SaveModelDialogSlot)
            self.fileinsertMenu.addAction(self.saveModelAction)
        self._menus.append(self.fileinsertMenu)
        self.getEditorView()
    def SaveModelDialogSlot(self):
        type_sbml = 'SBML'
        type_genesis = 'Genesis'
        dirpath = ""
        # if moose.Annotator(self.modelRoot+'/model/info'):
        #     moose.Annotator(self.modelRoot+'/model/info')
        # mooseAnno = moose.Annotator(self.modelRoot+'/model/info')
        #dirpath = mooseAnno.dirpath
        if not dirpath:
            dirpath = expanduser("~")
        filters = {'SBML(*.xml)': type_sbml,'Genesis(*.g)':type_genesis}

        filename,filter_ = QtGui.QFileDialog.getSaveFileNameAndFilter(None,'Save File',dirpath,';;'.join(filters))
        extension = ""
        if str(filename).rfind('.') != -1:
            filename = filename[:str(filename).rfind('.')]
            if str(filter_).rfind('.') != -1:
                extension = filter_[str(filter_).rfind('.'):len(filter_)-1]
        if filename:
            filename = filename
            if filters[str(filter_)] == 'SBML':
                self.sceneObj = KkitEditorView(self).getCentralWidget().mooseId_GObj
                self.coOrdinates = {}
                self.plugin = KkitEditorView(self).getCentralWidget().plugin
                self.defaultScenewidth = KkitEditorView(self).getCentralWidget().defaultScenewidth
                self.defaultSceneheight = KkitEditorView(self).getCentralWidget().defaultSceneheight
                for k,v in self.sceneObj.items():
                    if moose.exists(moose.element(k).path+'/info'):
                        annoInfo = Annotator(k.path+'/info')
                        if moose.element(self.plugin.modelRoot+'/info').modeltype == 'kkit':
                            self.coOrdinates[k] = {'x':annoInfo.x*self.defaultScenewidth, 'y':annoInfo.y*self.defaultSceneheight}
                        else:
                            self.coOrdinates[k] = {'x':annoInfo.x, 'y':annoInfo.y}
                #writeerror = moose.writeSBML(self.modelRoot,str(filename),self.coOrdinates)
                writeerror = -2
                conisitencyMessages = ""
                writtentofile = "/test.xml"
                writeerror,consistencyMessages,writtentofile = moose.SBML.mooseWriteSBML(self.modelRoot,str(filename),self.coOrdinates)
                if writeerror == -2:
                    #QtGui.QMessageBox.warning(None,'Could not save the Model','\n WriteSBML :  This copy of MOOSE has not been compiled with SBML writing support.')
                    QtGui.QMessageBox.warning(None,'Could not save the Model',consistencyMessages)
                elif writeerror == -1:
                    QtGui.QMessageBox.warning(None,'Could not save the Model','\n This model is not valid SBML Model, failed in the consistency check')
                elif writeerror == 1:
                    QtGui.QMessageBox.information(None,'Saved the Model','\n File saved to \'{filename}\''.format(filename =filename+'.xml'),QtGui.QMessageBox.Ok)
                elif writeerror == 0:
                     QtGui.QMessageBox.information(None,'Could not save the Model','\nThe filename could not be opened for writing')
            elif filters[str(filter_)] == 'Genesis':
                mdtype = moose.Annotator(self.modelRoot+'/info')
                ss = KkitEditorView(self).getCentralWidget().mooseId_GObj
                for k,v in ss.items():
                    if moose.exists(moose.element(k).path+'/info'):
                        annoInfo = Annotator(k.path+'/info')
                        #co-ordinates will be in decimals converting to int which should be b/w 0 to 10
                        x = annoInfo.x * 10
                        y = -annoInfo.y * 10
                        self.coOrdinates[k] = {'x':x, 'y':y}

                error,written = mooseWriteKkit(self.modelRoot,str(filename),self.coOrdinates)
                if written == False:
                    QtGui.QMessageBox.information(None,'Could not save the Model','\nCheck the file')
                else:
                    if error == "":
                        QtGui.QMessageBox.information(None,'Saved the Model','\n File saved to \'{filename}\''.format(filename =filename+'.g'),QtGui.QMessageBox.Ok)
                    else:
                        status = QtCore.QString("File saved but %2").arg(error);
                        QtGui.QMessageBox.information(None,'Saved the Model but ...','{error}'.format(error=error),QtGui.QMessageBox.Ok)
    
    def getPreviousPlugin(self):
        return None

    def getNextPlugin(self):
        return None

    def getAdjacentPlugins(self):
        return []

    def getViews(self):
        return self._views

    def getCurrentView(self):
        return self.currentView

    def getEditorView(self):
        if not hasattr(self, 'editorView'):
            #self.editorView = KkitEditorView(self, self.dataTable)
            self.editorView = KkitEditorView(self)
            self.editorView.getCentralWidget().editObject.connect(self.mainWindow.objectEditSlot)
            #self.editorView.GrViewresize(self)
            #self.editorView.connect(self,QtCore.SIGNAL("resize(QResizeEvent)"),self.editorView.GrViewresize)
            self.currentView = self.editorView
        return self.editorView

    def getRunView(self):
        if self.view is None:
            self.view = AnotherKkitRunView(self.modelRoot, self)
        return self.view


        if self.view is not None: return AnotherKkitRunView(self.modelRoot, self)
        if self.view is not None: return self.view
        self.view = RunView(self.modelRoot, self)
        graphView = self.view._centralWidget
        graphView.setDataRoot(self.modelRoot)
        graphView.plotAllData()
        schedulingDockWidget = self.view.getSchedulingDockWidget().widget()
        self._kkitWidget = self.view.plugin.getEditorView().getCentralWidget()
        #self.runView = KkitRunView(self,self.dataTable)
        self.runView = KkitRunView(self, self._kkitWidget)
        self.currentRunView = self.ruAnotherKkitRunViewnView.getCentralWidget()

        #schedulingDockWidget.runner.update.connect(self.currentRunView.changeBgSize)
        #schedulingDockWidget.runner.resetAndRun.connect(self.currentRunView.resetColor)
        graphView.layout().addWidget(self.currentRunView,0,0,2,1)
        return self.view

class AnotherKkitRunView(RunView):

    def __init__(self, modelRoot, plugin,*args):
        RunView.__init__(self, modelRoot, plugin, *args)
        self.modelRoot = modelRoot
        self.plugin    = plugin
        self.schedular = None

    def setSolverFromSettings(self, chemicalSettings):
        self.setSolver(self.modelRoot,
                       chemicalSettings["simulation"]["solver"])

    def createCentralWidget(self):
        self._centralWidget = RunWidget.RunWidget(self.modelRoot)
        self.kkitRunView   = KkitRunView(self.plugin)
        self.plotWidgetContainer = PlotWidgetContainer(self.modelRoot)
        self._centralWidget.setChildWidget(self.kkitRunView.getCentralWidget(), False, 0, 0, 1, 1)
        self._centralWidget.setChildWidget(self.plotWidgetContainer, False, 0, 1, 1, 2)
        self._centralWidget.setPlotWidgetContainer(self.plotWidgetContainer)
        self.schedular = self.getSchedulingDockWidget().widget()
        self.schedular.runner.simulationProgressed.connect(self.kkitRunView.getCentralWidget().updateValue)
        self.schedular.runner.simulationProgressed.connect(self.kkitRunView.getCentralWidget().changeBgSize)
        self.schedular.runner.simulationReset.connect(self.kkitRunView.getCentralWidget().resetColor)
        # self.schedular.runner.simulationReset.connect(self.setSolver)
        self.schedular.preferences.applyChemicalSettings.connect(self.setSolverFromSettings)
        compt = moose.wildcardFind(self.modelRoot+'/##[ISA=ChemCompt]')
        ann = moose.Annotator(self.modelRoot+'/info')
        if compt:
            #self.runTime = (moose.Annotator(self.modelRoot+'/info')).runtime
            #solver = (moose.Annotator(self.modelRoot+'/info')).solver
            self.runTime = moose.element(ann).runtime
            solver = moose.element(ann).solver
        else:
            self.runTime = 100
            solver = "gsl"
        self.schedular.simulationRuntime.setText(str(self.runTime))
        #preferences
        chemprefs = self.schedular.preferences.getChemicalPreferences()
        c = moose.Clock('/clock')
        self.simulationdt = c.tickDt[11]
        self.plotdt = c.tickDt[18]
        chemprefs["simulation"]["simulation-dt"] = self.simulationdt
        chemprefs["simulation"]["plot-update-interval"] = self.plotdt
        chemprefs["simulation"]["gui-update-interval"] = 2 * self.plotdt
        chemprefs["simulation"]["solver"] = "Runge Kutta"
        if solver == "gsl":
            chemprefs["simulation"]["solver"] = "Runge Kutta"
        elif solver == "gssa":
            chemprefs["simulation"]["solver"] = "Gillespie"
        elif solver == "ee" or solver == " ":
            chemprefs["simulation"]["solver"] = "Exponential Euler"
        else:
            chemprefs["simulation"]["solver"] = "Runge Kutta"
        self.schedular.preferences.setChemicalPreferences()
        return self._centralWidget

    def setSolver(self, modelRoot,solver = None):
        if solver == None:
            reinit = addSolver(modelRoot,self.getSchedulingDockWidget().widget().solver)
            if reinit:
                self.getSchedulingDockWidget().widget().resetSimulation()
        else:
            reinit = addSolver(modelRoot,solver)
            if reinit:
                self.getSchedulingDockWidget().widget().resetSimulation()

            #self.kkitRunView.getCentralWidget().addSolver(solver)

    def getCentralWidget(self):
        if self._centralWidget is None:
            self.createCentralWidget()
        return self._centralWidget

class KkitRunView(MooseEditorView):

    #def __init__(self, plugin,dataTable):
    def __init__(self, plugin):
        MooseEditorView.__init__(self, plugin)
        #self.dataTable =dataTable
        self.plugin = plugin
    '''
    def getToolPanes(self):
        return super(KkitRunView, self).getToolPanes()

    def getLibraryPane(self):
        return super(KkitRunView, self).getLibraryPane()

    def getOperationsWidget(self):
        return super(KkitRunView, self).getOperationsPane()

    def getToolBars(self):
        return self._toolBars
    '''
    def getCentralWidget(self):
        if self._centralWidget is None:
            self._centralWidget = kineticRunWidget(self.plugin)
            self._centralWidget.editor = self.plugin.editorView
            # self._centralWidget.view.objectSelected.connect(self.plugin.mainWindow.objectEditSlot)
            self._centralWidget.setModelRoot(self.plugin.modelRoot)
        return self._centralWidget

class KkitEditorView(MooseEditorView):
    #def __init__(self, plugin, dataTable):
    def __init__(self, plugin):
        MooseEditorView.__init__(self, plugin)
        ''' EditorView  '''
        #self.dataTable = dataTable
        #self.fileinsertMenu = QtGui.QMenu('&File')
        # if not hasattr(self,'SaveModelAction'):
        #     #self.fileinsertMenu.addSeparator()
        #     self.saveModelAction = QtGui.QAction('SaveToGenesisFormat', self)
        #     self.saveModelAction.setShortcut(QtGui.QApplication.translate("MainWindow", "Ctrl+S", None, QtGui.QApplication.UnicodeUTF8))
        #     self.connect(self.saveModelAction, QtCore.SIGNAL('triggered()'), self.SaveToGenesisSlot)
        #     self.fileinsertMenu.addAction(self.saveModelAction)
        #self._menus.append(self.fileinsertMenu)

    # def SaveModelDialogSlot(self):
    #     type_sbml = 'SBML'
    #     filters = {'SBML(*.xml)': type_sbml}
    #     filename,filter_ = QtGui.QFileDialog.getSaveFileNameAndFilter(None,'Save File','',';;'.join(filters))
    #     extension = ""
    #     if str(filename).rfind('.') != -1:
    #         filename = filename[:str(filename).rfind('.')]
    #         if str(filter_).rfind('.') != -1:
    #             extension = filter_[str(filter_).rfind('.'):len(filter_)-1]
    #     if filename:
    #         filename = filename+extension
    #         if filters[str(filter_)] == 'SBML':
    #             writeerror = moose.writeSBML(str(filename),self.plugin.modelRoot)
    #             if writeerror:
    #                 QtGui.QMessageBox.warning(None,'Could not save the Model','\n Error in the consistency check')
    #             else:
    #                  QtGui.QMessageBox.information(None,'Saved the Model','\n File Saved to \'{filename}\''.format(filename =filename),QtGui.QMessageBox.Ok)
    '''
    def getToolPanes(self):
        return super(KkitEditorView, self).getToolPanes()

    def getLibraryPane(self):
        return super(KkitEditorView, self).getLibraryPane()

    def getOperationsWidget(self):
        return super(KkitEditorView, self).getOperationsPane()

    def getToolBars(self):
        return self._toolBars
    '''
    def getCentralWidget(self):
        if self._centralWidget is None:
            self._centralWidget = kineticEditorWidget(self.plugin)
            self._centralWidget.setModelRoot(self.plugin.modelRoot)
        return self._centralWidget

class  KineticsWidget(EditorWidgetBase):
    def __init__(self, plugin, *args):
        EditorWidgetBase.__init__(self, *args)
        self.plugin = plugin
        self.border = 5
        self.comptPen = 5
        self.iconScale = 1
        self.arrowsize = 2
        self.reset()
        self.defaultSceneheight = 800#1000 
        self.defaultScenewidth  = 1000#2400
        self.positionInfoExist  = True
        self.defaultComptsize   = 5
        self.srcdesConnection   = {}
        self.mooseId_GObj       = {}
        self.qGraCompt          = {}
    def reset(self):
        self.createdItem = {}
        #This are created at drawLine
        self.lineItem_dict = {}
        self.object2line = defaultdict(list)
        self.itemignoreZooming = False

        if hasattr(self,'sceneContainer'):
                self.sceneContainer.clear()
        self.sceneContainer = QtGui.QGraphicsScene(self)
        self.sceneContainer.setItemIndexMethod(QtGui.QGraphicsScene.NoIndex)
        sceneDim = self.sceneContainer.itemsBoundingRect()
        # if (sceneDim.width() == 0 and sceneDim.height() == 0):
        #     self.sceneContainer.setSceneRect(0,0,30,30)
        # else:
        #elf.sceneContainer.setSceneRect(self.sceneContainer.itemsBoundingRect())
        self.sceneContainer.setBackgroundBrush(QColor(230,220,219,120))

    def updateModelView(self):
        self.getMooseObj()
        #minmaxratiodict = {'xmin':self.xmin,'xmax':self.xmax,'ymin':self.ymin,'ymax':self.ymax,'xratio':self.xratio,'yratio':self.yratio}
        if not self.m:
            #At the time of model building
            # when we want an empty GraphicView while creating new model,
            # then remove all the view and add an empty view
            if hasattr(self, 'view') and isinstance(self.view, QtGui.QWidget):
                self.layout().removeWidget(self.view)
            #self.sceneContainer.setSceneRect(-self.width()/2,-self.height()/2,self.width(),self.height())
            #self.view = GraphicalView(self.modelRoot,self.sceneContainer,self.border,self,self.createdItem,minmaxratiodict)
            self.view = GraphicalView(self.modelRoot,self.sceneContainer,self.border,self,self.createdItem)
            if isinstance(self,kineticEditorWidget):
                self.view.setRefWidget("editorView")
                self.view.setAcceptDrops(True)
            elif isinstance(self,kineticRunWidget):
                self.view.setRefWidget("runView")
            self.connect(self.view, QtCore.SIGNAL("dropped"), self.objectEditSlot)
            hLayout = QtGui.QGridLayout(self)
            self.setLayout(hLayout)
            hLayout.addWidget(self.view,0,0)
        else:
            # Already created Model
            # maxmium and minimum coordinates of the objects specified in kkit file.
            #self.mooseObjOntoscene()
            #self.drawLine_arrow()
            if hasattr(self, 'view') and isinstance(self.view, QtGui.QWidget):
                self.layout().removeWidget(self.view)
            # self.view = GraphicalView(self.modelRoot,self.sceneContainer,self.border,self,self.createdItem,minmaxratiodict)
            self.view = GraphicalView(self.modelRoot,self.sceneContainer,self.border,self,self.createdItem)
            if isinstance(self,kineticEditorWidget):
                #self.getMooseObj()
                self.mooseObjOntoscene()
                self.drawLine_arrow()
                self.view.setRefWidget("editorView")
                self.view.setAcceptDrops(True)
                self.connect(self.view, QtCore.SIGNAL("dropped"), self.objectEditSlot)
                hLayout = QtGui.QGridLayout(self)
                self.setLayout(hLayout)
                hLayout.addWidget(self.view)
            elif isinstance(self,kineticRunWidget):
                self.view.setRefWidget("runView")
                hLayout = QtGui.QGridLayout(self)
                self.setLayout(hLayout)
                hLayout.addWidget(self.view)
                self.view.fitInView(self.sceneContainer.itemsBoundingRect().x()-10,self.sceneContainer.itemsBoundingRect().y()-10,self.sceneContainer.itemsBoundingRect().width()+20,self.sceneContainer.itemsBoundingRect().height()+20,Qt.Qt.IgnoreAspectRatio)

    def getMooseObj(self):
        #This fun call 2 more function
        # -- setupMeshObj(self.modelRoot),
        #    ----self.meshEntry has [meshEnt] = function: {}, Pool: {} etc
        # setupItem
        self.m = wildcardFind(self.modelRoot+'/##[ISA=ChemCompt]')
        if self.m:
            self.srcdesConnection = {}
            if self.meshEntry:
                self.meshEntry.clear()
            else:
                self.meshEntry = {}
            #self.meshEntry.clear= {}
            # Compartment and its members are setup
            #self.meshEntry,self.xmin,self.xmax,self.ymin,self.ymax,self.noPositionInfo = setupMeshObj(self.modelRoot)

            #self.meshEntry,xcord,ycord = setupMeshObj(self.modelRoot)
            #self.positionInfoExist = not(len(np.nonzero(xcord)[0]) == 0 \
            #                         and len(np.nonzero(ycord)[0]) == 0)
            self.objPar,self.meshEntry,self.xmin,self.xmax,self.ymin,self.ymax,self.noPositionInfo = setupMeshObj(self.modelRoot)
            self.autocoordinates = False
            if self.srcdesConnection:
                self.srcdesConnection.clear()
            else:
                self.srcdesConnection = {}
            setupItem(self.modelRoot,self.srcdesConnection)
            
            # if not self.positionInfoExist:
            #     autoCoordinates(self.meshEntry,self.srcdesConnection)
            if not self.noPositionInfo:
                self.autocoordinates = True
                #self.xmin,self.xmax,self.ymin,self.ymax,self.autoCordinatepos = autoCoordinates(self.meshEntry,self.srcdesConnection)
                #print " after ",self.xmin,self.xmax, self.ymin, self.ymax,self.autoCordinatepos
                autoCoordinates(self.meshEntry,self.srcdesConnection)
        
        self.size = QtCore.QSize(1000 ,550)
        if self.xmax-self.xmin != 0:
            self.xratio = (self.size.width()-10)/(self.xmax-self.xmin)
        else: self.xratio = self.size.width()-10

        if self.ymax-self.ymin:
            self.yratio = (self.size.height()-10)/(self.ymax-self.ymin)
        else: self.yratio = (self.size.height()-10)
        
        self.xratio = int(self.xratio)
        self.yratio = int(self.yratio)
        if self.xratio == 0:
            self.xratio = 1
        if self.yratio == 0:
            self.yratio = 1
    def sizeHint(self):
        return QtCore.QSize(800,400)

    def updateItemSlot(self, mooseObject):
        #This is overridden by derived classes to connect appropriate
        #slot for updating the display item.
        #In this case if the name is updated from the keyboard both in mooseobj and gui gets updation
        changedItem = ''

        for item in self.sceneContainer.items():
            if isinstance(item,PoolItem):
                if mooseObject.getId() == element(item.mobj).getId():
                    item.updateSlot()
                    #once the text is edited in editor, laydisplay gets updated in turn resize the length, positionChanged signal shd be emitted
                    self.positionChange(mooseObject)
                    self.view.removeConnector()
                    self.view.showConnector(item)
    def updateColorSlot(self,mooseObject, color):
        #Color slot for changing background color for PoolItem from objecteditor
        anninfo = moose.Annotator(mooseObject.path+'/info')
        textcolor,bgcolor = getColor(anninfo)
        anninfo.color = str(color.name())
        item = self.mooseId_GObj[mooseObject]
        if (isinstance(item,PoolItem) or isinstance(item,EnzItem) or isinstance(item,MMEnzItem) ):
            item.updateColor(color)
    def mooseObjOntoscene(self):
        #  All the compartments are put first on to the scene \
        #  Need to do: Check With upi if empty compartments exist
        self.qGraCompt   = {}
        self.mooseId_GObj = {}
        if self.qGraCompt:
            self.qGraCompt.clear()
        else:
            self.qGraCompt = {}
        if self.mooseId_GObj:
            self.mooseId_GObj.clear()
        else:
            self.mooseId_GObj = {}

        for cmpt in sorted(self.meshEntry.iterkeys()):
            self.createCompt(cmpt)
            self.qGraCompt[cmpt]
            #comptRef = self.qGraCompt[cmpt]

        #Enzymes of all the compartments are placed first, \
        #     so that when cplx (which is pool object) queries for its parent, it gets its \
        #     parent enz co-ordinates with respect to QGraphicsscene """

        for cmpt,memb in self.meshEntry.items():
            for enzObj in find_index(memb,'enzyme'):
                enzinfo = enzObj.path+'/info'
                if enzObj.className == 'Enz':
                    enzItem = EnzItem(enzObj,self.qGraCompt[cmpt])
                else:
                    enzItem = MMEnzItem(enzObj,self.qGraCompt[cmpt])
                self.mooseId_GObj[element(enzObj.getId())] = enzItem
                self.setupDisplay(enzinfo,enzItem,"enzyme")

                #self.setupSlot(enzObj,enzItem)
        for cmpt,memb in self.meshEntry.items():
            for poolObj in find_index(memb,'pool'):
                poolinfo = poolObj.path+'/info'
                #depending on Editor Widget or Run widget pool will be created a PoolItem or PoolItemCircle
                poolItem = self.makePoolItem(poolObj,self.qGraCompt[cmpt])
                self.mooseId_GObj[element(poolObj.getId())] = poolItem
                self.setupDisplay(poolinfo,poolItem,"pool")

            for reaObj in find_index(memb,'reaction'):
                reainfo = reaObj.path+'/info'
                reaItem = ReacItem(reaObj,self.qGraCompt[cmpt])
                self.setupDisplay(reainfo,reaItem,"reaction")
                self.mooseId_GObj[element(reaObj.getId())] = reaItem

            for tabObj in find_index(memb,'table'):
                tabinfo = tabObj.path+'/info'
                tabItem = TableItem(tabObj,self.qGraCompt[cmpt])
                self.setupDisplay(tabinfo,tabItem,"tab")
                self.mooseId_GObj[element(tabObj.getId())] = tabItem

            for funcObj in find_index(memb,'function'):
                funcinfo = moose.element(funcObj).path+'/info'
                if funcObj.parent.className == "ZombieBufPool" or funcObj.parent.className == "BufPool":
                    funcinfo = moose.element(funcObj).path+'/info'
                    Af = Annotator(funcinfo)
                    funcParent =self.mooseId_GObj[element(funcObj.parent)]
                elif funcObj.parent.className == "CubeMesh" or funcObj.parent.className == "CylMesh":
                    funcParent = self.qGraCompt[cmpt]
                funcItem = FuncItem(funcObj,funcParent)
                self.mooseId_GObj[element(funcObj.getId())] = funcItem
                self.setupDisplay(funcinfo,funcItem,"Function")

            for cplxObj in find_index(memb,'cplx'):
                cplxinfo = (cplxObj.parent).path+'/info'
                p = element(cplxObj).parent
                cplxItem = CplxItem(cplxObj,self.mooseId_GObj[element(cplxObj).parent])
                self.mooseId_GObj[element(cplxObj.getId())] = cplxItem
                self.setupDisplay(cplxinfo,cplxItem,"cplx")

        # compartment's rectangle size is calculated depending on children
        self.comptChildrenBoundingRect()
    '''
    def mooseObjOntoscene(self):
        #  All the compartments are put first on to the scene \
        #  Need to do: Check With upi if empty compartments exist
        self.qGraCompt   = {}
        self.qGraGrp     = {}
        self.mooseId_GObj = {}
        if self.qGraCompt:
            self.qGraCompt.clear()
        else:
            self.qGraCompt = {}
        if self.qGraGrp:
            self.qGraGrp.clear()
        else:
            self.qGraGrp = {}
        
        if self.qGraGrp:
            self.qGraGrp.clear()
        else:
            self.qGraGrp = {}

        if self.mooseId_GObj:
            self.mooseId_GObj.clear()
        else:
            self.mooseId_GObj = {}
        for k,v in self.objPar.items():
            if isinstance(moose.element(k),moose.ChemCompt):
                self.createCompt(k)
                self.qGraCompt[k]
                
            elif isinstance(moose.element(k),Neutral):
                if len(self.meshEntry[k]):
                    if isinstance(moose.element(v), moose.ChemCompt):
                        group_parent = self.qGraCompt[v]
                    elif isinstance(moose.element(v), moose.Neutral):
                        group_parent = self.qGraGrp[v]
                    self.createGroup(k,group_parent)
        for cmpt_grp,memb in self.meshEntry.items():
            if len(memb):
                if isinstance(moose.element(cmpt_grp),moose.ChemCompt):
                    qtGrpparent = self.qGraCompt[cmpt_grp]
                elif isinstance(moose.element(cmpt_grp), moose.Neutral):
                    qtGrpparent = self.qGraGrp[cmpt_grp]
                for mclass in ["enzyme","pool","reaction","cplx","function","stimTab"]:
                    self.mObjontoscene(memb,mclass,qtGrpparent)

        self.groupChildrenBoundingRect()
        # compartment's rectangle size is calculated depending on children
        self.comptChildrenBoundingRect()
    def mObjontoscene(self,memb,mclass,qtGrpparent):
        try:
            value = memb[mclass]
        except KeyError:
            pass
        else:
            for mObj in memb[mclass]:
                minfo = mObj.path+'/info'

                if mObj.className in['Enz',"ZombieEnz"]:
                    mItem = EnzItem(mObj,qtGrpparent)
                
                elif mObj.className in['MMenz',"ZombieMMenz"]:
                    mItem = MMEnzItem(mObj,qtGrpparent)
                
                elif isinstance (moose.element(mObj),moose.PoolBase) and mclass != "cplx":
                    #depending on Editor Widget or Run widget pool will be created a PoolItem or PoolItemCircle
                    mItem = self.makePoolItem(mObj,qtGrpparent) 

                elif isinstance (moose.element(mObj),moose.ReacBase):
                    mItem = ReacItem(mObj,qtGrpparent)    
                
                elif mclass == "cplx":
                    minfo = (mObj.parent).path+'/info'
                    mItem = CplxItem(mObj,self.mooseId_GObj[element(mObj).parent])
                    self.mooseId_GObj[element(mObj.getId())] = mItem
                elif mclass == "function":
                    if isinstance(moose.element(mObj.parent),moose.PoolBase):
                        minfo = moose.element(mObj).path+'/info'
                        Af = Annotator(minfo)
                        qtGrpparent = self.mooseId_GObj[element(mObj.parent)]
                    mItem = FuncItem(mObj,qtGrpparent)
                elif mclass == "stimTab":
                    minfo = mObj.path+'/info'
                    mItem = TableItem(mObj,qtGrpparent)
                self.mooseId_GObj[element(mObj.getId())] = mItem
                self.setupDisplay(minfo,mItem,mclass)

    def createGroup(self,key,parent):
        self.new_GRP = GRPItem(parent,0,0,0,0,key)
        self.qGraGrp[key] = self.new_GRP
        self.new_GRP.setRect(20,20,20,20)

    def groupChildrenBoundingRect(self):
        for k, v in self.qGraGrp.items():
            grpcolor = moose.Annotator(moose.element(k.path+'/info')).color
            #Todo: One may need to calculate explicitly the boundary for Group also if there is a cross-group connection, then
            # childrenBoundrect() will take the QPolygonItem position
            rectcompt = v.childrenBoundingRect()
            v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20))
            v.setPen(QtGui.QPen(Qt.QColor(grpcolor), self.comptPen, Qt.Qt.SolidLine, Qt.Qt.RoundCap, Qt.Qt.RoundJoin))
    
    def comptChildrenBoundingRect(self):
        for k, v in self.qGraCompt.items():
            # compartment's rectangle size is calculated depending on children
            rectcompt = calculateChildBoundingRect(v)
            v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20))
            v.setPen(QtGui.QPen(Qt.QColor(66,66,66,100), self.comptPen, Qt.Qt.SolidLine, Qt.Qt.RoundCap, Qt.Qt.RoundJoin))
    def createCompt(self,key):
        self.new_Compt = ComptItem(self,0,0,0,0,key)
        self.qGraCompt[key] = self.new_Compt
        self.new_Compt.setRect(10,10,10,10)
        self.sceneContainer.addItem(self.new_Compt)

    def setupDisplay(self,info,graphicalObj,objClass):
        Annoinfo = Annotator(info)
        # For Reaction and Complex object I have skipped the process to get the facecolor and background color as \
        #    we are not using these colors for displaying the object so just passing dummy color white
        if( objClass == "reaction"  or objClass == "cplx" or objClass == "Function" or objClass == "StimulusTable"):
            textcolor,bgcolor = QColor("white"),QColor("white")
        elif(objClass == "enzyme"):
            textcolor,bgcolor = getColor(info)
            if bgcolor.name() == "#ffffff" or bgcolor == "white":
                bgcolor = getRandColor()
                Annoinfo.color = str(bgcolor.name())
        else:
            textcolor,bgcolor = getColor(info)
            if bgcolor.name() == "#ffffff" or bgcolor == "white":
                bgcolor = getRandColor()
                Annoinfo.color = str(bgcolor.name())
        if isinstance(self,kineticEditorWidget):
            funct = ["Function","ZombieFunction"]
            comptt = ["CubeMesh","CylMesh"]

            if objClass in funct:
                poolt = ["ZombieBufPool","BufPool"]
                if graphicalObj.mobj.parent.className in poolt:
                    xpos = 0
                    ypos = 30
                if graphicalObj.mobj.parent.className in comptt:
                    xpos,ypos = self.positioninfo(info)
            else:
                xpos,ypos = self.positioninfo(info)
            self.xylist = [xpos,ypos]
            self.xyCord[moose.element(info).parent] = [xpos,ypos]
        elif isinstance(self,kineticRunWidget):
            self.editormooseId_GObj = self.editor.getCentralWidget().mooseId_GObj
            editorItem = self.editormooseId_GObj[moose.element(info).parent]
            xpos = editorItem.scenePos().x()
            ypos = editorItem.scenePos().y()
            #Annoinfo.x = xpos
            #Annoinfo.y = -ypos 
        graphicalObj.setDisplayProperties(xpos,ypos,textcolor,bgcolor)
        #Annoinfo.x = xpos
        #Annoinfo.y = ypos

    def positioninfo(self,iteminfo):
        '''By this time, model loaded from kkit,cspace,SBML would have info field created and co-ordinates are added
            either by autocoordinates (for cspace,SBML(unless it is not saved from moose)) or from kkit
        '''
        if moose.Annotator(self.plugin.modelRoot+'/info').modeltype == 'kkit':
            x = self.defaultScenewidth * float(element(iteminfo).getField('x'))
            y = self.defaultSceneheight * float(element(iteminfo).getField('y'))
            #x = x /self.defaultScenewidth
            #y = y /self.defaultSceneheight
        else:
            x = float(element(iteminfo).getField('x'))
            y = float(element(iteminfo).getField('y'))
    def drawLine_arrow(self, itemignoreZooming=False):
        for inn,out in self.srcdesConnection.items():
            #print "inn ",inn, " out ",out
            # self.srcdesConnection is dictionary which contains key,value \
            #    key is Enzyme or Reaction  and value [[list of substrate],[list of product]] (tuple)
            #    key is Function and value is [list of pool] (list)

            #src = self.mooseId_GObj[inn]
            if isinstance(out,tuple):
                src = self.mooseId_GObj[inn]
                if len(out[0])== 0:
                    print (inn.className + ' : ' +inn.name+ " doesn't output message")
                else:
                    for items in (items for items in out[0] ):
                        des = self.mooseId_GObj[element(items[0])]
                        self.lineCord(src,des,items,itemignoreZooming)
                if len(out[1]) == 0:
                    print (inn.className + ' : ' +inn.name+ " doesn't output message")
                else:
                    for items in (items for items in out[1] ):
                        des = self.mooseId_GObj[element(items[0])]
                        self.lineCord(src,des,items,itemignoreZooming)
            elif isinstance(out,list):
                if len(out) == 0:
                    if inn.className == "StimulusTable":
                        print (inn.name +" doesn't have output")
                    elif inn.className == "ZombieFunction" or inn.className == "Function":
                        print (inn.name + " doesn't have sumtotal ")
                else:
                    src = self.mooseId_GObj[inn]
                    for items in (items for items in out ):
                        des = self.mooseId_GObj[element(items[0])]
                        self.lineCord(src,des,items,itemignoreZooming)
    def lineCord(self,src,des,type_no,itemignoreZooming):
        srcdes_list = []
        endtype = type_no[1]
        line = 0
        if (src == "") and (des == ""):
            print ("Source or destination is missing or incorrect")
            return
        srcdes_list = [src,des,endtype,line]
        arrow = calcArrow(srcdes_list,itemignoreZooming,self.iconScale)
        self.drawLine(srcdes_list,arrow)

        while(type_no[2] > 1 and line <= (type_no[2]-1)):
            srcdes_list =[src,des,endtype,line]
            arrow = calcArrow(srcdes_list,itemignoreZooming,self.iconScale)
            self.drawLine(srcdes_list,arrow)
            line = line +1

        if type_no[2] > 5:
            print ("Higher order reaction will not be displayed")

    def drawLine(self,srcdes_list,arrow):
        src = srcdes_list[0]
        des = srcdes_list[1]
        endtype = srcdes_list[2]
        line = srcdes_list[3]
        source = element(next((k for k,v in self.mooseId_GObj.items() if v == src), None))
        for l,v,et,o in self.object2line[src]:
            if v == des and o ==line:
                l.setPolygon(arrow)
                arrowPen = l.pen()
                arrowPenWidth = self.arrowsize*self.iconScale
                arrowPen.setColor(l.pen().color())
                arrowPen.setWidth(arrowPenWidth)
                l.setPen(arrowPen)
                return
        qgLineitem = self.sceneContainer.addPolygon(arrow)
        qgLineitem.setParentItem(src.parentItem())
        pen = QtGui.QPen(QtCore.Qt.green, 0, Qt.Qt.SolidLine, Qt.Qt.RoundCap, Qt.Qt.RoundJoin)
        pen.setWidth(self.arrowsize)
        # Green is default color moose.ReacBase and derivatives - already set above
        if  isinstance(source, EnzBase):
            if ( (endtype == 's') or (endtype == 'p')):
                pen.setColor(QtCore.Qt.red)
            elif(endtype != 'cplx'):
                p1 = (next((k for k,v in self.mooseId_GObj.items() if v == src), None))
                pinfo = p1.parent.path+'/info'
                color,bgcolor = getColor(pinfo)
                #color = QColor(color[0],color[1],color[2])
        elif isinstance(source, moose.PoolBase) or isinstance(source,moose.Function):
            pen.setColor(QtCore.Qt.blue)
        elif isinstance(source,moose.StimulusTable):
            pen.setColor(QtCore.Qt.yellow)
        self.lineItem_dict[qgLineitem] = srcdes_list
        self.object2line[ src ].append( ( qgLineitem, des,endtype,line) )
        self.object2line[ des ].append( ( qgLineitem, src,endtype,line ) )
        qgLineitem.setPen(pen)
       
    def positionChange(self,mooseObject):
        #If the item position changes, the corresponding arrow's are calculated
        if isinstance(element(mooseObject),ChemCompt):
            for k, v in self.qGraCompt.items():
                mesh = moose.element(mooseObject).path
                if k.path == mesh:
                    for rectChilditem in v.childItems():
                        if isinstance(rectChilditem, KineticsDisplayItem):
                            if isinstance(moose.element(rectChilditem.mobj.path),PoolBase):
                                t = moose.element(rectChilditem.mobj.path)
                                moose.element(t).children
                                for items in moose.element(t).children:
                                    if isinstance(moose.element(items),Function):
                                        test = moose.element(items.path+'/x')
                                        for i in moose.element(test).neighbors['input']:
                                            j = self.mooseId_GObj[moose.element(i)]
                                            self.updateArrow(j)
                            self.updateArrow(rectChilditem)
        elif element(mooseObject).className == 'Neutral':
            for k,v in self.qGraGrp.items():
                if k.path == element(mooseObject).path:
                    for grpChilditem in v.childItems():
                        if isinstance(grpChilditem, KineticsDisplayItem):
                            if moose.exists(grpChilditem.mobj.path):
                                iInfo = grpChilditem.mobj.path+'/info'
                                anno = moose.Annotator(iInfo)
                                if moose.Annotator(self.plugin.modelRoot+'/info').modeltype == 'kkit':
                                    x = grpChilditem.scenePos().x()/self.defaultScenewidth
                                    y = grpChilditem.scenePos().y()/self.defaultSceneheight
                                else:
                                    #print "Check for other models at grp level ",grpChilditem.scenePos()
                                    x = grpChilditem.scenePos().x()
                                    y = grpChilditem.scenePos().y()
                                #print " x and y at 863 ",grpChilditem.scenePos()
                                anno.x = x
                                anno.y = y
                                #print " anno ",anno, anno.x, anno.y
                            if isinstance(moose.element(grpChilditem.mobj.path),PoolBase):
                                t = moose.element(grpChilditem.mobj.path)
                                moose.element(t).children
                                for items in moose.element(t).children:
                                    if isinstance(moose.element(items),Function):
                                        test = moose.element(items.path+'/x')
                                        for i in moose.element(test).neighbors['input']:
                                            j = self.mooseId_GObj[moose.element(i)]
                                            self.updateArrow(j)
                            self.updateArrow(grpChilditem)
                            # grpcompt = self.qGraCompt[self.objPar[k]]
                            # rectcompt = calculateChildBoundingRect(grpcompt)
                    rectgrp = calculateChildBoundingRect(v)
                    v.setRect(rectgrp.x()-10,rectgrp.y()-10,(rectgrp.width()+20),(rectgrp.height()+20))
            
        else:
            mobj = self.mooseId_GObj[element(mooseObject)]
            self.updateArrow(mobj)
            elePath = moose.element(mooseObject).path
            pos = elePath.find('/',1)
            l = elePath[0:pos]
            linfo = moose.Annotator(l+'/info')
            if moose.exists(l):
                #anno = moose.Annotator(linfo)
                if moose.Annotator(self.plugin.modelRoot+'/info').modeltype == 'kkit':
                    x = mobj.scenePos().x()/self.defaultScenewidth
                    y = mobj.scenePos().y()/self.defaultSceneheight
                else:
                    #print "Check for other models ",mobj.scenePos()
                    x = mobj.scenePos().x()
                    y = mobj.scenePos().y()
                    #print " x and y at 863 ",mobj.scenePos()
            # for gk,gv in self.qGraGrp.items():
            #     rectgrp = calculateChildBoundingRect(gv)
            #     grpBoundingRect = gv.boundingRect()
            #     if not grpBoundingRect.contains(rectgrp):
            #         self.updateCompartmentSize(v)
            #     else:
            #         gv.setRect(rectgrp.x()-10,rectgrp.y()-10,(rectgrp.width()+20),(rectgrp.height()+20))
            for k, v in self.qGraCompt.items():
                #rectcompt = v.childrenBoundingRect()
                rectcompt = calculateChildBoundingRect(v)
                comptBoundingRect = v.boundingRect()
                if not comptBoundingRect.contains(rectcompt):
                    self.updateCompartmentSize(v)
                else:
                    rectcompt = calculateChildBoundingRect(v)
                    v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20))
                    pass
        
    def updateGrpSize(self,compartment):
        compartmentBoundary = compartment.rect()
        
        childrenBoundary = calculateChildBoundingRect(compartment)
        x = childrenBoundary.x()
        y = childrenBoundary.y()
        height = childrenBoundary.height()
        width = childrenBoundary.width()
        compartment.setRect( x-10
                 , y-10
                 , width + 20
                 , height + 20
                 )
    def updateCompartmentSize(self, compartment):
        compartmentBoundary = compartment.rect()
        childrenBoundary = calculateChildBoundingRect(compartment)
        x = min(compartmentBoundary.x(), childrenBoundary.x())
        y = min(compartmentBoundary.y(), childrenBoundary.y())
        width = max(compartmentBoundary.width(), childrenBoundary.width())
        height = max(compartmentBoundary.height(), childrenBoundary.height())
        compartment.setRect( x-10
                 , y-10
                 , width + 20
                 , height + 20
                 )

    def updateArrow(self,qGTextitem):
        #if there is no arrow to update then return
        if qGTextitem not in self.object2line:
            return
        listItem = self.object2line[qGTextitem]
        for ql, va,endtype,order in self.object2line[qGTextitem]:
            srcdes = []
            srcdes = self.lineItem_dict[ql]
            # Checking if src (srcdes[0]) or des (srcdes[1]) is ZombieEnz,
            # if yes then need to check if cplx is connected to any mooseObject,
            # so that when Enzyme is moved, cplx connected arrow to other mooseObject(poolItem) should also be updated
            if( type(srcdes[0]) == EnzItem or type(srcdes[0] == MMEnzItem)):
                self.cplxUpdatearrow(srcdes[0])
            elif( type(srcdes[1]) == EnzItem or type(srcdes[1] == MMEnzItem)):
                self.cplxUpdatearrow(srcdes[1])
            # For calcArrow(src,des,endtype,itemignoreZooming) is to be provided
            arrow = calcArrow(srcdes,self.itemignoreZooming,self.iconScale)
            ql.setPolygon(arrow)

    def cplxUpdatearrow(self,srcdes):
        # srcdes which is 'EnzItem' from this,get ChildItems are retrived (b'cos cplx is child of zombieEnz)
        #And cplxItem is passed for updatearrow
        for item in srcdes.childItems():
            if isinstance(item,CplxItem):
                self.updateArrow(item)

    def positionChange1(self,mooseObject):
        #If the item position changes, the corresponding arrow's are calculated
        if ( (isinstance(element(mooseObject),CubeMesh)) or (isinstance(element(mooseObject),CylMesh))):
            v = self.qGraCompt[mooseObject]
            for rectChilditem in v.childItems():
                self.updateArrow(rectChilditem)
        else:
            mobj = self.mooseId_GObj[mooseObject.getId()]
            self.updateArrow(mobj)
            mooseObjcompt = self.findparent(mooseObject)
            v = self.qGraCompt[mooseObjcompt]
            #childBoundingRect = v.childrenBoundingRect()
            childBoundingRect = calculateChildBoundingRect(v)
            comptBoundingRect = v.boundingRect()
            rectcompt = comptBoundingRect.united(childBoundingRect)
            comptPen = v.pen()
            comptWidth =  5
            comptPen.setWidth(comptWidth)
            v.setPen(comptPen)
            if not comptBoundingRect.contains(childBoundingRect):
                v.setRect(rectcompt.x()-comptWidth,rectcompt.y()-comptWidth,rectcompt.width()+(comptWidth*2),rectcompt.height()+(comptWidth*2))

class kineticEditorWidget(KineticsWidget):
    def __init__(self, plugin,*args):

        KineticsWidget.__init__(self, plugin, *args)
        self.plugin = plugin