diff --git a/mgui.py b/mgui.py index 24d2bf83bc575b109adbda5837de124d4a8cc587..372fde8fa38b55c3667def740d14552548dbc296 100644 --- a/mgui.py +++ b/mgui.py @@ -6,7 +6,7 @@ # Maintainer: HarshaRani # Created: Mon Nov 12 09:38:09 2012 (+0530) # Version: -# Last-Updated: Thu Oct 5 14:54:33 2017 (+0530) +# Last-Updated: Fri Aug 31 14:54:33 2017 (+0530) # By: Harsha # Update #: # URL: @@ -44,6 +44,10 @@ # '''' +Aug 31: Pass file from the command to load into gui + : added dsolver in disableModel function is used to unset the solver for the model + into moose-gui which are not to be run. + Oct 5: clean up with round trip of dialog_exe ''' @@ -75,7 +79,8 @@ from PyQt4 import Qt, QtCore, QtGui from PyQt4.QtGui import * from MdiArea import MdiArea import os -from setsolver import * +from moose.chemUtil.add_Delete_ChemicalSolver import * +#from setsolver import * from defines import * from collections import OrderedDict @@ -181,7 +186,88 @@ class MWindow(QtGui.QMainWindow): self.setPlugin('default', '/') self.plugin.getEditorView().getCentralWidget().parent().close() self.popup = None - self.createPopup() + cmdfilepath = "" + try: + sys.argv[1] + except: + pass + else: + cmdfilepath = os.path.abspath(sys.argv[1]) + try: + sys.argv[2] + except: + solver = 'gsl' + else: + solver = os.path.abspath(sys.argv[2]) + + if cmdfilepath: + filepath,fileName = os.path.split(cmdfilepath) + modelRoot,extension = os.path.splitext(fileName) + if extension == '.py': + self.show() + self.createPopup() + freeCursor() + reply = QtGui.QMessageBox.information(self,"Model file can not open","At present python file cann\'t be laoded into GUI",QtGui.QMessageBox.Ok) + if reply == QtGui.QMessageBox.Ok: + QtGui.QApplication.restoreOverrideCursor() + return + if not os.path.exists(cmdfilepath): + self.show() + self.createPopup() + reply = QtGui.QMessageBox.information(self,"Model file can not open","Check filename or filepath ",QtGui.QMessageBox.Ok) + if reply == QtGui.QMessageBox.Ok: + QtGui.QApplication.restoreOverrideCursor() + return + else: + filePath = filepath+'/'+fileName + ret = loadFile(str(filePath), '%s' % (modelRoot), solver, merge=False) + self.objectEditSlot('/',False) + pluginLookup = '%s/%s' % (ret['modeltype'], ret['subtype']) + try: + pluginName = subtype_plugin_map['%s/%s' % (ret['modeltype'], ret['subtype'])] + except KeyError: + pluginName = 'default' + self.loadedModelsAction(ret['model'].path,pluginName) + if len(self._loadedModels)>5: + self._loadedModels.pop(0) + + if not moose.exists(ret['model'].path+'/info'): + moose.Annotator(ret['model'].path+'/info') + + 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()) + if moose.exists(ret['model'].path + "/data"): + self.data = moose.element(ret['model'].path + "/data") + self.data = moose.Neutral(ret['model'].path + "/data") + + modelAnno.dirpath = str(filepath) + self.setPlugin(pluginName, ret['model'].path) + self.show() + # 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 + else: + self.createPopup() def createPopup(self): self.popup = dialog = QDialog(self) @@ -450,7 +536,8 @@ class MWindow(QtGui.QMainWindow): if compts: #setCompartmentSolver(self._loadedModels[i][0],"gsl") - addSolver(self._loadedModels[i][0],"gsl") + mooseAddChemSolver(self._loadedModels[i][0],"gsl") + #addSolver(self._loadedModels[i][0],"gsl") else: c.tickDt[7] = self._loadedModels[i][3] c.tickDt[8] = self._loadedModels[i][4] @@ -1117,6 +1204,9 @@ class MWindow(QtGui.QMainWindow): if moose.exists(compt[0].path+'/gsolve'): gsolve = moose.Gsolve( compt[0].path+'/gsolve' ) gsolve.tick = -1 + if moose.exists(compt[0].path+'/dsolve'): + dsolve = moose.Dsolve(compt[0].path+'/dsolve') + dsolve.tick = -1 if moose.exists(compt[0].path+'/stoich'): stoich = moose.Stoich( compt[0].path+'/stoich' ) stoich.tick = -1 diff --git a/objectedit.py b/objectedit.py index dcb019a4d50d3faaf86e33d5cfdb1265f27302b4..08c38bbbae4a49daf6520d833c0c720b5a86027c 100644 --- a/objectedit.py +++ b/objectedit.py @@ -6,7 +6,7 @@ # Maintainer: # Created: Wed Jun 30 11:18:34 2010 (+0530) # Version: -# Last-Updated: Thu Jul 27 11:05:59 2017 (+0530) +# Last-Updated: Tue Jun 19 11:05:59 2017 (+0530) # By: Harsha # Update #: # URL: @@ -42,6 +42,7 @@ # by setting/unsetting isbuffered field # Fri May 17 23:45:59 2017 (+0530) - Harsha added, notes header, # Kd is calculated for the second order reaction and value is displayed +# Tue Jun 18 12:10:54 IST 2018 - Harsha now group boundary color can be editable from the object editor # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -174,7 +175,8 @@ class ObjectEditModel(QtCore.QAbstractTableModel): #harsha: For signalling models will be pulling out notes field from Annotator # can updates if exist for other types also if ( isinstance(self.mooseObject, moose.PoolBase) - or isinstance(self.mooseObject,moose.EnzBase) ) : + or isinstance(self.mooseObject,moose.EnzBase) + or isinstance(self.mooseObject,moose.Neutral)) : self.fields.append("Color") flag = QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable self.fieldFlags[fieldName] = flag diff --git a/plugins/kkit.py b/plugins/kkit.py index 3b997400dd496f23c4a1b0b0774ce3d8b58ef957..692de4b2b8aa286717533f32cf321a03419ff9de 100644 --- a/plugins/kkit.py +++ b/plugins/kkit.py @@ -6,10 +6,13 @@ __version__ = "1.0.0" __maintainer__ = "HarshaRani" __email__ = "hrani@ncbs.res.in" __status__ = "Development" -__updated__ = "Oct 18 2017" -''' +__updated__ = "Jun 19 2018" + +#Change log: +# 2018 Jun 18: update the color of the group from objecteditor + +#code -''' import math import sys from PyQt4 import QtGui, QtCore, Qt @@ -30,8 +33,8 @@ from PyQt4.QtGui import QGridLayout from PyQt4.QtGui import QColor import RunWidget from os.path import expanduser -from setsolver import * - +#from setsolver import * +from moose.chemUtil.add_Delete_ChemicalSolver import * class KkitPlugin(MoosePlugin): """Default plugin for MOOSE GUI""" @@ -81,6 +84,8 @@ class KkitPlugin(MoosePlugin): self.plugin = KkitEditorView(self).getCentralWidget().plugin self.defaultScenewidth = KkitEditorView(self).getCentralWidget().defaultScenewidth self.defaultSceneheight = KkitEditorView(self).getCentralWidget().defaultSceneheight + self.coOrdinates = KkitEditorView(self).getCentralWidget().getsceneCord() + ''' for k,v in self.sceneObj.items(): if moose.exists(moose.element(k).path+'/info'): annoInfo = Annotator(k.path+'/info') @@ -88,6 +93,7 @@ class KkitPlugin(MoosePlugin): 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 = "" @@ -231,11 +237,11 @@ class AnotherKkitRunView(RunView): def setSolver(self, modelRoot,solver = None): if solver == None: - reinit = addSolver(modelRoot,self.getSchedulingDockWidget().widget().solver) + reinit = mooseAddChemSolver(modelRoot,self.getSchedulingDockWidget().widget().solver) if reinit: self.getSchedulingDockWidget().widget().resetSimulation() else: - reinit = addSolver(modelRoot,solver) + reinit = mooseAddChemSolver(modelRoot,solver) if reinit: self.getSchedulingDockWidget().widget().resetSimulation() @@ -364,6 +370,17 @@ class KineticsWidget(EditorWidgetBase): # else: #elf.sceneContainer.setSceneRect(self.sceneContainer.itemsBoundingRect()) self.sceneContainer.setBackgroundBrush(QColor(230,220,219,120)) + + def getsceneCord(self): + self.cord = {} + for item in self.sceneContainer.items(): + if isinstance(item,KineticsDisplayItem): + #item.refresh(scale) + #self.update() + xpos = item.scenePos().x() + ypos = item.scenePos().y() + self.cord[item.mobj] = {'x':xpos,'y':ypos} + return self.cord def updateModelView(self): self.getMooseObj() @@ -483,14 +500,20 @@ class KineticsWidget(EditorWidgetBase): 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 + def updateColorSlot(self,mooseObject, colour): + #Color slot for changing background color for Pool,Enz and group 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) + anninfo.color = str(colour.name()) + + if mooseObject.className == "Neutral": + item = self.qGraGrp[mooseObject] + item.setPen(QtGui.QPen(QtGui.QColor(colour),item.pen().width(),item.pen().style(),item.pen().capStyle(),item.pen().joinStyle()))# self.comptPen, Qt.Qt.SolidLine, Qt.Qt.RoundCap, Qt.Qt.RoundJoin)) + + elif (isinstance(mooseObject,PoolBase) or isinstance(mooseObject,EnzBase) ): + item = self.mooseId_GObj[mooseObject] + item.updateColor(colour) + ''' def mooseObjOntoscene(self): # All the compartments are put first on to the scene \ @@ -738,6 +761,8 @@ class KineticsWidget(EditorWidgetBase): else: x = float(element(iteminfo).getField('x')) y = float(element(iteminfo).getField('y')) + self.defaultScenewidth = 1 + self.defaultSceneheight = 1 return(x,y) def drawLine_arrow(self, itemignoreZooming=False): @@ -862,13 +887,11 @@ class KineticsWidget(EditorWidgetBase): 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 @@ -897,7 +920,6 @@ class KineticsWidget(EditorWidgetBase): 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() @@ -919,15 +941,15 @@ class KineticsWidget(EditorWidgetBase): v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20)) pass - def updateGrpSize(self,compartment): - compartmentBoundary = compartment.rect() + def updateGrpSize(self,grp): + compartmentBoundary = grp.rect() - childrenBoundary = calculateChildBoundingRect(compartment) + childrenBoundary = calculateChildBoundingRect(grp) x = childrenBoundary.x() y = childrenBoundary.y() height = childrenBoundary.height() width = childrenBoundary.width() - compartment.setRect( x-10 + grp.setRect( x-10 , y-10 , width + 20 , height + 20 diff --git a/plugins/kkitViewcontrol.py b/plugins/kkitViewcontrol.py index 255de61208a6e0c6d736098979c4fd582b74c707..91113596c36985dbe53f4a1b589341f6122e0b04 100644 --- a/plugins/kkitViewcontrol.py +++ b/plugins/kkitViewcontrol.py @@ -5,20 +5,23 @@ __version__ = "1.0.0" __maintainer__ = "HarshaRani" __email__ = "hrani@ncbs.res.in" __status__ = "Development" -__updated__ = "Feb 3 2018" +__updated__ = "Jun 8 2018" ''' -Oct 17: If object is moved from one group or compartment to another group or with in same Compartment, + +Jun8 : If object is moved from one group or compartment to another group or with in same Compartment, then both at moose level (group or compartment path is updated ) and qt level the setParentItem is set -If object is moved to Empty place or not allowed place in the GUI its moved back to origin position -also some clean up when object is just clicked in QsvgItem and v/s clicked and some action done -with Rubber selection if object are moved then group size is updated +2018 Oct 3 : At mousePressEvent, a clean way of checking on what object mouse press Event happened is checked. This is after group is added where Group Interior and Boundary is checked, with in groupInterior if click in on COMPARTMENT BOUNDARY is clicked then COMPARTMENT_BOUNDARY is return, else top most group object is returned. Sep 20: Group related function added -resolveGroupInteriorAndBoundary, findGraphic_groupcompt, graphicsIsInstance -@resolveItem,editorMousePressEvent,editorMouseMoveEvent,editorMouseReleaseEvent checks made for group +2017 ''' import sys from modelBuild import * @@ -189,12 +192,13 @@ class GraphicalView(QtGui.QGraphicsView): if itemType == GROUP_BOUNDARY: popupmenu = QtGui.QMenu('PopupMenu', self) popupmenu.addAction("DeleteGroup", lambda : self.deleteGroup(item,self.layoutPt)) - popupmenu.addAction("CloneGroup" ,lambda : handleCollisions(comptList, moveMin, self.layoutPt )) + #popupmenu.addAction("CloneGroup" ,lambda : handleCollisions(comptList, moveMin, self.layoutPt )) popupmenu.exec_(self.mapToGlobal(event.pos())) elif itemType == COMPARTMENT_BOUNDARY: if len(list(self.layoutPt.qGraCompt.values())) > 1: popupmenu = QtGui.QMenu('PopupMenu', self) + #popupmenu.addAction("DeleteCmpt", lambda : self.deleteCmpt(item,self.layoutPt)) popupmenu.addAction("LinearLayout", lambda : handleCollisions(list(self.layoutPt.qGraCompt.values()), moveX, self.layoutPt)) popupmenu.addAction("VerticalLayout" ,lambda : handleCollisions(list(self.layoutPt.qGraCompt.values()), moveMin, self.layoutPt )) popupmenu.exec_(self.mapToGlobal(event.pos())) @@ -341,6 +345,38 @@ class GraphicalView(QtGui.QGraphicsView): pressItem = self.state["press"]["item"] if actionType == "move": + tobemoved = True + movedGraphObj = self.state["press"]["item"].parent() + if itemType != EMPTY: + item = self.findGraphic_groupcompt(item) + if movedGraphObj.parentItem() != item: + if moose.exists(item.mobj.path+'/'+movedGraphObj.mobj.name): + desObj = item.mobj.className + if desObj == "CubeMesh" or desObj == "CyclMesh": + desObj = "compartment" + elif desObj == "Neutral": + desObj = "group" + tobemoved = False + self.layoutPt.setupDisplay(movedGraphObj.mobj.path+'/info',movedGraphObj,"pool") + self.layoutPt.updateArrow(movedGraphObj) + QtGui.QMessageBox.warning(None,'Could not move the object', "The object name \'%s\' exist in \'%s\' %s" %(movedGraphObj.mobj.name,item.mobj.name,desObj)) + else: + movedGraphObj.setParentItem(item) + moose.move(movedGraphObj.mobj, item.mobj) + if tobemoved: + if isinstance(movedGraphObj,KineticsDisplayItem): + itemPath = movedGraphObj.mobj.path + if moose.exists(itemPath): + iInfo = itemPath+'/info' + anno = moose.Annotator(iInfo) + x = movedGraphObj.scenePos().x()/self.layoutPt.defaultScenewidth + y = movedGraphObj.scenePos().y()/self.layoutPt.defaultSceneheight + anno.x = x + anno.y = y + QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.Qt.ArrowCursor)) + self.layoutPt.positionChange(item.mobj) + self.updateScale(self.iconScale) + ''' QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.Qt.ArrowCursor)) #If any case, move is not valide need to move back the object to original position is store and calculation initscenepos = self.state["press"]["scenepos"] @@ -398,7 +434,7 @@ class GraphicalView(QtGui.QGraphicsView): self.layoutPt.positionChange(item.mobj) self.updateScale(self.iconScale) - + ''' if actionType == "delete": self.removeConnector() pixmap = QtGui.QPixmap(24, 24) @@ -417,7 +453,7 @@ class GraphicalView(QtGui.QGraphicsView): QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: #delete solver first as topology is changing - deleteSolver(self.modelRoot) + mooseDeleteChemSolver(self.layoutPt.modelRoot) self.deleteObj([item.parent()]) QtGui.QApplication.restoreOverrideCursor() else: @@ -461,7 +497,7 @@ class GraphicalView(QtGui.QGraphicsView): #Solver should be deleted ## if there is change in 'Topology' of the model ## or if copy has to made then oject should be in unZombify mode - deleteSolver(self.modelRoot) + mooseDeleteChemSolver(self.layoutPt.modelRoot) #As name is suggesting, if item is Compartment, then search in qGraCompt and if group then qGraGrp if isinstance(itemAtView,ComptItem): lKey = [key for key, value in self.layoutPt.qGraCompt.iteritems() if value == itemAtView][0] @@ -560,13 +596,17 @@ class GraphicalView(QtGui.QGraphicsView): self.resetState() def deleteGroup(self,item,layoutPt): - key = [k for k,v in self.layoutPt.qGraGrp.items() if v == item] - if key[0] in self.layoutPt.qGraGrp: - self.layoutPt.qGraGrp.pop(key[0]) - self.groupItemlist1 = item.childItems() - self.groupItemlist = [ i for i in self.groupItemlist1 if not isinstance(i,QtGui.QGraphicsPolygonItem)] - self.deleteObj(self.groupItemlist) - self.deleteItem(item) + reply = QtGui.QMessageBox.question(self, "Deleting Object",'Do want to delete group \'{groupname}\' and its children and connections'.format(groupname=item.mobj.name), + QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) + if reply == QtGui.QMessageBox.Yes: + mooseDeleteChemSolver(self.layoutPt.modelRoot) + key = [k for k,v in self.layoutPt.qGraGrp.items() if v == item] + if key[0] in self.layoutPt.qGraGrp: + self.layoutPt.qGraGrp.pop(key[0]) + self.groupItemlist1 = item.childItems() + self.groupItemlist = [ i for i in self.groupItemlist1 if not isinstance(i,QtGui.QGraphicsPolygonItem)] + self.deleteObj(self.groupItemlist) + self.deleteItem(item) def drawExpectedConnection(self, event): self.connectionSource = self.state["press"]["item"] @@ -847,7 +887,7 @@ class GraphicalView(QtGui.QGraphicsView): def deleteObj(self,item): self.rubberbandlist = item - deleteSolver(self.layoutPt.modelRoot) + mooseDeleteChemSolver(self.layoutPt.modelRoot) self.Enz_cplxlist = [ i for i in self.rubberbandlist if (isinstance(i,MMEnzItem) or isinstance(i,EnzItem) or isinstance(i,CplxItem) )] self.PFRSlist = [ i for i in self.rubberbandlist if (isinstance(i,PoolItem) or isinstance(i,TableItem) or isinstance(i,ReacItem) or isinstance(i,FuncItem) )] self.grp = [ i for i in self.rubberbandlist if isinstance(i,GRPItem)] @@ -892,7 +932,7 @@ class GraphicalView(QtGui.QGraphicsView): reply = QtGui.QMessageBox.question(self, "Deleting Object","Do want to delete object and its connections", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: - deleteSolver(self.layoutPt.modelRoot) + mooseDeleteChemSolver(self.layoutPt.modelRoot) msgIdforDeleting = " " if isinstance(item,QtGui.QGraphicsPolygonItem): src = self.layoutPt.lineItem_dict[item]