diff --git a/moose-gui/MdiArea.py b/moose-gui/MdiArea.py new file mode 100644 index 0000000000000000000000000000000000000000..005bf7c0b4ad15bbe4597a35d259ad9569dc9874 --- /dev/null +++ b/moose-gui/MdiArea.py @@ -0,0 +1,26 @@ +from PyQt4 import Qt, QtCore, QtGui +from PyQt4.QtGui import * +import os + +APPLICATION_BACKGROUND_PATH = os.path.join( os.path.dirname(os.path.realpath(__file__)) + , "icons/moose_icon_large.png" + ) + + +class MdiArea(QMdiArea): + def __init__(self): + super(MdiArea, self).__init__() + self.backgroundImage = QImage(APPLICATION_BACKGROUND_PATH) + self.background = None + + def resizeEvent(self,event): + # http://qt-project.org/faq/answer/when_setting_a_background_pixmap_for_a_widget_it_is_tiled_if_the_pixmap_is_ + self.background = QImage(event.size(), QImage.Format_ARGB32_Premultiplied) + painter = QPainter(self.background) + painter.fillRect(self.background.rect(), QColor(243, 239, 238, 255)) + scaled = self.backgroundImage.scaled(event.size() , QtCore.Qt.KeepAspectRatio) + scaledRect = scaled.rect() + scaledRect.moveCenter(self.background.rect().center()) + painter.drawImage(scaledRect, scaled) + self.setBackground(QBrush(self.background)) + super(MdiArea, self).resizeEvent(event) diff --git a/moose-gui/PlotWidgetContainer.py b/moose-gui/PlotWidgetContainer.py new file mode 100644 index 0000000000000000000000000000000000000000..ce9b6b83f699ec75a8807183b832fbd862699f7d --- /dev/null +++ b/moose-gui/PlotWidgetContainer.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from __future__ import print_function + +""" +""" + +__author__ = "Aviral Goel" +__credits__ = ["Upi Lab"] +__license__ = "GPL3" +__version__ = "1.0.0" +__maintainer__ = "Aviral Goel" +__email__ = "goel.aviral@gmail.com" +__status__ = "Development" + + +import sys +import os +import PyQt4 +from PyQt4 import QtGui, Qt +from PyQt4.QtGui import QWidget +from PyQt4.QtGui import QSizeGrip +from PyQt4.QtGui import QDockWidget +from PyQt4.QtGui import QLayout +from PyQt4.QtGui import QVBoxLayout +from PyQt4.QtGui import QGridLayout +from PyQt4.QtGui import QScrollArea +from PyQt4.QtGui import QToolBar +from PyQt4.QtGui import QSizeGrip +from PyQt4.QtGui import QSplitter + +import moose +import default +import sidebar +# from default import PlotWidget + +ELECTRICAL = 0 +CHEMICAL = 1 +class PlotWidgetContainer(QWidget): + + def __init__(self, modelRoot, *args, **kwargs): + + super(PlotWidgetContainer, self).__init__(*args) + self.modelRoot = modelRoot + if len(moose.wildcardFind(modelRoot + "/##[ISA=ChemCompt]")) == 0: + self.modelType = ELECTRICAL + else: + self.modelType = CHEMICAL + + self.model = moose.element(self.modelRoot) + if self.modelRoot != "/": + if moose.exists(modelRoot + "/data"): + self.data = moose.element(self.modelRoot + "/data") + else: + self.data = moose.Neutral(self.modelRoot + "/data") + + else: + self.data = moose.element("/data") + + self._layout = QVBoxLayout() + self.graphs = QSplitter() + self.graphs.setOrientation(PyQt4.QtCore.Qt.Vertical) + self.graphsArea = QScrollArea() + # self.graphsLayout = QGridLayout() + # self.menubar = self.createMenuBar() + self.rowIndex = 0 + # self.setSizePolicy( QtGui.QSizePolicy.Expanding + # , QtGui.QSizePolicy.Expanding + # ) + + self.graphs.setSizePolicy( QtGui.QSizePolicy.Expanding + , QtGui.QSizePolicy.Expanding + ) + self.setAcceptDrops(True) + # self._layout.setSizeConstraint( QLayout.SetNoConstraint ) + # self.graphs.setLayout(self.graphsLayout) + self.graphsArea.setWidget(self.graphs) + self.graphsArea.setWidgetResizable(True) + self.graphWidgets = [] + # self._layout.addWidget(self.menubar) + self._layout.addWidget(self.graphsArea) + self.setLayout(self._layout) + + for graph in self.data.children: + self.addPlotWidget(graph = graph) + + if len(self.data.children) == 0: + self.addPlotWidget() + + def deleteWidget(self, graphWidget): + # print("Deleted => ", graphWidget) + self.graphWidgets.remove(graphWidget) + graphWidget.setParent(None) + graphWidget.close() + + def createMenuBar(self): + bar = sidebar.sidebar() + bar.addAction(sidebar.add_graph_action(bar, lambda event: self.addPlotWidget() )) + # bar.addAction(sidebar.delete_graph_action(bar, lambda event: self.addPlotWidget() )) + # bar.addAction(sidebar.list_action(bar, self.showPlotView)) + return bar + + def addPlotWidget(self, row = None, col = 0, graph = None): + if graph == None: + graph = moose.Neutral(self.data.path + "/graph_" + str(self.rowIndex)) + widget = default.PlotWidget(self.model, graph, self.rowIndex, self) + + if self.modelType == ELECTRICAL: + for axes in widget.canvas.axes.values(): + # axes.autoscale(False, axis='x', tight=True) + axes.set_ylim(bottom = -0.07, top= 0.03) + + if row == None: + row = self.rowIndex + self.graphs.addWidget(widget) + self.rowIndex += 1 + self.graphWidgets.append(widget) + widget.widgetClosedSignal.connect(self.deleteWidget) + widget.addGraph.connect(lambda event : self.addPlotWidget()) + # widget.resize(1, 1); + return widget + + def showPlotView(self): + pass + + def setModelRoot(self, *args): + pass + + def getMenus(self, *args): + return [] + + def setDataRoot(self, *args): + pass + + def updatePlots(self): + for graphWidget in self.graphWidgets: + graphWidget.updatePlots() + + def rescalePlots(self): + for graphWidget in self.graphWidgets: + graphWidget.rescalePlots() + + def extendXAxes(self, xlim): + for graphWidget in self.graphWidgets: + graphWidget.extendXAxes(xlim) + + def plotAllData(self): + for graphWidget in self.graphWidgets: + graphWidget.plotAllData() + + #print(graphWidget) + # def plotAll(self): + # self.apply(lambda obj: obj.plotAll()) + + # def plotAllData(self): + # selt.plotWidgetContainer.plotAllData() + + # def genColorMap(self,tableObject): + # pass + + # def onclick(self,event1): + # pass + + # def addTimeSeries(self, table, *args, **kwargs): + # pass + + # def addRasterPlot(self, eventtable, yoffset=0, *args, **kwargs): + # pass + + # def extendXAxes(self, xlim): + # pass + + # def saveCsv(self, line,directory): + # pass + + # def saveAllCsv(self): + # pass diff --git a/moose-gui/README b/moose-gui/README new file mode 100644 index 0000000000000000000000000000000000000000..cf46c2cd9f7d9934f51cbd18db68dd979b188c7b --- /dev/null +++ b/moose-gui/README @@ -0,0 +1,35 @@ +File: README +Author: Subhasis Ray +Created: 2012-11-29 + +Requirements: + +Required: + +PyQt4 (4.8 or higher) +numpy +matplotlib + +Optional: +python-qscintilla (prettier Python shell with autocomplete) + + +This directory contains scripts for the MOOSE GUI. + +mgui.py : main driver for the gui. This provides a main window and +basic menubar and toolbar. + +plugins/ : All plugins should be added to this directory. + + +Each plugin should be derived from MoosePlugin in plugins/default.py. + +Each plugin provides three views: EditorView, PlotView and RunView. + +EditorView: the view for editing models + +PlotView: this is for advanced users to select fine details of +plotting. + +RunView: this view is for displaying dynamic updates when the +simulation is executed. diff --git a/moose-gui/README.md b/moose-gui/README.md new file mode 100644 index 0000000000000000000000000000000000000000..1ec6a410130194d05080e2f779797c4fc1321813 --- /dev/null +++ b/moose-gui/README.md @@ -0,0 +1 @@ +# moose-gui diff --git a/moose-gui/RunWidget.py b/moose-gui/RunWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..0be526f6bb926783c543abe13661e5458a9a951a --- /dev/null +++ b/moose-gui/RunWidget.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from __future__ import print_function + +"""Sidebar for plugins. The sidebar comprises of actions. +Currently mode, connect and settings are defined. +""" + +__author__ = "Aviral Goel" +__credits__ = ["Upi Lab"] +__license__ = "GPL3" +__version__ = "1.0.0" +__maintainer__ = "Aviral Goel" +__email__ = "goel.aviral@gmail.com" +__status__ = "Development" + + +import sys +import os +import SettingsDialog +from PyQt4 import QtGui, Qt +from PyQt4.QtGui import QWidget +from PyQt4.QtGui import QScrollArea +from PyQt4.QtGui import QGridLayout +from PyQt4.QtGui import QSplitter + +class RunWidget(QSplitter): + + def __init__(self, modelRoot, *args, **kwargs): + super(RunWidget, self).__init__(None) + self.modelRoot = modelRoot + layout = QGridLayout() + self.setLayout(layout) + self.plotWidgetContainer = None + def setChildWidget(self, widget, wrap, row, col, rowspan = 1, colspan = 1): + if wrap: + scrollArea = QScrollArea() + scrollArea.setWidget(widget) + scrollArea.setWidgetResizable(True); + self.layout().addWidget(scrollArea, row, col, rowspan, colspan) + else: + self.addWidget(widget) + # self.layout().addWidget(widget, row, col, rowspan, colspan) + + def setPlotWidgetContainer(self, widget): + self.plotWidgetContainer = widget + + def setModelRoot(self, *args): + pass + + def getMenus(self, *args): + return [] + + def setDataRoot(self, *args): + pass + + def updatePlots(self): + self.plotWidgetContainer.updatePlots() + + def rescalePlots(self): + self.plotWidgetContainer.rescalePlots() + + def extendXAxes(self, xlim): + self.plotWidgetContainer.extendXAxes(xlim) + + def plotAllData(self): + self.plotWidgetContainer.plotAllData() diff --git a/moose-gui/SettingsDialog.py b/moose-gui/SettingsDialog.py new file mode 100644 index 0000000000000000000000000000000000000000..f1a6cad6619bfe2fb130c5d8f8c5a28cba6bb595 --- /dev/null +++ b/moose-gui/SettingsDialog.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from __future__ import print_function + +"""Dialog for settings. Currently only plot settings are supported +""" + +__author__ = "Aviral Goel" +__credits__ = ["Upi Lab"] +__license__ = "GPL3" +__version__ = "1.0.0" +__maintainer__ = "Aviral Goel" +__email__ = "goel.aviral@gmail.com" +__status__ = "Development" + + +import sys +import os +from PyQt4 import QtGui, Qt +from PyQt4.QtGui import QWidget +from PyQt4.QtGui import QLabel +from PyQt4.QtGui import QComboBox +from PyQt4.QtGui import QGridLayout +from PyQt4.QtGui import QTabWidget + +class SettingsWidget(QTabWidget): + def __init__( self + , plotFieldMap + , parent = None + ): + super(SettingsWidget, self).__init__(parent) + + self.plotFieldMap = plotFieldMap + + self.addTab(self.plotSettingsPage(),"Plot Settings"); + self.addTab(self.plotSettingsPage(),"Other Settings"); + + def plotSettingsPage(self): + page = QWidget() + layout = QGridLayout() + page.setLayout(layout) + index = 0 + for key, values in self.plotFieldMap.iteritems() : + label = QLabel(key, page) + combo = QComboBox(page) + for value in values: + combo.addItem(value) + layout.addWidget(label,index,0, Qt.Qt.AlignRight) + layout.addWidget(combo,index,1, Qt.Qt.AlignLeft) + index += 1 + return page + + # combo.move(50, 50) + # self.lbl.move(50, 150) + + # combo.activated[str].connect(self.onActivated) + + # self.setGeometry(300, 300, 300, 200) + # self.setWindowTitle('QtGui.QComboBox') + # self.show() + + +def main(): + app = QtGui.QApplication(sys.argv) + window = QtGui.QMainWindow() + dialog = SettingsWidget({ + 'LeakyIaF':['Vm'], + 'Compartment':['Vm','Im'], + 'HHChannel':['Ik','Gk'], + 'ZombiePool':['n','conc'], + 'ZombieBufPool':['n','conc'], + 'HHChannel2D':['Ik','Gk'], + 'CaConc':['Ca'] + } + ) + dialog.show() + sys.exit(app.exec_()) + + +if __name__ == "__main__": + main() diff --git a/moose-gui/__init__.py b/moose-gui/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..6a92b00ff601c1cd84eaed391d56972ba833522a --- /dev/null +++ b/moose-gui/__init__.py @@ -0,0 +1 @@ +all = [ "plugins" ] diff --git a/moose-gui/about.html b/moose-gui/about.html new file mode 100644 index 0000000000000000000000000000000000000000..5345c9ca2ff26de266c661881ce8d8ce48abb25f --- /dev/null +++ b/moose-gui/about.html @@ -0,0 +1,36 @@ +<html> +<hr/> +<b align="center">MOOSE is the Multiscale Object-Oriented Simulation Environment (MOOSE) +<p> Version 3.0.2pre "Ghevar" +</b> +<hr/> +<p>Copyright (C) 2003-2016 Upinder S. Bhalla and NCBS.</p> + +<p>MOOSE is released under the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version.</p> + +<p>MOOSE is the Multiscale Object-Oriented Simulation Environment. It is designed +to simulate neural systems ranging from subcellular components and biochemical +reactions to complex models of single neurons, circuits, and large networks. +MOOSE can operate at many levels of detail, from stochastic chemical +computations, to multicompartment single-neuron models, to spiking neuron +network models. + +MOOSE is multiscale: It can do all these calculations together. For example it +handles interactions seamlessly between electrical and chemical signaling. +MOOSE is object-oriented. Biological concepts are mapped into classes, and a +model is built by creating instances of these classes and connecting them by +messages. MOOSE also has classes whose job is to take over difficult +computations in a certain domain, and do them fast. There are such solver +classes for stochastic and deterministic chemistry, for diffusion, and for +multicompartment neuronal models. MOOSE is a simulation environment, not just a +numerical engine: It provides data representations and solvers (of course!), but +also a scripting interface with Python, graphical displays with Matplotlib, +PyQt, and OpenGL, and support for many model formats. These include SBML, +NeuroML, GENESIS kkit and cell.p formats, HDF5 and NSDF for data writing.</p> + +<p align="center">Home Page: <a href="http://moose.ncbs.res.in"> +http://moose.ncbs.res.in</a></p> + +</html> diff --git a/moose-gui/bioModels/getAllCuratedModelsId.pkl b/moose-gui/bioModels/getAllCuratedModelsId.pkl new file mode 100644 index 0000000000000000000000000000000000000000..0bfc2607a7abb018ea3e79dde6353697e30a4373 --- /dev/null +++ b/moose-gui/bioModels/getAllCuratedModelsId.pkl @@ -0,0 +1,7303 @@ +(dp0 +ccopy_reg +_reconstructor +p1 +(csuds.sax.text +Text +p2 +c__builtin__ +unicode +p3 +VBIOMD0000000543 +p4 +tp5 +Rp6 +(dp7 +S'lang' +p8 +NsS'escaped' +p9 +I00 +sbS'Qi2013 - IL-6 and IFN crosstalk model (non-competitive)' +p10 +sg1 +(g2 +g3 +VBIOMD0000000542 +p11 +tp12 +Rp13 +(dp14 +g8 +Nsg9 +I00 +sbS'Yuraszeck2010 - Vulnerabilities in the Tau Network in Tau Pathophysiology' +p15 +sg1 +(g2 +g3 +VBIOMD0000000541 +p16 +tp17 +Rp18 +(dp19 +g8 +Nsg9 +I00 +sbS'Yugi2014 - Insulin induced signalling (PFKL phosphorylation) - model 2' +p20 +sg1 +(g2 +g3 +VBIOMD0000000540 +p21 +tp22 +Rp23 +(dp24 +g8 +Nsg9 +I00 +sbS'Yugi2014 - Insulin induced signalling (PFKL phosphorylation) - model 1' +p25 +sg1 +(g2 +g3 +VBIOMD0000000428 +p26 +tp27 +Rp28 +(dp29 +g8 +Nsg9 +I00 +sbS'Achcar2012 - Glycolysis in bloodstream form T. brucei' +p30 +sg1 +(g2 +g3 +VBIOMD0000000429 +p31 +tp32 +Rp33 +(dp34 +g8 +Nsg9 +I00 +sbS'Schaber2012 - Hog pathway in yeast' +p35 +sg1 +(g2 +g3 +VBIOMD0000000545 +p36 +tp37 +Rp38 +(dp39 +g8 +Nsg9 +I00 +sbS'Ouyang2014 - photomorphogenic UV-B signalling network' +p40 +sg1 +(g2 +g3 +VBIOMD0000000544 +p41 +tp42 +Rp43 +(dp44 +g8 +Nsg9 +I00 +sbS'Qi2013 - IL-6 and IFN crosstalk model' +p45 +sg1 +(g2 +g3 +VBIOMD0000000424 +p46 +tp47 +Rp48 +(dp49 +g8 +Nsg9 +I00 +sbS'Faratian2009_PTENrole_TrastuzumabResistance' +p50 +sg1 +(g2 +g3 +VBIOMD0000000425 +p51 +tp52 +Rp53 +(dp54 +g8 +Nsg9 +I00 +sbS'Tan2012 - Antibiotic Treatment, Inoculum Effect' +p55 +sg1 +(g2 +g3 +VBIOMD0000000426 +p56 +tp57 +Rp58 +(dp59 +g8 +Nsg9 +I00 +sbS'Mosca2012 - Central Carbon Metabolism Regulated by AKT' +p60 +sg1 +(g2 +g3 +VBIOMD0000000427 +p61 +tp62 +Rp63 +(dp64 +g8 +Nsg9 +I00 +sbS'Bianconi2012 - EGFR and IGF1R pathway in lung cancer' +p65 +sg1 +(g2 +g3 +VBIOMD0000000420 +p66 +tp67 +Rp68 +(dp69 +g8 +Nsg9 +I00 +sbS'Ratushny2012_ASSURE_I' +p70 +sg1 +(g2 +g3 +VBIOMD0000000421 +p71 +tp72 +Rp73 +(dp74 +g8 +Nsg9 +I00 +sbS'Ratushny2012_ASSURE_II' +p75 +sg1 +(g2 +g3 +VBIOMD0000000422 +p76 +tp77 +Rp78 +(dp79 +g8 +Nsg9 +I00 +sbS'Middleton2012_GibberellinSignalling' +p80 +sg1 +(g2 +g3 +VBIOMD0000000423 +p81 +tp82 +Rp83 +(dp84 +g8 +Nsg9 +I00 +sbS'Nyman2012_InsulinSignalling' +p85 +sg1 +(g2 +g3 +VBIOMD0000000547 +p86 +tp87 +Rp88 +(dp89 +g8 +Nsg9 +I00 +sbS'Talemi2014 - Arsenic toxicity and detoxification mechanisms in yeast' +p90 +sg1 +(g2 +g3 +VBIOMD0000000546 +p91 +tp92 +Rp93 +(dp94 +g8 +Nsg9 +I00 +sbS'Miao2010 - Innate and adaptive immune responses to primary Influenza A Virus infection' +p95 +sg1 +(g2 +g3 +VBIOMD0000000490 +p96 +tp97 +Rp98 +(dp99 +g8 +Nsg9 +I00 +sbS'Demin2013 - PKPD behaviour - 5-Lipoxygenase inhibitors' +p100 +sg1 +(g2 +g3 +VBIOMD0000000309 +p101 +tp102 +Rp103 +(dp104 +g8 +Nsg9 +I00 +sbS'Tyson2003_NegFB_Homeostasis' +p105 +sg1 +(g2 +g3 +VBIOMD0000000308 +p106 +tp107 +Rp108 +(dp109 +g8 +Nsg9 +I00 +sbS'Tyson2003_NegFB_Oscillator' +p110 +sg1 +(g2 +g3 +VBIOMD0000000301 +p111 +tp112 +Rp113 +(dp114 +g8 +Nsg9 +I00 +sbS'Friedland2009_Ara_RTC3_counter' +p115 +sg1 +(g2 +g3 +VBIOMD0000000300 +p116 +tp117 +Rp118 +(dp119 +g8 +Nsg9 +I00 +sbS'Schmierer2010_FIH_Ankyrins' +p120 +sg1 +(g2 +g3 +VBIOMD0000000303 +p121 +tp122 +Rp123 +(dp124 +g8 +Nsg9 +I00 +sbS'Liu2011_Complement_System' +p125 +sg1 +(g2 +g3 +VBIOMD0000000302 +p126 +tp127 +Rp128 +(dp129 +g8 +Nsg9 +I00 +sbS'Wang1996_Synaptic_Inhibition_Two_Neuron' +p130 +sg1 +(g2 +g3 +VBIOMD0000000305 +p131 +tp132 +Rp133 +(dp134 +g8 +Nsg9 +I00 +sbS'Kolomeisky2003_MyosinV_Processivity' +p135 +sg1 +(g2 +g3 +VBIOMD0000000304 +p136 +tp137 +Rp138 +(dp139 +g8 +Nsg9 +I00 +sbS'Plant1981_BurstingNerveCells' +p140 +sg1 +(g2 +g3 +VBIOMD0000000307 +p141 +tp142 +Rp143 +(dp144 +g8 +Nsg9 +I00 +sbS'Tyson2003_Substrate_Depletion_Osc' +p145 +sg1 +(g2 +g3 +VBIOMD0000000306 +p146 +tp147 +Rp148 +(dp149 +g8 +Nsg9 +I00 +sbS'Tyson2003_Activator_Inhibitor' +p150 +sg1 +(g2 +g3 +VBIOMD0000000548 +p151 +tp152 +Rp153 +(dp154 +g8 +Nsg9 +I00 +sbS"Sneppen2009 - Modeling proteasome dynamics in Parkinson's disease" +p155 +sg1 +(g2 +g3 +VBIOMD0000000493 +p156 +tp157 +Rp158 +(dp159 +g8 +Nsg9 +I00 +sbS'Schittler2010 - Cell fate of progenitor cells, osteoblasts or chondrocytes' +p160 +sg1 +(g2 +g3 +VBIOMD0000000158 +p161 +tp162 +Rp163 +(dp164 +g8 +Nsg9 +I00 +sbS'Zatorsky2006_p53_Model2' +p165 +sg1 +(g2 +g3 +VBIOMD0000000159 +p166 +tp167 +Rp168 +(dp169 +g8 +Nsg9 +I00 +sbS'Zatorsky2006_p53_Model1' +p170 +sg1 +(g2 +g3 +VBIOMD0000000495 +p171 +tp172 +Rp173 +(dp174 +g8 +Nsg9 +I00 +sbS'Sen2013 - Phospholipid Synthesis in P.knowlesi' +p175 +sg1 +(g2 +g3 +VBIOMD0000000015 +p176 +tp177 +Rp178 +(dp179 +g8 +Nsg9 +I00 +sbS'Curto1998_purineMetabol' +p180 +sg1 +(g2 +g3 +VBIOMD0000000014 +p181 +tp182 +Rp183 +(dp184 +g8 +Nsg9 +I00 +sbS'Levchenko2000_MAPK_Scaffold' +p185 +sg1 +(g2 +g3 +VBIOMD0000000017 +p186 +tp187 +Rp188 +(dp189 +g8 +Nsg9 +I00 +sbS'Hoefnagel2002_PyruvateBranches' +p190 +sg1 +(g2 +g3 +VBIOMD0000000016 +p191 +tp192 +Rp193 +(dp194 +g8 +Nsg9 +I00 +sbS'Goldbeter1995_CircClock' +p195 +sg1 +(g2 +g3 +VBIOMD0000000011 +p196 +tp197 +Rp198 +(dp199 +g8 +Nsg9 +I00 +sbS'Levchenko2000_MAPK_noScaffold' +p200 +sg1 +(g2 +g3 +VBIOMD0000000010 +p201 +tp202 +Rp203 +(dp204 +g8 +Nsg9 +I00 +sbS'Kholodenko2000 - Ultrasensitivity and negative feedback bring oscillations in MAPK cascade' +p205 +sg1 +(g2 +g3 +VBIOMD0000000013 +p206 +tp207 +Rp208 +(dp209 +g8 +Nsg9 +I00 +sbS'Poolman2004_CalvinCycle' +p210 +sg1 +(g2 +g3 +VBIOMD0000000012 +p211 +tp212 +Rp213 +(dp214 +g8 +Nsg9 +I00 +sbS'Elowitz2000 - Repressilator' +p215 +sg1 +(g2 +g3 +VBIOMD0000000019 +p216 +tp217 +Rp218 +(dp219 +g8 +Nsg9 +I00 +sbS'Schoeberl2002_EGF_MAPK' +p220 +sg1 +(g2 +g3 +VBIOMD0000000018 +p221 +tp222 +Rp223 +(dp224 +g8 +Nsg9 +I00 +sbS'Morrison1989_FolateCycle' +p225 +sg1 +(g2 +g3 +VBIOMD0000000250 +p226 +tp227 +Rp228 +(dp229 +g8 +Nsg9 +I00 +sbS'Nakakuki2010_CellFateDecision_Mechanistic' +p230 +sg1 +(g2 +g3 +VBIOMD0000000478 +p231 +tp232 +Rp233 +(dp234 +g8 +Nsg9 +I00 +sbS'Besozzi2012 - Oscillatory regimes in the Ras/cAMP/PKA pathway in S.cerevisiae' +p235 +sg1 +(g2 +g3 +VBIOMD0000000039 +p236 +tp237 +Rp238 +(dp239 +g8 +Nsg9 +I00 +sbS'Marhl2000_CaOscillations' +p240 +sg1 +(g2 +g3 +VBIOMD0000000038 +p241 +tp242 +Rp243 +(dp244 +g8 +Nsg9 +I00 +sbS'Rohwer2000_Phosphotransferase_System' +p245 +sg1 +(g2 +g3 +VBIOMD0000000122 +p246 +tp247 +Rp248 +(dp249 +g8 +Nsg9 +I00 +sbS'Fisher2006_Ca_Oscillation_dpdnt_NFAT_dynamics' +p250 +sg1 +(g2 +g3 +VBIOMD0000000161 +p251 +tp252 +Rp253 +(dp254 +g8 +Nsg9 +I00 +sbS'Eungdamrong2007_Ras_Activation' +p255 +sg1 +(g2 +g3 +VBIOMD0000000160 +p256 +tp257 +Rp258 +(dp259 +g8 +Nsg9 +I00 +sbS'Xie2007_CircClock' +p260 +sg1 +(g2 +g3 +VBIOMD0000000163 +p261 +tp262 +Rp263 +(dp264 +g8 +Nsg9 +I00 +sbS'Zi2007_TGFbeta_signaling' +p265 +sg1 +(g2 +g3 +VBIOMD0000000089 +p266 +tp267 +Rp268 +(dp269 +g8 +Nsg9 +I00 +sbS'Locke2006_CircClock_LL' +p270 +sg1 +(g2 +g3 +VBIOMD0000000165 +p271 +tp272 +Rp273 +(dp274 +g8 +Nsg9 +I00 +sbS'Saucerman2006_PKA' +p275 +sg1 +(g2 +g3 +VBIOMD0000000164 +p276 +tp277 +Rp278 +(dp279 +g8 +Nsg9 +I00 +sbS'SmithAE2002_RanTransport' +p280 +sg1 +(g2 +g3 +VBIOMD0000000167 +p281 +tp282 +Rp283 +(dp284 +g8 +Nsg9 +I00 +sbS'Mayya2005_STATmodule' +p285 +sg1 +(g2 +g3 +VBIOMD0000000166 +p286 +tp287 +Rp288 +(dp289 +g8 +Nsg9 +I00 +sbS'Zhu2007_TF_modulated_by_Calcium' +p290 +sg1 +(g2 +g3 +VBIOMD0000000169 +p291 +tp292 +Rp293 +(dp294 +g8 +Nsg9 +I00 +sbS'Aguda1999_CellCycle' +p295 +sg1 +(g2 +g3 +VBIOMD0000000168 +p296 +tp297 +Rp298 +(dp299 +g8 +Nsg9 +I00 +sbS'Obeyesekere1999_CellCycle' +p300 +sg1 +(g2 +g3 +VBIOMD0000000080 +p301 +tp302 +Rp303 +(dp304 +g8 +Nsg9 +I00 +sbS'Thomsen1989_AdenylateCyclase' +p305 +sg1 +(g2 +g3 +VBIOMD0000000081 +p306 +tp307 +Rp308 +(dp309 +g8 +Nsg9 +I00 +sbS'Suh2004_KCNQ_Regulation' +p310 +sg1 +(g2 +g3 +VBIOMD0000000086 +p311 +tp312 +Rp313 +(dp314 +g8 +Nsg9 +I00 +sbS'Bornheimer2004_GTPaseCycle' +p315 +sg1 +(g2 +g3 +VBIOMD0000000087 +p316 +tp317 +Rp318 +(dp319 +g8 +Nsg9 +I00 +sbS'Proctor2006_telomere' +p320 +sg1 +(g2 +g3 +VBIOMD0000000084 +p321 +tp322 +Rp323 +(dp324 +g8 +Nsg9 +I00 +sbS'Hornberg2005_ERKcascade' +p325 +sg1 +(g2 +g3 +VBIOMD0000000085 +p326 +tp327 +Rp328 +(dp329 +g8 +Nsg9 +I00 +sbS'Maurya2005_GTPaseCycle_reducedOrder' +p330 +sg1 +(g2 +g3 +VBIOMD0000000460 +p331 +tp332 +Rp333 +(dp334 +g8 +Nsg9 +I00 +sbS'Liebal2012 - B.subtilis sigB proteolysis model' +p335 +sg1 +(g2 +g3 +VBIOMD0000000461 +p336 +tp337 +Rp338 +(dp339 +g8 +Nsg9 +I00 +sbS'Liebal2012 - B.subtilis transcription inhibition model' +p340 +sg1 +(g2 +g3 +VBIOMD0000000462 +p341 +tp342 +Rp343 +(dp344 +g8 +Nsg9 +I00 +sbS'Proctor2012 - Amyloid-beta aggregation' +p345 +sg1 +(g2 +g3 +VBIOMD0000000463 +p346 +tp347 +Rp348 +(dp349 +g8 +Nsg9 +I00 +sbS'Heldt2012 - Influenza Virus Replication' +p350 +sg1 +(g2 +g3 +VBIOMD0000000464 +p351 +tp352 +Rp353 +(dp354 +g8 +Nsg9 +I00 +sbS'Koo2013 - Shear stress induced calcium influx and eNOS activation - Model 1' +p355 +sg1 +(g2 +g3 +VBIOMD0000000465 +p356 +tp357 +Rp358 +(dp359 +g8 +Nsg9 +I00 +sbS'Koo2013 - Shear stress induced AKT and eNOS phosphorylation - Model 2' +p360 +sg1 +(g2 +g3 +VBIOMD0000000466 +p361 +tp362 +Rp363 +(dp364 +g8 +Nsg9 +I00 +sbS'Koo2013 - Shear stress induced eNOS expression - Model 3' +p365 +sg1 +(g2 +g3 +VBIOMD0000000467 +p366 +tp367 +Rp368 +(dp369 +g8 +Nsg9 +I00 +sbS'Koo2013 - Shear stress induced NO production - Model 4' +p370 +sg1 +(g2 +g3 +VBIOMD0000000468 +p371 +tp372 +Rp373 +(dp374 +g8 +Nsg9 +I00 +sbS'Koo2013 - Integrated shear stress induced NO production model' +p375 +sg1 +(g2 +g3 +VBIOMD0000000469 +p376 +tp377 +Rp378 +(dp379 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - E.coli metabolic model with linlog rate law' +p380 +sg1 +(g2 +g3 +VBIOMD0000000559 +p381 +tp382 +Rp383 +(dp384 +g8 +Nsg9 +I00 +sbS'Ouzounoglou2014 - Modeling of alpha-synuclein effects on neuronal homeostasis' +p385 +sg1 +(g2 +g3 +VBIOMD0000000498 +p386 +tp387 +Rp388 +(dp389 +g8 +Nsg9 +I00 +sbS'Mitchell2013 - Liver Iron Metabolism' +p390 +sg1 +(g2 +g3 +VBIOMD0000000349 +p391 +tp392 +Rp393 +(dp394 +g8 +Nsg9 +I00 +sbS'Fridlyand2010_GlucoseSensitivity_B' +p395 +sg1 +(g2 +g3 +VBIOMD0000000348 +p396 +tp397 +Rp398 +(dp399 +g8 +Nsg9 +I00 +sbS'Fridlyand2010_GlucoseSensitivity_A' +p400 +sg1 +(g2 +g3 +VBIOMD0000000345 +p401 +tp402 +Rp403 +(dp404 +g8 +Nsg9 +I00 +sbS'Koschorreck2008_InsulinClearance' +p405 +sg1 +(g2 +g3 +VBIOMD0000000344 +p406 +tp407 +Rp408 +(dp409 +g8 +Nsg9 +I00 +sbS'Proctor2011_ProteinHomeostasis_NormalCondition' +p410 +sg1 +(g2 +g3 +VBIOMD0000000347 +p411 +tp412 +Rp413 +(dp414 +g8 +Nsg9 +I00 +sbS'Bachmann2011_JAK2-STAT5_FeedbackControl' +p415 +sg1 +(g2 +g3 +VBIOMD0000000346 +p416 +tp417 +Rp418 +(dp419 +g8 +Nsg9 +I00 +sbS'FitzHugh1961_NerveMembrane' +p420 +sg1 +(g2 +g3 +VBIOMD0000000341 +p421 +tp422 +Rp423 +(dp424 +g8 +Nsg9 +I00 +sbS'Topp2000_BetaCellMass_Diabetes' +p425 +sg1 +(g2 +g3 +VBIOMD0000000340 +p426 +tp427 +Rp428 +(dp429 +g8 +Nsg9 +I00 +sbS'Wajima2009_BloodCoagulation_warfarin_heparin' +p430 +sg1 +(g2 +g3 +VBIOMD0000000343 +p431 +tp432 +Rp433 +(dp434 +g8 +Nsg9 +I00 +sbS'Brannmark2010_InsulinSignalling_Mifamodel' +p435 +sg1 +(g2 +g3 +VBIOMD0000000342 +p436 +tp437 +Rp438 +(dp439 +g8 +Nsg9 +I00 +sbS'Zi2011_TGF-beta_Pathway' +p440 +sg1 +(g2 +g3 +VBIOMD0000000266 +p441 +tp442 +Rp443 +(dp444 +g8 +Nsg9 +I00 +sbS'Voit2003_Trehalose_Cycle' +p445 +sg1 +(g2 +g3 +VBIOMD0000000267 +p446 +tp447 +Rp448 +(dp449 +g8 +Nsg9 +I00 +sbS'Lebeda2008_BoNT_Paralysis_3stepModel' +p450 +sg1 +(g2 +g3 +VBIOMD0000000264 +p451 +tp452 +Rp453 +(dp454 +g8 +Nsg9 +I00 +sbS'Fujita2010_Akt_Signalling_EGFRinhib' +p455 +sg1 +(g2 +g3 +VBIOMD0000000265 +p456 +tp457 +Rp458 +(dp459 +g8 +Nsg9 +I00 +sbS'Conradie2010_RPControl_CellCycle' +p460 +sg1 +(g2 +g3 +VBIOMD0000000262 +p461 +tp462 +Rp463 +(dp464 +g8 +Nsg9 +I00 +sbS'Fujita2010_Akt_Signalling_EGF' +p465 +sg1 +(g2 +g3 +VBIOMD0000000263 +p466 +tp467 +Rp468 +(dp469 +g8 +Nsg9 +I00 +sbS'Fujita2010_Akt_Signalling_NGF' +p470 +sg1 +(g2 +g3 +VBIOMD0000000260 +p471 +tp472 +Rp473 +(dp474 +g8 +Nsg9 +I00 +sbS'Tiago2010_FeMetabolism_FeAdequate' +p475 +sg1 +(g2 +g3 +VBIOMD0000000261 +p476 +tp477 +Rp478 +(dp479 +g8 +Nsg9 +I00 +sbS'Tiago2010_FeMetabolism_FeLoaded' +p480 +sg1 +(g2 +g3 +VBIOMD0000000268 +p481 +tp482 +Rp483 +(dp484 +g8 +Nsg9 +I00 +sbS'Reed2008_Glutathione_Metabolism' +p485 +sg1 +(g2 +g3 +VBIOMD0000000269 +p486 +tp487 +Rp488 +(dp489 +g8 +Nsg9 +I00 +sbS'Liu2010_Hormonal_Crosstalk_Arabidopsis' +p490 +sg1 +(g2 +g3 +VBIOMD0000000518 +p491 +tp492 +Rp493 +(dp494 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Colon Crypt cycle - Version 2' +p495 +sg1 +(g2 +g3 +VBIOMD0000000519 +p496 +tp497 +Rp498 +(dp499 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Colon Crypt cycle - Version 1' +p500 +sg1 +(g2 +g3 +VBIOMD0000000514 +p501 +tp502 +Rp503 +(dp504 +g8 +Nsg9 +I00 +sbS'Kerkhoven2013 - Glycolysis and Pentose Phosphate Pathway in T.brucei - MODEL B' +p505 +sg1 +(g2 +g3 +VBIOMD0000000515 +p506 +tp507 +Rp508 +(dp509 +g8 +Nsg9 +I00 +sbS'Kerkhoven2013 - Glycolysis and Pentose Phosphate Pathway in T.brucei - MODEL C in fructose medium (with glucosomal ribokinase)' +p510 +sg1 +(g2 +g3 +VBIOMD0000000516 +p511 +tp512 +Rp513 +(dp514 +g8 +Nsg9 +I00 +sbS'Kerkhoven2013 - Glycolysis and Pentose Phosphate Pathway in T.brucei - MODEL D in fructose medium (with ATP:ADP antiporter)' +p515 +sg1 +(g2 +g3 +VBIOMD0000000517 +p516 +tp517 +Rp518 +(dp519 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Colon Crypt cycle - Version 3' +p520 +sg1 +(g2 +g3 +VBIOMD0000000510 +p521 +tp522 +Rp523 +(dp524 +g8 +Nsg9 +I00 +sbS'Kerkhoven2013 - Glycolysis and Pentose Phosphate Pathway in T.brucei - MODEL C (with glucosomal ribokinase)' +p525 +sg1 +(g2 +g3 +VBIOMD0000000511 +p526 +tp527 +Rp528 +(dp529 +g8 +Nsg9 +I00 +sbS'Kerkhoven2013 - Glycolysis and Pentose Phosphate Pathway in T.brucei - MODEL D (with ATP:ADP antiporter)' +p530 +sg1 +(g2 +g3 +VBIOMD0000000512 +p531 +tp532 +Rp533 +(dp534 +g8 +Nsg9 +I00 +sbS'Benson2014 - FAAH inhibitors for the treatment of osteoarthritic pain' +p535 +sg1 +(g2 +g3 +VBIOMD0000000513 +p536 +tp537 +Rp538 +(dp539 +g8 +Nsg9 +I00 +sbS'Kerkhoven2013 - Glycolysis in T.brucei - MODEL A' +p540 +sg1 +(g2 +g3 +VBIOMD0000000549 +p541 +tp542 +Rp543 +(dp544 +g8 +Nsg9 +I00 +sbS'Baker2013 - Cytokine Mediated Inflammation in Rheumatoid Arthritis - Age Dependant' +p545 +sg1 +(g2 +g3 +VBIOMD0000000494 +p546 +tp547 +Rp548 +(dp549 +g8 +Nsg9 +I00 +sbS'Roblitz2013 - Menstrual Cycle following GnRH analogue administration' +p550 +sg1 +(g2 +g3 +VBIOMD0000000370 +p551 +tp552 +Rp553 +(dp554 +g8 +Nsg9 +I00 +sbS'Vinod2011_MitoticExit' +p555 +sg1 +(g2 +g3 +VBIOMD0000000371 +p556 +tp557 +Rp558 +(dp559 +g8 +Nsg9 +I00 +sbS'DeVries2000_PancreaticBetaCells_InsulinSecretion' +p560 +sg1 +(g2 +g3 +VBIOMD0000000375 +p561 +tp562 +Rp563 +(dp564 +g8 +Nsg9 +I00 +sbS'Mears1997_CRAC_PancreaticBetaCells' +p565 +sg1 +(g2 +g3 +VBIOMD0000000271 +p566 +tp567 +Rp568 +(dp569 +g8 +Nsg9 +I00 +sbS'Becker2010_EpoR_CoreModel' +p570 +sg1 +(g2 +g3 +VBIOMD0000000270 +p571 +tp572 +Rp573 +(dp574 +g8 +Nsg9 +I00 +sbS'Schilling2009_ERK_distributive' +p575 +sg1 +(g2 +g3 +VBIOMD0000000125 +p576 +tp577 +Rp578 +(dp579 +g8 +Nsg9 +I00 +sbS'Komarova2005_TheoreticalFramework_BasicArchitecture' +p580 +sg1 +(g2 +g3 +VBIOMD0000000124 +p581 +tp582 +Rp583 +(dp584 +g8 +Nsg9 +I00 +sbS'Wu2006_K+Channel' +p585 +sg1 +(g2 +g3 +VBIOMD0000000127 +p586 +tp587 +Rp588 +(dp589 +g8 +Nsg9 +I00 +sbS'Izhikevich2003_SpikingNeuron' +p590 +sg1 +(g2 +g3 +VBIOMD0000000126 +p591 +tp592 +Rp593 +(dp594 +g8 +Nsg9 +I00 +sbS'Clancy2002_CardiacSodiumChannel_WT' +p595 +sg1 +(g2 +g3 +VBIOMD0000000121 +p596 +tp597 +Rp598 +(dp599 +g8 +Nsg9 +I00 +sbS'Clancy2001_Kchannel' +p600 +sg1 +(g2 +g3 +VBIOMD0000000120 +p601 +tp602 +Rp603 +(dp604 +g8 +Nsg9 +I00 +sbS'Chan2004_TCell_receptor_activation' +p605 +sg1 +(g2 +g3 +VBIOMD0000000048 +p606 +tp607 +Rp608 +(dp609 +g8 +Nsg9 +I00 +sbS'Kholodenko1999_EGFRsignaling' +p610 +sg1 +(g2 +g3 +VBIOMD0000000049 +p611 +tp612 +Rp613 +(dp614 +g8 +Nsg9 +I00 +sbS'Sasagawa2005_MAPK' +p615 +sg1 +(g2 +g3 +VBIOMD0000000046 +p616 +tp617 +Rp618 +(dp619 +g8 +Nsg9 +I00 +sbS'Olsen2003_peroxidase' +p620 +sg1 +(g2 +g3 +VBIOMD0000000047 +p621 +tp622 +Rp623 +(dp624 +g8 +Nsg9 +I00 +sbS'Oxhamre2005_Ca_oscillation' +p625 +sg1 +(g2 +g3 +VBIOMD0000000044 +p626 +tp627 +Rp628 +(dp629 +g8 +Nsg9 +I00 +sbS'Borghans1997 - Calcium Oscillation - Model 2' +p630 +sg1 +(g2 +g3 +VBIOMD0000000045 +p631 +tp632 +Rp633 +(dp634 +g8 +Nsg9 +I00 +sbS'Borghans1997 - Calcium Oscillation - Model 3' +p635 +sg1 +(g2 +g3 +VBIOMD0000000042 +p636 +tp637 +Rp638 +(dp639 +g8 +Nsg9 +I00 +sbS'Nielsen1998_Glycolysis' +p640 +sg1 +(g2 +g3 +VBIOMD0000000043 +p641 +tp642 +Rp643 +(dp644 +g8 +Nsg9 +I00 +sbS'Borghans1997 - Calcium Oscillation - Model 1' +p645 +sg1 +(g2 +g3 +VBIOMD0000000040 +p646 +tp647 +Rp648 +(dp649 +g8 +Nsg9 +I00 +sbS'Field1974_Oregonator' +p650 +sg1 +(g2 +g3 +VBIOMD0000000041 +p651 +tp652 +Rp653 +(dp654 +g8 +Nsg9 +I00 +sbS'Kongas2007 - Creatine Kinase in energy metabolic signaling in muscle' +p655 +sg1 +(g2 +g3 +VBIOMD0000000381 +p656 +tp657 +Rp658 +(dp659 +g8 +Nsg9 +I00 +sbS'Maree2006_DuCa_Type1DiabetesModel' +p660 +sg1 +(g2 +g3 +VBIOMD0000000380 +p661 +tp662 +Rp663 +(dp664 +g8 +Nsg9 +I00 +sbS'Smallbone2011_TrehaloseBiosynthesis' +p665 +sg1 +(g2 +g3 +VBIOMD0000000228 +p666 +tp667 +Rp668 +(dp669 +g8 +Nsg9 +I00 +sbS'Swat2004_Mammalian_G1_S_Transition' +p670 +sg1 +(g2 +g3 +VBIOMD0000000229 +p671 +tp672 +Rp673 +(dp674 +g8 +Nsg9 +I00 +sbS'Ma2002_cAMP_oscillations' +p675 +sg1 +(g2 +g3 +VBIOMD0000000385 +p676 +tp677 +Rp678 +(dp679 +g8 +Nsg9 +I00 +sbS'Arnold2011_Schultz2003_RuBisCO-CalvinCycle' +p680 +sg1 +(g2 +g3 +VBIOMD0000000384 +p681 +tp682 +Rp683 +(dp684 +g8 +Nsg9 +I00 +sbS'Arnold2011_Medlyn2002_RuBisCO-CalvinCycle' +p685 +sg1 +(g2 +g3 +VBIOMD0000000387 +p686 +tp687 +Rp688 +(dp689 +g8 +Nsg9 +I00 +sbS'Arnold2011_Damour2007_RuBisCO-CalvinCycle' +p690 +sg1 +(g2 +g3 +VBIOMD0000000386 +p691 +tp692 +Rp693 +(dp694 +g8 +Nsg9 +I00 +sbS'Arnold2011_Sharkey2007_RuBisCO-CalvinCycle' +p695 +sg1 +(g2 +g3 +VBIOMD0000000389 +p696 +tp697 +Rp698 +(dp699 +g8 +Nsg9 +I00 +sbS'Arnold2011_Hahn1986_CalvinCycle_Starch_Sucrose' +p700 +sg1 +(g2 +g3 +VBIOMD0000000388 +p701 +tp702 +Rp703 +(dp704 +g8 +Nsg9 +I00 +sbS'Arnold2011_Zhu2009_CalvinCycle' +p705 +sg1 +(g2 +g3 +VBIOMD0000000220 +p706 +tp707 +Rp708 +(dp709 +g8 +Nsg9 +I00 +sbS'Albeck2008_extrinsic_apoptosis' +p710 +sg1 +(g2 +g3 +VBIOMD0000000221 +p711 +tp712 +Rp713 +(dp714 +g8 +Nsg9 +I00 +sbS'Singh2006_TCA_Ecoli_acetate' +p715 +sg1 +(g2 +g3 +VBIOMD0000000226 +p716 +tp717 +Rp718 +(dp719 +g8 +Nsg9 +I00 +sbS'Radulescu2008_NFkB_hierarchy_M_14_25_28_Lipniacky' +p720 +sg1 +(g2 +g3 +VBIOMD0000000227 +p721 +tp722 +Rp723 +(dp724 +g8 +Nsg9 +I00 +sbS'Radulescu2008_NFkB_hierarchy_M_39_65_90' +p725 +sg1 +(g2 +g3 +VBIOMD0000000224 +p726 +tp727 +Rp728 +(dp729 +g8 +Nsg9 +I00 +sbS'Meyer1991_CalciumSpike_ICC' +p730 +sg1 +(g2 +g3 +VBIOMD0000000225 +p731 +tp732 +Rp733 +(dp734 +g8 +Nsg9 +I00 +sbS'Westermark2003_Pancreatic_GlycOsc_basic' +p735 +sg1 +(g2 +g3 +VBIOMD0000000419 +p736 +tp737 +Rp738 +(dp739 +g8 +Nsg9 +I00 +sbS'Ratushny2012_SPF_I' +p740 +sg1 +(g2 +g3 +VBIOMD0000000418 +p741 +tp742 +Rp743 +(dp744 +g8 +Nsg9 +I00 +sbS'Ratushny2012_SPF' +p745 +sg1 +(g2 +g3 +VBIOMD0000000552 +p746 +tp747 +Rp748 +(dp749 +g8 +Nsg9 +I00 +sbS"Ehrenstein2000 - Positive-Feedback model for the loss of acetylcholine in Alzheimer's disease" +p750 +sg1 +(g2 +g3 +VBIOMD0000000553 +p751 +tp752 +Rp753 +(dp754 +g8 +Nsg9 +I00 +sbS"Ehrenstein1997 - The choline-leakage hypothesis in Alzheimer's disease" +p755 +sg1 +(g2 +g3 +VBIOMD0000000554 +p756 +tp757 +Rp758 +(dp759 +g8 +Nsg9 +I00 +sbS'Cloutier2009 - Brain Energy Metabolism' +p760 +sg1 +(g2 +g3 +VBIOMD0000000555 +p761 +tp762 +Rp763 +(dp764 +g8 +Nsg9 +I00 +sbS'Auer2010 - Correlation between lag time and aggregation rate in protein aggregation' +p765 +sg1 +(g2 +g3 +VBIOMD0000000556 +p766 +tp767 +Rp768 +(dp769 +g8 +Nsg9 +I00 +sbS'Ortega2013 - Interplay between secretases determines biphasic amyloid-beta level' +p770 +sg1 +(g2 +g3 +VBIOMD0000000557 +p771 +tp772 +Rp773 +(dp774 +g8 +Nsg9 +I00 +sbS'Reiterer2013 - pseudophosphatase STYX role in ERK signalling' +p775 +sg1 +(g2 +g3 +VBIOMD0000000411 +p776 +tp777 +Rp778 +(dp779 +g8 +Nsg9 +I00 +sbS'Heiland2012_CircadianClock_C.reinhardtii' +p780 +sg1 +(g2 +g3 +VBIOMD0000000410 +p781 +tp782 +Rp783 +(dp784 +g8 +Nsg9 +I00 +sbS'Wegner2012_TGFbetaSignalling_FeedbackLoops' +p785 +sg1 +(g2 +g3 +VBIOMD0000000413 +p786 +tp787 +Rp788 +(dp789 +g8 +Nsg9 +I00 +sbS'Band2012_DII-Venus_FullModel' +p790 +sg1 +(g2 +g3 +VBIOMD0000000412 +p791 +tp792 +Rp793 +(dp794 +g8 +Nsg9 +I00 +sbS'Pokhilko2012_CircClock_RepressilatorFeedbackloop' +p795 +sg1 +(g2 +g3 +VBIOMD0000000415 +p796 +tp797 +Rp798 +(dp799 +g8 +Nsg9 +I00 +sbS'Mellor2012_LipooxygenasePathway' +p800 +sg1 +(g2 +g3 +VBIOMD0000000414 +p801 +tp802 +Rp803 +(dp804 +g8 +Nsg9 +I00 +sbS'Band2012_DII-Venus_ReducedModel' +p805 +sg1 +(g2 +g3 +VBIOMD0000000417 +p806 +tp807 +Rp808 +(dp809 +g8 +Nsg9 +I00 +sbS'Ratushny2012_NF' +p810 +sg1 +(g2 +g3 +VBIOMD0000000416 +p811 +tp812 +Rp813 +(dp814 +g8 +Nsg9 +I00 +sbS'Muraro2011_Cytokinin-Auxin_CrossRegulation' +p815 +sg1 +(g2 +g3 +VBIOMD0000000316 +p816 +tp817 +Rp818 +(dp819 +g8 +Nsg9 +I00 +sbS'Shen-Orr2002_FeedForward_AND_gate' +p820 +sg1 +(g2 +g3 +VBIOMD0000000317 +p821 +tp822 +Rp823 +(dp824 +g8 +Nsg9 +I00 +sbS'Shen-Orr2002_Single_Input_Module' +p825 +sg1 +(g2 +g3 +VBIOMD0000000314 +p826 +tp827 +Rp828 +(dp829 +g8 +Nsg9 +I00 +sbS'Raia2011_IL13_L1236' +p830 +sg1 +(g2 +g3 +VBIOMD0000000315 +p831 +tp832 +Rp833 +(dp834 +g8 +Nsg9 +I00 +sbS'Montagne2011_Oligator_optimised' +p835 +sg1 +(g2 +g3 +VBIOMD0000000312 +p836 +tp837 +Rp838 +(dp839 +g8 +Nsg9 +I00 +sbS'Tyson2003_Perfect_Adaption' +p840 +sg1 +(g2 +g3 +VBIOMD0000000313 +p841 +tp842 +Rp843 +(dp844 +g8 +Nsg9 +I00 +sbS'Raia2010_IL13_Signalling_MedB1' +p845 +sg1 +(g2 +g3 +VBIOMD0000000259 +p846 +tp847 +Rp848 +(dp849 +g8 +Nsg9 +I00 +sbS'Tiago2010_FeMetabolism_FeDeficient' +p850 +sg1 +(g2 +g3 +VBIOMD0000000258 +p851 +tp852 +Rp853 +(dp854 +g8 +Nsg9 +I00 +sbS'Ortega2006_bistability_doublePhosphorylation' +p855 +sg1 +(g2 +g3 +VBIOMD0000000257 +p856 +tp857 +Rp858 +(dp859 +g8 +Nsg9 +I00 +sbS'Piedrafita2010_MR_System' +p860 +sg1 +(g2 +g3 +VBIOMD0000000256 +p861 +tp862 +Rp863 +(dp864 +g8 +Nsg9 +I00 +sbS'Rehm2006_Caspase' +p865 +sg1 +(g2 +g3 +VBIOMD0000000255 +p866 +tp867 +Rp868 +(dp869 +g8 +Nsg9 +I00 +sbS'Chen2009_ErbB_Signaling' +p870 +sg1 +(g2 +g3 +VBIOMD0000000254 +p871 +tp872 +Rp873 +(dp874 +g8 +Nsg9 +I00 +sbS'Bier2000_GlycolyticOscillation' +p875 +sg1 +(g2 +g3 +VBIOMD0000000253 +p876 +tp877 +Rp878 +(dp879 +g8 +Nsg9 +I00 +sbS'Teusink1998_Glycolysis_TurboDesign' +p880 +sg1 +(g2 +g3 +VBIOMD0000000252 +p881 +tp882 +Rp883 +(dp884 +g8 +Nsg9 +I00 +sbS'Hunziker2010_p53_StressSpecificResponse' +p885 +sg1 +(g2 +g3 +VBIOMD0000000318 +p886 +tp887 +Rp888 +(dp889 +g8 +Nsg9 +I00 +sbS'Yao2008_Rb_E2F_Switch' +p890 +sg1 +(g2 +g3 +VBIOMD0000000319 +p891 +tp892 +Rp893 +(dp894 +g8 +Nsg9 +I00 +sbS'Decroly1982_Enzymatic_Oscillator' +p895 +sg1 +(g2 +g3 +VBIOMD0000000530 +p896 +tp897 +Rp898 +(dp899 +g8 +Nsg9 +I00 +sbS'Schmitz2014 - RNA triplex formation' +p900 +sg1 +(g2 +g3 +VBIOMD0000000531 +p901 +tp902 +Rp903 +(dp904 +g8 +Nsg9 +I00 +sbS'Crespo2012 - Kinetics of Amyloid Fibril Formation' +p905 +sg1 +(g2 +g3 +VBIOMD0000000538 +p906 +tp907 +Rp908 +(dp909 +g8 +Nsg9 +I00 +sbS'Clarke2000 - One-hit model of cell death in neuronal degenerations' +p910 +sg1 +(g2 +g3 +VBIOMD0000000539 +p911 +tp912 +Rp913 +(dp914 +g8 +Nsg9 +I00 +sbS'Fran\xc3\xa7ois2005 - Mixed Feedback Loop (two-gene network)' +p915 +sg1 +(g2 +g3 +VBIOMD0000000002 +p916 +tp917 +Rp918 +(dp919 +g8 +Nsg9 +I00 +sbS'Edelstein1996 - EPSP ACh species' +p920 +sg1 +(g2 +g3 +VBIOMD0000000003 +p921 +tp922 +Rp923 +(dp924 +g8 +Nsg9 +I00 +sbS'Goldbeter1991 - Min Mit Oscil' +p925 +sg1 +(g2 +g3 +VBIOMD0000000001 +p926 +tp927 +Rp928 +(dp929 +g8 +Nsg9 +I00 +sbS'Edelstein1996 - EPSP ACh event' +p930 +sg1 +(g2 +g3 +VBIOMD0000000006 +p931 +tp932 +Rp933 +(dp934 +g8 +Nsg9 +I00 +sbS'Tyson1991 - Cell Cycle 2 var' +p935 +sg1 +(g2 +g3 +VBIOMD0000000007 +p936 +tp937 +Rp938 +(dp939 +g8 +Nsg9 +I00 +sbS'Novak1997 - Cell Cycle' +p940 +sg1 +(g2 +g3 +VBIOMD0000000004 +p941 +tp942 +Rp943 +(dp944 +g8 +Nsg9 +I00 +sbS'Goldbeter1991 - Min Mit Oscil, Expl Inact' +p945 +sg1 +(g2 +g3 +VBIOMD0000000005 +p946 +tp947 +Rp948 +(dp949 +g8 +Nsg9 +I00 +sbS'Tyson1991 - Cell Cycle 6 var' +p950 +sg1 +(g2 +g3 +VBIOMD0000000008 +p951 +tp952 +Rp953 +(dp954 +g8 +Nsg9 +I00 +sbS'Gardner1998 - Cell Cycle Goldbeter' +p955 +sg1 +(g2 +g3 +VBIOMD0000000009 +p956 +tp957 +Rp958 +(dp959 +g8 +Nsg9 +I00 +sbS'Huang1996 - Ultrasensitivity in MAPK cascade' +p960 +sg1 +(g2 +g3 +VBIOMD0000000183 +p961 +tp962 +Rp963 +(dp964 +g8 +Nsg9 +I00 +sbS'Stefan2008_calmodulin_allostery' +p965 +sg1 +(g2 +g3 +VBIOMD0000000182 +p966 +tp967 +Rp968 +(dp969 +g8 +Nsg9 +I00 +sbS'Neves2008 - Role of cell shape and size in controlling intracellular signalling' +p970 +sg1 +(g2 +g3 +VBIOMD0000000181 +p971 +tp972 +Rp973 +(dp974 +g8 +Nsg9 +I00 +sbS'Sriram2007_CellCycle' +p975 +sg1 +(g2 +g3 +VBIOMD0000000180 +p976 +tp977 +Rp978 +(dp979 +g8 +Nsg9 +I00 +sbS'Kim2007_CellularMemory_SymmetricModel' +p980 +sg1 +(g2 +g3 +VBIOMD0000000187 +p981 +tp982 +Rp983 +(dp984 +g8 +Nsg9 +I00 +sbS'Ibrahim2008 - Mitotic Spindle Assembly Checkpoint - Convey variant' +p985 +sg1 +(g2 +g3 +VBIOMD0000000186 +p986 +tp987 +Rp988 +(dp989 +g8 +Nsg9 +I00 +sbS'Ibrahim2008 - Mitotic Spindle Assembly Checkpoint - Dissociation variant' +p990 +sg1 +(g2 +g3 +VBIOMD0000000185 +p991 +tp992 +Rp993 +(dp994 +g8 +Nsg9 +I00 +sbS'Locke2008_Circadian_Clock' +p995 +sg1 +(g2 +g3 +VBIOMD0000000184 +p996 +tp997 +Rp998 +(dp999 +g8 +Nsg9 +I00 +sbS'Lavrentovich2008_Ca_Oscillations' +p1000 +sg1 +(g2 +g3 +VBIOMD0000000189 +p1001 +tp1002 +Rp1003 +(dp1004 +g8 +Nsg9 +I00 +sbS'Proctor2008_p53_Mdm2_ARF' +p1005 +sg1 +(g2 +g3 +VBIOMD0000000188 +p1006 +tp1007 +Rp1008 +(dp1009 +g8 +Nsg9 +I00 +sbS'Proctor2008_p53_Mdm2_ATM' +p1010 +sg1 +(g2 +g3 +VBIOMD0000000178 +p1011 +tp1012 +Rp1013 +(dp1014 +g8 +Nsg9 +I00 +sbS'Lebeda2008_BoTN_Paralysis_4stepModel' +p1015 +sg1 +(g2 +g3 +VBIOMD0000000179 +p1016 +tp1017 +Rp1018 +(dp1019 +g8 +Nsg9 +I00 +sbS'Kim2007_CellularMemory_AsymmetricModel' +p1020 +sg1 +(g2 +g3 +VBIOMD0000000176 +p1021 +tp1022 +Rp1023 +(dp1024 +g8 +Nsg9 +I00 +sbS'Conant2007_WGD_glycolysis_2A3AB' +p1025 +sg1 +(g2 +g3 +VBIOMD0000000177 +p1026 +tp1027 +Rp1028 +(dp1029 +g8 +Nsg9 +I00 +sbS'Conant2007_glycolysis_2C' +p1030 +sg1 +(g2 +g3 +VBIOMD0000000174 +p1031 +tp1032 +Rp1033 +(dp1034 +g8 +Nsg9 +I00 +sbS'Del_Conte_Zerial2008_Rab5_Rab7_cut_out_switch' +p1035 +sg1 +(g2 +g3 +VBIOMD0000000175 +p1036 +tp1037 +Rp1038 +(dp1039 +g8 +Nsg9 +I00 +sbS'Birtwistle2007_ErbB_Signalling' +p1040 +sg1 +(g2 +g3 +VBIOMD0000000172 +p1041 +tp1042 +Rp1043 +(dp1044 +g8 +Nsg9 +I00 +sbS'Pritchard2002_glycolysis' +p1045 +sg1 +(g2 +g3 +VBIOMD0000000173 +p1046 +tp1047 +Rp1048 +(dp1049 +g8 +Nsg9 +I00 +sbS'Schmierer_2008_Smad_Tgfb' +p1050 +sg1 +(g2 +g3 +VBIOMD0000000170 +p1051 +tp1052 +Rp1053 +(dp1054 +g8 +Nsg9 +I00 +sbS'Weimann2004_CircadianOscillator' +p1055 +sg1 +(g2 +g3 +VBIOMD0000000171 +p1056 +tp1057 +Rp1058 +(dp1059 +g8 +Nsg9 +I00 +sbS'Leloup1998_CircClock_LD' +p1060 +sg1 +(g2 +g3 +VBIOMD0000000077 +p1061 +tp1062 +Rp1063 +(dp1064 +g8 +Nsg9 +I00 +sbS'Blum2000_LHsecretion_1' +p1065 +sg1 +(g2 +g3 +VBIOMD0000000076 +p1066 +tp1067 +Rp1068 +(dp1069 +g8 +Nsg9 +I00 +sbS'Cronwright2002_Glycerol_Synthesis' +p1070 +sg1 +(g2 +g3 +VBIOMD0000000075 +p1071 +tp1072 +Rp1073 +(dp1074 +g8 +Nsg9 +I00 +sbS'Xu2003_Phosphoinositide_turnover' +p1075 +sg1 +(g2 +g3 +VBIOMD0000000074 +p1076 +tp1077 +Rp1078 +(dp1079 +g8 +Nsg9 +I00 +sbS'Leloup2003_CircClock_DD_REV-ERBalpha' +p1080 +sg1 +(g2 +g3 +VBIOMD0000000073 +p1081 +tp1082 +Rp1083 +(dp1084 +g8 +Nsg9 +I00 +sbS'Leloup2003_CircClock_DD' +p1085 +sg1 +(g2 +g3 +VBIOMD0000000072 +p1086 +tp1087 +Rp1088 +(dp1089 +g8 +Nsg9 +I00 +sbS'Yi2003_GproteinCycle' +p1090 +sg1 +(g2 +g3 +VBIOMD0000000071 +p1091 +tp1092 +Rp1093 +(dp1094 +g8 +Nsg9 +I00 +sbS'Bakker2001_Glycolysis' +p1095 +sg1 +(g2 +g3 +VBIOMD0000000070 +p1096 +tp1097 +Rp1098 +(dp1099 +g8 +Nsg9 +I00 +sbS'Holzhutter2004_Erythrocyte_Metabolism' +p1100 +sg1 +(g2 +g3 +VBIOMD0000000079 +p1101 +tp1102 +Rp1103 +(dp1104 +g8 +Nsg9 +I00 +sbS'Goldbeter2006_weightCycling' +p1105 +sg1 +(g2 +g3 +VBIOMD0000000078 +p1106 +tp1107 +Rp1108 +(dp1109 +g8 +Nsg9 +I00 +sbS'Leloup2003_CircClock_LD' +p1110 +sg1 +(g2 +g3 +VBIOMD0000000358 +p1111 +tp1112 +Rp1113 +(dp1114 +g8 +Nsg9 +I00 +sbS'Stortelder1997 - Thrombin Generation Amidolytic Activity' +p1115 +sg1 +(g2 +g3 +VBIOMD0000000359 +p1116 +tp1117 +Rp1118 +(dp1119 +g8 +Nsg9 +I00 +sbS'Panteleev2002_TFPImechanism_schmema3' +p1120 +sg1 +(g2 +g3 +VBIOMD0000000123 +p1121 +tp1122 +Rp1123 +(dp1124 +g8 +Nsg9 +I00 +sbS'Fisher2006_NFAT_Activation' +p1125 +sg1 +(g2 +g3 +VBIOMD0000000352 +p1126 +tp1127 +Rp1128 +(dp1129 +g8 +Nsg9 +I00 +sbS'Vernoux2011_AuxinSignaling_AuxinFluctuating' +p1130 +sg1 +(g2 +g3 +VBIOMD0000000353 +p1131 +tp1132 +Rp1133 +(dp1134 +g8 +Nsg9 +I00 +sbS'Nag2011_ChloroplasticStarchDegradation' +p1135 +sg1 +(g2 +g3 +VBIOMD0000000350 +p1136 +tp1137 +Rp1138 +(dp1139 +g8 +Nsg9 +I00 +sbS'Troein2011_ClockCircuit_OstreococcusTauri' +p1140 +sg1 +(g2 +g3 +VBIOMD0000000351 +p1141 +tp1142 +Rp1143 +(dp1144 +g8 +Nsg9 +I00 +sbS'Vernoux2011_AuxinSignaling_AuxinSingleStepInput' +p1145 +sg1 +(g2 +g3 +VBIOMD0000000356 +p1146 +tp1147 +Rp1148 +(dp1149 +g8 +Nsg9 +I00 +sbS'Nyman2011_M3Hierarachical_InsulinGlucosedynamics' +p1150 +sg1 +(g2 +g3 +VBIOMD0000000357 +p1151 +tp1152 +Rp1153 +(dp1154 +g8 +Nsg9 +I00 +sbS'Lee2010_ThrombinActivation_OneForm_reduced' +p1155 +sg1 +(g2 +g3 +VBIOMD0000000354 +p1156 +tp1157 +Rp1158 +(dp1159 +g8 +Nsg9 +I00 +sbS'Abell2011_CalciumSignaling_WithoutAdaptation' +p1160 +sg1 +(g2 +g3 +VBIOMD0000000355 +p1161 +tp1162 +Rp1163 +(dp1164 +g8 +Nsg9 +I00 +sbS'Abell2011_CalciumSignaling_WithAdaptation' +p1165 +sg1 +(g2 +g3 +VBIOMD0000000213 +p1166 +tp1167 +Rp1168 +(dp1169 +g8 +Nsg9 +I00 +sbS'Nijhout2004_Folate_Cycle' +p1170 +sg1 +(g2 +g3 +VBIOMD0000000212 +p1171 +tp1172 +Rp1173 +(dp1174 +g8 +Nsg9 +I00 +sbS'Curien2009_Aspartate_Metabolism' +p1175 +sg1 +(g2 +g3 +VBIOMD0000000211 +p1176 +tp1177 +Rp1178 +(dp1179 +g8 +Nsg9 +I00 +sbS'Albert2005_Glycolysis' +p1180 +sg1 +(g2 +g3 +VBIOMD0000000210 +p1181 +tp1182 +Rp1183 +(dp1184 +g8 +Nsg9 +I00 +sbS'Chickarmane2008 - Stem cell lineage - NANOG GATA-6 switch' +p1185 +sg1 +(g2 +g3 +VBIOMD0000000217 +p1186 +tp1187 +Rp1188 +(dp1189 +g8 +Nsg9 +I00 +sbS'Bruggeman2005_AmmoniumAssimilation' +p1190 +sg1 +(g2 +g3 +VBIOMD0000000216 +p1191 +tp1192 +Rp1193 +(dp1194 +g8 +Nsg9 +I00 +sbS'Hong2009_CircadianClock' +p1195 +sg1 +(g2 +g3 +VBIOMD0000000215 +p1196 +tp1197 +Rp1198 +(dp1199 +g8 +Nsg9 +I00 +sbS'Schulz2009_Th1_differentiation' +p1200 +sg1 +(g2 +g3 +VBIOMD0000000214 +p1201 +tp1202 +Rp1203 +(dp1204 +g8 +Nsg9 +I00 +sbS'Akman2008_Circadian_Clock_Model2' +p1205 +sg1 +(g2 +g3 +VBIOMD0000000219 +p1206 +tp1207 +Rp1208 +(dp1209 +g8 +Nsg9 +I00 +sbS'Singh2006_TCA_mtu_model1' +p1210 +sg1 +(g2 +g3 +VBIOMD0000000218 +p1211 +tp1212 +Rp1213 +(dp1214 +g8 +Nsg9 +I00 +sbS'Singh2006_TCA_mtu_model2' +p1215 +sg1 +(g2 +g3 +VBIOMD0000000529 +p1216 +tp1217 +Rp1218 +(dp1219 +g8 +Nsg9 +I00 +sbS'Fribourg2014 - Dynamics of viral antagonism and innate immune response (H1N1 influenza A virus - NC/99)' +p1220 +sg1 +(g2 +g3 +VBIOMD0000000528 +p1221 +tp1222 +Rp1223 +(dp1224 +g8 +Nsg9 +I00 +sbS'Fribourg2014 - Dynamics of viral antagonism and innate immune response (H1N1 influenza A virus - Cal/09)' +p1225 +sg1 +(g2 +g3 +VBIOMD0000000521 +p1226 +tp1227 +Rp1228 +(dp1229 +g8 +Nsg9 +I00 +sbS'Ribba2012 - Low-grade gliomas, tumour growth inhibition model' +p1230 +sg1 +(g2 +g3 +VBIOMD0000000129 +p1231 +tp1232 +Rp1233 +(dp1234 +g8 +Nsg9 +I00 +sbS'Izhikevich2004_SpikingNeurons_inhibitionInducedSpiking' +p1235 +sg1 +(g2 +g3 +VBIOMD0000000523 +p1236 +tp1237 +Rp1238 +(dp1239 +g8 +Nsg9 +I00 +sbS'Kallenberger2014 - CD95L induced apoptosis initiated by caspase-8, CD95 HeLa cells (cis/trans variant)' +p1240 +sg1 +(g2 +g3 +VBIOMD0000000522 +p1241 +tp1242 +Rp1243 +(dp1244 +g8 +Nsg9 +I00 +sbS'Muraro2014 - Vascular patterning in Arabidopsis roots' +p1245 +sg1 +(g2 +g3 +VBIOMD0000000525 +p1246 +tp1247 +Rp1248 +(dp1249 +g8 +Nsg9 +I00 +sbS'Kallenberger2014 - CD95L induced apoptosis initiated by caspase-8, CD95 HeLa cells (cis/trans-cis/trans variant)' +p1250 +sg1 +(g2 +g3 +VBIOMD0000000524 +p1251 +tp1252 +Rp1253 +(dp1254 +g8 +Nsg9 +I00 +sbS'Kallenberger2014 - CD95L induced apoptosis initiated by caspase-8, wild-type HeLa cells (cis/trans variant)' +p1255 +sg1 +(g2 +g3 +VBIOMD0000000527 +p1256 +tp1257 +Rp1258 +(dp1259 +g8 +Nsg9 +I00 +sbS'Kaiser2014 - Salmonella persistence after ciprofloxacin treatment' +p1260 +sg1 +(g2 +g3 +VBIOMD0000000128 +p1261 +tp1262 +Rp1263 +(dp1264 +g8 +Nsg9 +I00 +sbS'Bertram2006_Endothelin' +p1265 +sg1 +(g2 +g3 +VBIOMD0000000459 +p1266 +tp1267 +Rp1268 +(dp1269 +g8 +Nsg9 +I00 +sbS'Liebal2012 - B.subtilis post-transcriptional instability model' +p1270 +sg1 +(g2 +g3 +VBIOMD0000000458 +p1271 +tp1272 +Rp1273 +(dp1274 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Serine biosynthesis' +p1275 +sg1 +(g2 +g3 +VBIOMD0000000329 +p1276 +tp1277 +Rp1278 +(dp1279 +g8 +Nsg9 +I00 +sbS'Kummer2000_CalciumSpiking' +p1280 +sg1 +(g2 +g3 +VBIOMD0000000328 +p1281 +tp1282 +Rp1283 +(dp1284 +g8 +Nsg9 +I00 +sbS'Bucher2011_Atorvastatin_Metabolism' +p1285 +sg1 +(g2 +g3 +VBIOMD0000000455 +p1286 +tp1287 +Rp1288 +(dp1289 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Metabolic Control Analysis - Example 2' +p1290 +sg1 +(g2 +g3 +VBIOMD0000000454 +p1291 +tp1292 +Rp1293 +(dp1294 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Metabolic Control Analysis - Example 1' +p1295 +sg1 +(g2 +g3 +VBIOMD0000000457 +p1296 +tp1297 +Rp1298 +(dp1299 +g8 +Nsg9 +I00 +sbS'Firczuk2013 - Eukaryotic mRNA translation machinery' +p1300 +sg1 +(g2 +g3 +VBIOMD0000000456 +p1301 +tp1302 +Rp1303 +(dp1304 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Metabolic Control Analysis - Example 3' +p1305 +sg1 +(g2 +g3 +VBIOMD0000000451 +p1306 +tp1307 +Rp1308 +(dp1309 +g8 +Nsg9 +I00 +sbS'Carbo2013 - Cytokine driven CD4+ T Cell differentiation and phenotype plasticity' +p1310 +sg1 +(g2 +g3 +VBIOMD0000000450 +p1311 +tp1312 +Rp1313 +(dp1314 +g8 +Nsg9 +I00 +sbS'Reyes-Palomares2012 - a combined model hepatic polyamine and sulfur aminoacid metabolism - version2' +p1315 +sg1 +(g2 +g3 +VBIOMD0000000453 +p1316 +tp1317 +Rp1318 +(dp1319 +g8 +Nsg9 +I00 +sbS'Bidkhori2012 - EGFR signalling in NSCLC' +p1320 +sg1 +(g2 +g3 +VBIOMD0000000452 +p1321 +tp1322 +Rp1323 +(dp1324 +g8 +Nsg9 +I00 +sbS'Bidkhori2012 - normal EGFR signalling' +p1325 +sg1 +(g2 +g3 +VBIOMD0000000442 +p1326 +tp1327 +Rp1328 +(dp1329 +g8 +Nsg9 +I00 +sbS'Sarma2012 - Oscillations in MAPK cascade (S2), inclusion of external signalling module' +p1330 +sg1 +(g2 +g3 +VBIOMD0000000443 +p1331 +tp1332 +Rp1333 +(dp1334 +g8 +Nsg9 +I00 +sbS'Sarma2012 - Oscillations in MAPK cascade (S1n)' +p1335 +sg1 +(g2 +g3 +VBIOMD0000000440 +p1336 +tp1337 +Rp1338 +(dp1339 +g8 +Nsg9 +I00 +sbS'Sarma2012 - Oscillations in MAPK cascade (S1)' +p1340 +sg1 +(g2 +g3 +VBIOMD0000000441 +p1341 +tp1342 +Rp1343 +(dp1344 +g8 +Nsg9 +I00 +sbS'Sarma2012 - Oscillations in MAPK cascade (S2)' +p1345 +sg1 +(g2 +g3 +VBIOMD0000000330 +p1346 +tp1347 +Rp1348 +(dp1349 +g8 +Nsg9 +I00 +sbS'Larsen2004_CalciumSpiking' +p1350 +sg1 +(g2 +g3 +VBIOMD0000000447 +p1351 +tp1352 +Rp1353 +(dp1354 +g8 +Nsg9 +I00 +sbS'Venkatraman2012 - Interplay between PLS and TSP1 in TGF-\xce\xb21 activation' +p1355 +sg1 +(g2 +g3 +VBIOMD0000000444 +p1356 +tp1357 +Rp1358 +(dp1359 +g8 +Nsg9 +I00 +sbS'Sarma2012 - Oscillations in MAPK cascade (S2n)' +p1360 +sg1 +(g2 +g3 +VBIOMD0000000445 +p1361 +tp1362 +Rp1363 +(dp1364 +g8 +Nsg9 +I00 +sbS'Pokhilko2013 - TOC1 signalling in Arabidopsis circadian clock' +p1365 +sg1 +(g2 +g3 +VBIOMD0000000162 +p1366 +tp1367 +Rp1368 +(dp1369 +g8 +Nsg9 +I00 +sbS'Hernjak2005_Calcium_Signaling' +p1370 +sg1 +(g2 +g3 +VBIOMD0000000132 +p1371 +tp1372 +Rp1373 +(dp1374 +g8 +Nsg9 +I00 +sbS'Izhikevich2004_SpikingNeurons_reboundSpike' +p1375 +sg1 +(g2 +g3 +VBIOMD0000000133 +p1376 +tp1377 +Rp1378 +(dp1379 +g8 +Nsg9 +I00 +sbS'Izhikevich2004_SpikingNeurons_resonator' +p1380 +sg1 +(g2 +g3 +VBIOMD0000000130 +p1381 +tp1382 +Rp1383 +(dp1384 +g8 +Nsg9 +I00 +sbS'Izhikevich2004_SpikingNeurons_integrator' +p1385 +sg1 +(g2 +g3 +VBIOMD0000000131 +p1386 +tp1387 +Rp1388 +(dp1389 +g8 +Nsg9 +I00 +sbS'Izhikevich2004_SpikingNeurons_reboundBurst' +p1390 +sg1 +(g2 +g3 +VBIOMD0000000136 +p1391 +tp1392 +Rp1393 +(dp1394 +g8 +Nsg9 +I00 +sbS'Izhikevich2004_SpikingNeurons_thresholdVariability' +p1395 +sg1 +(g2 +g3 +VBIOMD0000000137 +p1396 +tp1397 +Rp1398 +(dp1399 +g8 +Nsg9 +I00 +sbS'Sedaghat2002_InsulinSignalling_noFeedback' +p1400 +sg1 +(g2 +g3 +VBIOMD0000000134 +p1401 +tp1402 +Rp1403 +(dp1404 +g8 +Nsg9 +I00 +sbS'Izhikevich2004_SpikingNeurons_SpikeLatency' +p1405 +sg1 +(g2 +g3 +VBIOMD0000000135 +p1406 +tp1407 +Rp1408 +(dp1409 +g8 +Nsg9 +I00 +sbS'Izhikevich2004_SpikingNeurons_subthresholdOscillations' +p1410 +sg1 +(g2 +g3 +VBIOMD0000000033 +p1411 +tp1412 +Rp1413 +(dp1414 +g8 +Nsg9 +I00 +sbS'Brown2004_NGF_EGF_signaling' +p1415 +sg1 +(g2 +g3 +VBIOMD0000000032 +p1416 +tp1417 +Rp1418 +(dp1419 +g8 +Nsg9 +I00 +sbS'Kofahl2004_PheromonePathway' +p1420 +sg1 +(g2 +g3 +VBIOMD0000000138 +p1421 +tp1422 +Rp1423 +(dp1424 +g8 +Nsg9 +I00 +sbS'Tabak2007_dopamine' +p1425 +sg1 +(g2 +g3 +VBIOMD0000000139 +p1426 +tp1427 +Rp1428 +(dp1429 +g8 +Nsg9 +I00 +sbS'Hoffmann2002_KnockOut_IkBNFkB_Signaling' +p1430 +sg1 +(g2 +g3 +VBIOMD0000000037 +p1431 +tp1432 +Rp1433 +(dp1434 +g8 +Nsg9 +I00 +sbS'Marwan_Genetics_2003' +p1435 +sg1 +(g2 +g3 +VBIOMD0000000036 +p1436 +tp1437 +Rp1438 +(dp1439 +g8 +Nsg9 +I00 +sbS'Tyson1999_CircClock' +p1440 +sg1 +(g2 +g3 +VBIOMD0000000035 +p1441 +tp1442 +Rp1443 +(dp1444 +g8 +Nsg9 +I00 +sbS'Vilar2002_Oscillator' +p1445 +sg1 +(g2 +g3 +VBIOMD0000000034 +p1446 +tp1447 +Rp1448 +(dp1449 +g8 +Nsg9 +I00 +sbS'Smolen2004_CircClock' +p1450 +sg1 +(g2 +g3 +VBIOMD0000000492 +p1451 +tp1452 +Rp1453 +(dp1454 +g8 +Nsg9 +I00 +sbS'Pathak2013 - MAPK activation in response to various biotic stresses' +p1455 +sg1 +(g2 +g3 +VBIOMD0000000248 +p1456 +tp1457 +Rp1458 +(dp1459 +g8 +Nsg9 +I00 +sbS'Lai2007_O2_Transport_Metabolism' +p1460 +sg1 +(g2 +g3 +VBIOMD0000000249 +p1461 +tp1462 +Rp1463 +(dp1464 +g8 +Nsg9 +I00 +sbS'Restif2006_Whooping_Cough' +p1465 +sg1 +(g2 +g3 +VBIOMD0000000497 +p1466 +tp1467 +Rp1468 +(dp1469 +g8 +Nsg9 +I00 +sbS'Stanford2013 - Kinetic model of yeast metabolic network (regulation)' +p1470 +sg1 +(g2 +g3 +VBIOMD0000000496 +p1471 +tp1472 +Rp1473 +(dp1474 +g8 +Nsg9 +I00 +sbS'Stanford2013 - Kinetic model of yeast metabolic network (standard)' +p1475 +sg1 +(g2 +g3 +VBIOMD0000000499 +p1476 +tp1477 +Rp1478 +(dp1479 +g8 +Nsg9 +I00 +sbS'Vizan2013 - TGF pathway long term signaling' +p1480 +sg1 +(g2 +g3 +VBIOMD0000000398 +p1481 +tp1482 +Rp1483 +(dp1484 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_NeuralStemCellDifferentiation_Crosstalk' +p1485 +sg1 +(g2 +g3 +VBIOMD0000000399 +p1486 +tp1487 +Rp1488 +(dp1489 +g8 +Nsg9 +I00 +sbS'Jenkinson2011_EGF_MAPK' +p1490 +sg1 +(g2 +g3 +VBIOMD0000000396 +p1491 +tp1492 +Rp1493 +(dp1494 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_NotchSignalingPathway' +p1495 +sg1 +(g2 +g3 +VBIOMD0000000397 +p1496 +tp1497 +Rp1498 +(dp1499 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_WntSignalingPathway' +p1500 +sg1 +(g2 +g3 +VBIOMD0000000394 +p1501 +tp1502 +Rp1503 +(dp1504 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_EGFReceptorSignalingPathway' +p1505 +sg1 +(g2 +g3 +VBIOMD0000000395 +p1506 +tp1507 +Rp1508 +(dp1509 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_HedgehogSignalingPathway' +p1510 +sg1 +(g2 +g3 +VBIOMD0000000392 +p1511 +tp1512 +Rp1513 +(dp1514 +g8 +Nsg9 +I00 +sbS'Arnold2011_Laisk2006_CalvinCycle_Starch_Sucrose' +p1515 +sg1 +(g2 +g3 +VBIOMD0000000393 +p1516 +tp1517 +Rp1518 +(dp1519 +g8 +Nsg9 +I00 +sbS'Arnold2011_Zhu2007_CalvinCycle_Starch_Sucrose_Photorespiration' +p1520 +sg1 +(g2 +g3 +VBIOMD0000000390 +p1521 +tp1522 +Rp1523 +(dp1524 +g8 +Nsg9 +I00 +sbS'Arnold2011_Giersch1990_CalvinCycle' +p1525 +sg1 +(g2 +g3 +VBIOMD0000000391 +p1526 +tp1527 +Rp1528 +(dp1529 +g8 +Nsg9 +I00 +sbS'Arnold2011_Poolman2000_CalvinCycle_Starch' +p1530 +sg1 +(g2 +g3 +VBIOMD0000000247 +p1531 +tp1532 +Rp1533 +(dp1534 +g8 +Nsg9 +I00 +sbS'Ralser2007_Carbohydrate_Rerouting_ROS' +p1535 +sg1 +(g2 +g3 +VBIOMD0000000147 +p1536 +tp1537 +Rp1538 +(dp1539 +g8 +Nsg9 +I00 +sbS'ODea2007_IkappaB' +p1540 +sg1 +(g2 +g3 +VBIOMD0000000146 +p1541 +tp1542 +Rp1543 +(dp1544 +g8 +Nsg9 +I00 +sbS'Hatakeyama2003_MAPK' +p1545 +sg1 +(g2 +g3 +VBIOMD0000000145 +p1546 +tp1547 +Rp1548 +(dp1549 +g8 +Nsg9 +I00 +sbS'Wang2007_ATP_induced_Ca_Oscillation' +p1550 +sg1 +(g2 +g3 +VBIOMD0000000144 +p1551 +tp1552 +Rp1553 +(dp1554 +g8 +Nsg9 +I00 +sbS'Calzone2007_CellCycle' +p1555 +sg1 +(g2 +g3 +VBIOMD0000000143 +p1556 +tp1557 +Rp1558 +(dp1559 +g8 +Nsg9 +I00 +sbS'Olsen2003_neutrophil_oscillatory_metabolism' +p1560 +sg1 +(g2 +g3 +VBIOMD0000000142 +p1561 +tp1562 +Rp1563 +(dp1564 +g8 +Nsg9 +I00 +sbS'Izhikevich2004_SpikingNeurons_Class2Excitable' +p1565 +sg1 +(g2 +g3 +VBIOMD0000000141 +p1566 +tp1567 +Rp1568 +(dp1569 +g8 +Nsg9 +I00 +sbS'Izhikevich2004_SpikingNeurons_Class1Excitable' +p1570 +sg1 +(g2 +g3 +VBIOMD0000000140 +p1571 +tp1572 +Rp1573 +(dp1574 +g8 +Nsg9 +I00 +sbS'Hoffmann2002_WT_IkBNFkB_Signaling' +p1575 +sg1 +(g2 +g3 +VBIOMD0000000149 +p1576 +tp1577 +Rp1578 +(dp1579 +g8 +Nsg9 +I00 +sbS'Kim2007 - Crosstalk between Wnt and ERK pathways' +p1580 +sg1 +(g2 +g3 +VBIOMD0000000148 +p1581 +tp1582 +Rp1583 +(dp1584 +g8 +Nsg9 +I00 +sbS'Komarova2003_BoneRemodeling' +p1585 +sg1 +(g2 +g3 +VBIOMD0000000406 +p1586 +tp1587 +Rp1588 +(dp1589 +g8 +Nsg9 +I00 +sbS'Moriya2011_CellCycle_FissionYeast' +p1590 +sg1 +(g2 +g3 +VBIOMD0000000407 +p1591 +tp1592 +Rp1593 +(dp1594 +g8 +Nsg9 +I00 +sbS'Schliemann2011_TNF_ProAntiApoptosis' +p1595 +sg1 +(g2 +g3 +VBIOMD0000000404 +p1596 +tp1597 +Rp1598 +(dp1599 +g8 +Nsg9 +I00 +sbS'Bray1993_chemotaxis' +p1600 +sg1 +(g2 +g3 +VBIOMD0000000405 +p1601 +tp1602 +Rp1603 +(dp1604 +g8 +Nsg9 +I00 +sbS'Cookson2011_EnzymaticQueueingCoupling' +p1605 +sg1 +(g2 +g3 +VBIOMD0000000402 +p1606 +tp1607 +Rp1608 +(dp1609 +g8 +Nsg9 +I00 +sbS'Ayati2010_BoneRemodelingDynamics_WithTumour' +p1610 +sg1 +(g2 +g3 +VBIOMD0000000403 +p1611 +tp1612 +Rp1613 +(dp1614 +g8 +Nsg9 +I00 +sbS'Ayati2010_BoneRemodelingDynamics_WithTumour+DrugTreatment' +p1615 +sg1 +(g2 +g3 +VBIOMD0000000400 +p1616 +tp1617 +Rp1618 +(dp1619 +g8 +Nsg9 +I00 +sbS'Cooling2007_IP3transients_CardiacMyocyte' +p1620 +sg1 +(g2 +g3 +VBIOMD0000000401 +p1621 +tp1622 +Rp1623 +(dp1624 +g8 +Nsg9 +I00 +sbS'Ayati2010_BoneRemodelingDynamics_NormalCondition' +p1625 +sg1 +(g2 +g3 +VBIOMD0000000408 +p1626 +tp1627 +Rp1628 +(dp1629 +g8 +Nsg9 +I00 +sbS'Hettling2011_CreatineKinase' +p1630 +sg1 +(g2 +g3 +VBIOMD0000000409 +p1631 +tp1632 +Rp1633 +(dp1634 +g8 +Nsg9 +I00 +sbS'Queralt2006_MitoticExit_Cdc55DownregulationBySeparase' +p1635 +sg1 +(g2 +g3 +VBIOMD0000000363 +p1636 +tp1637 +Rp1638 +(dp1639 +g8 +Nsg9 +I00 +sbS'Lee2010_ThrombinActivation_OneForm_minimal' +p1640 +sg1 +(g2 +g3 +VBIOMD0000000362 +p1641 +tp1642 +Rp1643 +(dp1644 +g8 +Nsg9 +I00 +sbS'Butenas2004_BloodCoagulation' +p1645 +sg1 +(g2 +g3 +VBIOMD0000000361 +p1646 +tp1647 +Rp1648 +(dp1649 +g8 +Nsg9 +I00 +sbS'Panteleev2002_TFPImechanism_schmema1' +p1650 +sg1 +(g2 +g3 +VBIOMD0000000360 +p1651 +tp1652 +Rp1653 +(dp1654 +g8 +Nsg9 +I00 +sbS'Panteleev2002_TFPImechanism_schmema2' +p1655 +sg1 +(g2 +g3 +VBIOMD0000000367 +p1656 +tp1657 +Rp1658 +(dp1659 +g8 +Nsg9 +I00 +sbS'Mueller2008_ThrombinGeneration_minimal' +p1660 +sg1 +(g2 +g3 +VBIOMD0000000366 +p1661 +tp1662 +Rp1663 +(dp1664 +g8 +Nsg9 +I00 +sbS'Orfao2008_ThrombinGeneration_AmidolyticActivity' +p1665 +sg1 +(g2 +g3 +VBIOMD0000000365 +p1666 +tp1667 +Rp1668 +(dp1669 +g8 +Nsg9 +I00 +sbS'Hockin1999_BloodCoagulation_VaInactivation' +p1670 +sg1 +(g2 +g3 +VBIOMD0000000364 +p1671 +tp1672 +Rp1673 +(dp1674 +g8 +Nsg9 +I00 +sbS'Lee2010_ThrombinActivation_OneForm' +p1675 +sg1 +(g2 +g3 +VBIOMD0000000244 +p1676 +tp1677 +Rp1678 +(dp1679 +g8 +Nsg9 +I00 +sbS'Kotte2010_Ecoli_Metabolic_Adaption' +p1680 +sg1 +(g2 +g3 +VBIOMD0000000245 +p1681 +tp1682 +Rp1683 +(dp1684 +g8 +Nsg9 +I00 +sbS'Lei2001_Yeast_Aerobic_Metabolism' +p1685 +sg1 +(g2 +g3 +VBIOMD0000000369 +p1686 +tp1687 +Rp1688 +(dp1689 +g8 +Nsg9 +I00 +sbS'Beltrami1995_ThrombinGeneration_D' +p1690 +sg1 +(g2 +g3 +VBIOMD0000000368 +p1691 +tp1692 +Rp1693 +(dp1694 +g8 +Nsg9 +I00 +sbS'Beltrami1995_ThrombinGeneration_C' +p1695 +sg1 +(g2 +g3 +VBIOMD0000000240 +p1696 +tp1697 +Rp1698 +(dp1699 +g8 +Nsg9 +I00 +sbS'Veening2008_DegU_Regulation' +p1700 +sg1 +(g2 +g3 +VBIOMD0000000241 +p1701 +tp1702 +Rp1703 +(dp1704 +g8 +Nsg9 +I00 +sbS'Shi1993_Caffeine_pressor_tolerance' +p1705 +sg1 +(g2 +g3 +VBIOMD0000000242 +p1706 +tp1707 +Rp1708 +(dp1709 +g8 +Nsg9 +I00 +sbS'Bai2003_G1phaseRegulation' +p1710 +sg1 +(g2 +g3 +VBIOMD0000000243 +p1711 +tp1712 +Rp1713 +(dp1714 +g8 +Nsg9 +I00 +sbS'Neumann2010_CD95Stimulation_NFkB_Apoptosis' +p1715 +sg1 +(g2 +g3 +VBIOMD0000000383 +p1716 +tp1717 +Rp1718 +(dp1719 +g8 +Nsg9 +I00 +sbS'Arnold2011_Farquhar1980_RuBisCO-CalvinCycle' +p1720 +sg1 +(g2 +g3 +VBIOMD0000000382 +p1721 +tp1722 +Rp1723 +(dp1724 +g8 +Nsg9 +I00 +sbS'Sturis1991_InsulinGlucoseModel_UltradianOscillation' +p1725 +sg1 +(g2 +g3 +VBIOMD0000000222 +p1726 +tp1727 +Rp1728 +(dp1729 +g8 +Nsg9 +I00 +sbS'Singh2006_TCA_Ecoli_glucose' +p1730 +sg1 +(g2 +g3 +VBIOMD0000000223 +p1731 +tp1732 +Rp1733 +(dp1734 +g8 +Nsg9 +I00 +sbS'Borisov2009_EGF_Insulin_Crosstalk' +p1735 +sg1 +(g2 +g3 +VBIOMD0000000561 +p1736 +tp1737 +Rp1738 +(dp1739 +g8 +Nsg9 +I00 +sbS'Martins2013 - True and apparent inhibition of amyloid fribril formation' +p1740 +sg1 +(g2 +g3 +VBIOMD0000000560 +p1741 +tp1742 +Rp1743 +(dp1744 +g8 +Nsg9 +I00 +sbS'Hui2014 - Age-related changes in articular cartilage' +p1745 +sg1 +(g2 +g3 +VBIOMD0000000520 +p1746 +tp1747 +Rp1748 +(dp1749 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Colon Crypt cycle - Version 0' +p1750 +sg1 +(g2 +g3 +VBIOMD0000000190 +p1751 +tp1752 +Rp1753 +(dp1754 +g8 +Nsg9 +I00 +sbS'Rodriguez-Caso2006_Polyamine_Metabolism' +p1755 +sg1 +(g2 +g3 +VBIOMD0000000191 +p1756 +tp1757 +Rp1758 +(dp1759 +g8 +Nsg9 +I00 +sbS'Monta\xc3\xb1ez2008_Arginine_catabolism' +p1760 +sg1 +(g2 +g3 +VBIOMD0000000192 +p1761 +tp1762 +Rp1763 +(dp1764 +g8 +Nsg9 +I00 +sbS'G\xc3\xb6rlich2003_RanGTP_gradient' +p1765 +sg1 +(g2 +g3 +VBIOMD0000000193 +p1766 +tp1767 +Rp1768 +(dp1769 +g8 +Nsg9 +I00 +sbS'Ibrahim2008_MCC_assembly_model_KDM' +p1770 +sg1 +(g2 +g3 +VBIOMD0000000194 +p1771 +tp1772 +Rp1773 +(dp1774 +g8 +Nsg9 +I00 +sbS'Ibrahim2008_Cdc20_Sequestring_Template_Model' +p1775 +sg1 +(g2 +g3 +VBIOMD0000000195 +p1776 +tp1777 +Rp1778 +(dp1779 +g8 +Nsg9 +I00 +sbS'Tyson2001_Cell_Cycle_Regulation' +p1780 +sg1 +(g2 +g3 +VBIOMD0000000196 +p1781 +tp1782 +Rp1783 +(dp1784 +g8 +Nsg9 +I00 +sbS'Srividhya2006_CellCycle' +p1785 +sg1 +(g2 +g3 +VBIOMD0000000197 +p1786 +tp1787 +Rp1788 +(dp1789 +g8 +Nsg9 +I00 +sbS'Bartholome2007_MDCKII' +p1790 +sg1 +(g2 +g3 +VBIOMD0000000198 +p1791 +tp1792 +Rp1793 +(dp1794 +g8 +Nsg9 +I00 +sbS'Stone1996_NOsGC' +p1795 +sg1 +(g2 +g3 +VBIOMD0000000199 +p1796 +tp1797 +Rp1798 +(dp1799 +g8 +Nsg9 +I00 +sbS'Santolini2001_nNOS_Mechanism_Regulation' +p1800 +sg1 +(g2 +g3 +VBIOMD0000000299 +p1801 +tp1802 +Rp1803 +(dp1804 +g8 +Nsg9 +I00 +sbS'Leloup1999_CircadianRhythms_Neurospora' +p1805 +sg1 +(g2 +g3 +VBIOMD0000000298 +p1806 +tp1807 +Rp1808 +(dp1809 +g8 +Nsg9 +I00 +sbS'Leloup1999_CircadianRhythms_Drosophila' +p1810 +sg1 +(g2 +g3 +VBIOMD0000000293 +p1811 +tp1812 +Rp1813 +(dp1814 +g8 +Nsg9 +I00 +sbS'Proctor2010_UCHL1_ProteinAggregation' +p1815 +sg1 +(g2 +g3 +VBIOMD0000000292 +p1816 +tp1817 +Rp1818 +(dp1819 +g8 +Nsg9 +I00 +sbS'Rovers1995_Photsynthetic_Oscillations' +p1820 +sg1 +(g2 +g3 +VBIOMD0000000291 +p1821 +tp1822 +Rp1823 +(dp1824 +g8 +Nsg9 +I00 +sbS'Nikolaev2005_AlbuminBilirubinAdsorption' +p1825 +sg1 +(g2 +g3 +VBIOMD0000000290 +p1826 +tp1827 +Rp1828 +(dp1829 +g8 +Nsg9 +I00 +sbS'Alexander2010_Tcell_Regulation_Sys2' +p1830 +sg1 +(g2 +g3 +VBIOMD0000000297 +p1831 +tp1832 +Rp1833 +(dp1834 +g8 +Nsg9 +I00 +sbS'Ciliberto2003_Morphogenesis_Checkpoint' +p1835 +sg1 +(g2 +g3 +VBIOMD0000000296 +p1836 +tp1837 +Rp1838 +(dp1839 +g8 +Nsg9 +I00 +sbS'Balagadd\xc3\xa92008_E_coli_Predator_Prey' +p1840 +sg1 +(g2 +g3 +VBIOMD0000000295 +p1841 +tp1842 +Rp1843 +(dp1844 +g8 +Nsg9 +I00 +sbS'Akman2008_Circadian_Clock_Model1' +p1845 +sg1 +(g2 +g3 +VBIOMD0000000294 +p1846 +tp1847 +Rp1848 +(dp1849 +g8 +Nsg9 +I00 +sbS'Restif2007_Vaccination_Invasion' +p1850 +sg1 +(g2 +g3 +VBIOMD0000000109 +p1851 +tp1852 +Rp1853 +(dp1854 +g8 +Nsg9 +I00 +sbS'Haberichter2007_cellcycle' +p1855 +sg1 +(g2 +g3 +VBIOMD0000000108 +p1856 +tp1857 +Rp1858 +(dp1859 +g8 +Nsg9 +I00 +sbS'Kowald2006_SOD' +p1860 +sg1 +(g2 +g3 +VBIOMD0000000103 +p1861 +tp1862 +Rp1863 +(dp1864 +g8 +Nsg9 +I00 +sbS'Legewie2006_apoptosis_NC' +p1865 +sg1 +(g2 +g3 +VBIOMD0000000102 +p1866 +tp1867 +Rp1868 +(dp1869 +g8 +Nsg9 +I00 +sbS'Legewie2006_apoptosis_WT' +p1870 +sg1 +(g2 +g3 +VBIOMD0000000101 +p1871 +tp1872 +Rp1873 +(dp1874 +g8 +Nsg9 +I00 +sbS'Vilar2006_TGFbeta' +p1875 +sg1 +(g2 +g3 +VBIOMD0000000100 +p1876 +tp1877 +Rp1878 +(dp1879 +g8 +Nsg9 +I00 +sbS'Rozi2003_GlycogenPhosphorylase_Activation' +p1880 +sg1 +(g2 +g3 +VBIOMD0000000107 +p1881 +tp1882 +Rp1883 +(dp1884 +g8 +Nsg9 +I00 +sbS'Novak1993_M_phase_control' +p1885 +sg1 +(g2 +g3 +VBIOMD0000000106 +p1886 +tp1887 +Rp1888 +(dp1889 +g8 +Nsg9 +I00 +sbS'Yang2007_ArachidonicAcid' +p1890 +sg1 +(g2 +g3 +VBIOMD0000000105 +p1891 +tp1892 +Rp1893 +(dp1894 +g8 +Nsg9 +I00 +sbS'Proctor2007_ubiquitine' +p1895 +sg1 +(g2 +g3 +VBIOMD0000000104 +p1896 +tp1897 +Rp1898 +(dp1899 +g8 +Nsg9 +I00 +sbS'Klipp2002_MetabolicOptimization_linearPathway(n=2)' +p1900 +sg1 +(g2 +g3 +VBIOMD0000000064 +p1901 +tp1902 +Rp1903 +(dp1904 +g8 +Nsg9 +I00 +sbS'Teusink2000_Glycolysis' +p1905 +sg1 +(g2 +g3 +VBIOMD0000000065 +p1906 +tp1907 +Rp1908 +(dp1909 +g8 +Nsg9 +I00 +sbS'Yildirim2003_Lac_Operon' +p1910 +sg1 +(g2 +g3 +VBIOMD0000000066 +p1911 +tp1912 +Rp1913 +(dp1914 +g8 +Nsg9 +I00 +sbS'Chassagnole2001_Threonine Synthesis' +p1915 +sg1 +(g2 +g3 +VBIOMD0000000067 +p1916 +tp1917 +Rp1918 +(dp1919 +g8 +Nsg9 +I00 +sbS'Fung2005_Metabolic_Oscillator' +p1920 +sg1 +(g2 +g3 +VBIOMD0000000060 +p1921 +tp1922 +Rp1923 +(dp1924 +g8 +Nsg9 +I00 +sbS'Keizer1996_Ryanodine_receptor_adaptation' +p1925 +sg1 +(g2 +g3 +VBIOMD0000000061 +p1926 +tp1927 +Rp1928 +(dp1929 +g8 +Nsg9 +I00 +sbS'Hynne2001_Glycolysis' +p1930 +sg1 +(g2 +g3 +VBIOMD0000000062 +p1931 +tp1932 +Rp1933 +(dp1934 +g8 +Nsg9 +I00 +sbS'Bhartiya2003_Tryptophan_operon' +p1935 +sg1 +(g2 +g3 +VBIOMD0000000063 +p1936 +tp1937 +Rp1938 +(dp1939 +g8 +Nsg9 +I00 +sbS'Galazzo1990_FermentationPathwayKinetics' +p1940 +sg1 +(g2 +g3 +VBIOMD0000000068 +p1941 +tp1942 +Rp1943 +(dp1944 +g8 +Nsg9 +I00 +sbS'Curien2003_MetThr_synthesis' +p1945 +sg1 +(g2 +g3 +VBIOMD0000000069 +p1946 +tp1947 +Rp1948 +(dp1949 +g8 +Nsg9 +I00 +sbS'Fuss2006_MitoticActivation' +p1950 +sg1 +(g2 +g3 +VBIOMD0000000550 +p1951 +tp1952 +Rp1953 +(dp1954 +g8 +Nsg9 +I00 +sbS'Baker2013 - Cytokine Mediated Inflammation in Rheumatoid Arthritis' +p1955 +sg1 +(g2 +g3 +VBIOMD0000000551 +p1956 +tp1957 +Rp1958 +(dp1959 +g8 +Nsg9 +I00 +sbS'Das2010 - Effect of a gamma-secretase inhibitor on Amyloid-beta dynamics' +p1960 +sg1 +(g2 +g3 +VBIOMD0000000088 +p1961 +tp1962 +Rp1963 +(dp1964 +g8 +Nsg9 +I00 +sbS'Maeda2006_MyosinPhosphorylation' +p1965 +sg1 +(g2 +g3 +VBIOMD0000000200 +p1966 +tp1967 +Rp1968 +(dp1969 +g8 +Nsg9 +I00 +sbS'Bray1995_chemotaxis_receptorlinkedcomplex' +p1970 +sg1 +(g2 +g3 +VBIOMD0000000201 +p1971 +tp1972 +Rp1973 +(dp1974 +g8 +Nsg9 +I00 +sbS'Goldbeter2008_Somite_Segmentation_Clock_Notch_Wnt_FGF' +p1975 +sg1 +(g2 +g3 +VBIOMD0000000202 +p1976 +tp1977 +Rp1978 +(dp1979 +g8 +Nsg9 +I00 +sbS'ChenXF2008_CICR' +p1980 +sg1 +(g2 +g3 +VBIOMD0000000203 +p1981 +tp1982 +Rp1983 +(dp1984 +g8 +Nsg9 +I00 +sbS'Chickarmane2006 - Stem cell switch reversible' +p1985 +sg1 +(g2 +g3 +VBIOMD0000000204 +p1986 +tp1987 +Rp1988 +(dp1989 +g8 +Nsg9 +I00 +sbS'Chickarmane2006 - Stem cell switch irreversible' +p1990 +sg1 +(g2 +g3 +VBIOMD0000000205 +p1991 +tp1992 +Rp1993 +(dp1994 +g8 +Nsg9 +I00 +sbS'Ung2008_EGFR_Endocytosis' +p1995 +sg1 +(g2 +g3 +VBIOMD0000000206 +p1996 +tp1997 +Rp1998 +(dp1999 +g8 +Nsg9 +I00 +sbS'Wolf2000_Glycolytic_Oscillations' +p2000 +sg1 +(g2 +g3 +VBIOMD0000000207 +p2001 +tp2002 +Rp2003 +(dp2004 +g8 +Nsg9 +I00 +sbS'Romond1999_CellCycle' +p2005 +sg1 +(g2 +g3 +VBIOMD0000000208 +p2006 +tp2007 +Rp2008 +(dp2009 +g8 +Nsg9 +I00 +sbS'Deineko2003_CellCycle' +p2010 +sg1 +(g2 +g3 +VBIOMD0000000209 +p2011 +tp2012 +Rp2013 +(dp2014 +g8 +Nsg9 +I00 +sbS'Chickarmane2008 - Stem cell lineage determination' +p2015 +sg1 +(g2 +g3 +VBIOMD0000000536 +p2016 +tp2017 +Rp2018 +(dp2019 +g8 +Nsg9 +I00 +sbS'Dwivedi2014 - Crohns IL6 Disease model - sgp130 activity' +p2020 +sg1 +(g2 +g3 +VBIOMD0000000537 +p2021 +tp2022 +Rp2023 +(dp2024 +g8 +Nsg9 +I00 +sbS'Dwivedi2014 - Crohns IL6 Disease model - Anti-IL6R Antibody' +p2025 +sg1 +(g2 +g3 +VBIOMD0000000534 +p2026 +tp2027 +Rp2028 +(dp2029 +g8 +Nsg9 +I00 +sbS'Dwivedi2014 - Healthy Volunteer IL6 Model' +p2030 +sg1 +(g2 +g3 +VBIOMD0000000535 +p2031 +tp2032 +Rp2033 +(dp2034 +g8 +Nsg9 +I00 +sbS'Dwivedi2014 - Crohns IL6 Disease model - Anti-IL6 Antibody' +p2035 +sg1 +(g2 +g3 +VBIOMD0000000532 +p2036 +tp2037 +Rp2038 +(dp2039 +g8 +Nsg9 +I00 +sbS'Vazquez2014 - Chemical inhibition from amyloid protein aggregation kinetics' +p2040 +sg1 +(g2 +g3 +VBIOMD0000000533 +p2041 +tp2042 +Rp2043 +(dp2044 +g8 +Nsg9 +I00 +sbS'Steckmann2012 - Amyloid beta-protein fibrillogenesis (kinetics of secondary structure conversion)' +p2045 +sg1 +(g2 +g3 +VBIOMD0000000439 +p2046 +tp2047 +Rp2048 +(dp2049 +g8 +Nsg9 +I00 +sbS'Smith2009 - RGS mediated GTP hydrolysis' +p2050 +sg1 +(g2 +g3 +VBIOMD0000000438 +p2051 +tp2052 +Rp2053 +(dp2054 +g8 +Nsg9 +I00 +sbS'Saeidi2012 - Quorum sensing device that produces GFP' +p2055 +sg1 +(g2 +g3 +VBIOMD0000000437 +p2056 +tp2057 +Rp2058 +(dp2059 +g8 +Nsg9 +I00 +sbS'Tseng2012 - Circadian clock of N.crassa' +p2060 +sg1 +(g2 +g3 +VBIOMD0000000436 +p2061 +tp2062 +Rp2063 +(dp2064 +g8 +Nsg9 +I00 +sbS'Gupta2009 - Eicosanoid Metabolism' +p2065 +sg1 +(g2 +g3 +VBIOMD0000000435 +p2066 +tp2067 +Rp2068 +(dp2069 +g8 +Nsg9 +I00 +sbS'deBack2012 - Lineage Specification in Pancreas Development' +p2070 +sg1 +(g2 +g3 +VBIOMD0000000434 +p2071 +tp2072 +Rp2073 +(dp2074 +g8 +Nsg9 +I00 +sbS'McAuley2012 - Whole-body Cholesterol Metabolism' +p2075 +sg1 +(g2 +g3 +VBIOMD0000000433 +p2076 +tp2077 +Rp2078 +(dp2079 +g8 +Nsg9 +I00 +sbS'Sarma2012 - Interaction topologies of MAPK cascade (M4_K2_QSS_PSEQ)' +p2080 +sg1 +(g2 +g3 +VBIOMD0000000432 +p2081 +tp2082 +Rp2083 +(dp2084 +g8 +Nsg9 +I00 +sbS'Sarma2012 - Interaction topologies of MAPK cascade (M4_K2_QSS_USEQ)' +p2085 +sg1 +(g2 +g3 +VBIOMD0000000431 +p2086 +tp2087 +Rp2088 +(dp2089 +g8 +Nsg9 +I00 +sbS'Sarma2012 - Interaction topologies of MAPK cascade (M4_K2_PSEQ)' +p2090 +sg1 +(g2 +g3 +VBIOMD0000000430 +p2091 +tp2092 +Rp2093 +(dp2094 +g8 +Nsg9 +I00 +sbS'Sarma2012 - Interaction topologies of MAPK cascade (M4_K2_USEQ)' +p2095 +sg1 +(g2 +g3 +VBIOMD0000000082 +p2096 +tp2097 +Rp2098 +(dp2099 +g8 +Nsg9 +I00 +sbS'Thomsen1988_AdenylateCyclase_Inhibition' +p2100 +sg1 +(g2 +g3 +VBIOMD0000000083 +p2101 +tp2102 +Rp2103 +(dp2104 +g8 +Nsg9 +I00 +sbS'Leloup2003_CircClock_LD_REV-ERBalpha' +p2105 +sg1 +(g2 +g3 +VBIOMD0000000448 +p2106 +tp2107 +Rp2108 +(dp2109 +g8 +Nsg9 +I00 +sbS'Br\xc3\xa4nnmark2013 - Insulin signalling in human adipocytes (normal condition)' +p2110 +sg1 +(g2 +g3 +VBIOMD0000000449 +p2111 +tp2112 +Rp2113 +(dp2114 +g8 +Nsg9 +I00 +sbS'Br\xc3\xa4nnmark2013 - Insulin signalling in human adipocytes (diabetic condition)' +p2115 +sg1 +(g2 +g3 +VBIOMD0000000338 +p2116 +tp2117 +Rp2118 +(dp2119 +g8 +Nsg9 +I00 +sbS'Wajima2009_BloodCoagulation_aPTTtest' +p2120 +sg1 +(g2 +g3 +VBIOMD0000000339 +p2121 +tp2122 +Rp2123 +(dp2124 +g8 +Nsg9 +I00 +sbS'Wajima2009_BloodCoagulation_PTtest' +p2125 +sg1 +(g2 +g3 +VBIOMD0000000334 +p2126 +tp2127 +Rp2128 +(dp2129 +g8 +Nsg9 +I00 +sbS'Bungay2003_Thrombin_Generation' +p2130 +sg1 +(g2 +g3 +VBIOMD0000000335 +p2131 +tp2132 +Rp2133 +(dp2134 +g8 +Nsg9 +I00 +sbS'Hockin2002_BloodCoagulation' +p2135 +sg1 +(g2 +g3 +VBIOMD0000000336 +p2136 +tp2137 +Rp2138 +(dp2139 +g8 +Nsg9 +I00 +sbS'Jones1994_BloodCoagulation' +p2140 +sg1 +(g2 +g3 +VBIOMD0000000337 +p2141 +tp2142 +Rp2143 +(dp2144 +g8 +Nsg9 +I00 +sbS'Pfeiffer2001_ATP-ProducingPathways_CooperationCompetition' +p2145 +sg1 +(g2 +g3 +VBIOMD0000000446 +p2146 +tp2147 +Rp2148 +(dp2149 +g8 +Nsg9 +I00 +sbS'Erguler2013 - Unfolded protein stress response' +p2150 +sg1 +(g2 +g3 +VBIOMD0000000331 +p2151 +tp2152 +Rp2153 +(dp2154 +g8 +Nsg9 +I00 +sbS'Larsen2004_CalciumSpiking_EnzymeBinding' +p2155 +sg1 +(g2 +g3 +VBIOMD0000000332 +p2156 +tp2157 +Rp2158 +(dp2159 +g8 +Nsg9 +I00 +sbS'Bungay2006_Plasma' +p2160 +sg1 +(g2 +g3 +VBIOMD0000000333 +p2161 +tp2162 +Rp2163 +(dp2164 +g8 +Nsg9 +I00 +sbS'Bungay2006_FollicularFluid' +p2165 +sg1 +(g2 +g3 +VBIOMD0000000327 +p2166 +tp2167 +Rp2168 +(dp2169 +g8 +Nsg9 +I00 +sbS'Whitcomb2004_Bicarbonate_Pancreas' +p2170 +sg1 +(g2 +g3 +VBIOMD0000000326 +p2171 +tp2172 +Rp2173 +(dp2174 +g8 +Nsg9 +I00 +sbS'DellOrco2009_phototransduction' +p2175 +sg1 +(g2 +g3 +VBIOMD0000000325 +p2176 +tp2177 +Rp2178 +(dp2179 +g8 +Nsg9 +I00 +sbS'Palini2011_Minimal_2_Feedback_Model' +p2180 +sg1 +(g2 +g3 +VBIOMD0000000028 +p2181 +tp2182 +Rp2183 +(dp2184 +g8 +Nsg9 +I00 +sbS'Markevich2004_MAPK_phosphoRandomElementary' +p2185 +sg1 +(g2 +g3 +VBIOMD0000000029 +p2186 +tp2187 +Rp2188 +(dp2189 +g8 +Nsg9 +I00 +sbS'Markevich2004_MAPK_phosphoRandomMM' +p2190 +sg1 +(g2 +g3 +VBIOMD0000000324 +p2191 +tp2192 +Rp2193 +(dp2194 +g8 +Nsg9 +I00 +sbS'Morris1981_MuscleFibre_Voltage_full' +p2195 +sg1 +(g2 +g3 +VBIOMD0000000020 +p2196 +tp2197 +Rp2198 +(dp2199 +g8 +Nsg9 +I00 +sbS'Hodgkin-Huxley1952 squid-axon' +p2200 +sg1 +(g2 +g3 +VBIOMD0000000021 +p2201 +tp2202 +Rp2203 +(dp2204 +g8 +Nsg9 +I00 +sbS'Leloup1999_CircClock' +p2205 +sg1 +(g2 +g3 +VBIOMD0000000022 +p2206 +tp2207 +Rp2208 +(dp2209 +g8 +Nsg9 +I00 +sbS'Ueda2001_CircClock' +p2210 +sg1 +(g2 +g3 +VBIOMD0000000023 +p2211 +tp2212 +Rp2213 +(dp2214 +g8 +Nsg9 +I00 +sbS'Rohwer2001_Sucrose' +p2215 +sg1 +(g2 +g3 +VBIOMD0000000024 +p2216 +tp2217 +Rp2218 +(dp2219 +g8 +Nsg9 +I00 +sbS'Scheper1999_CircClock' +p2220 +sg1 +(g2 +g3 +VBIOMD0000000025 +p2221 +tp2222 +Rp2223 +(dp2224 +g8 +Nsg9 +I00 +sbS'Smolen2002_CircClock' +p2225 +sg1 +(g2 +g3 +VBIOMD0000000026 +p2226 +tp2227 +Rp2228 +(dp2229 +g8 +Nsg9 +I00 +sbS'Markevich2004_MAPK_orderedElementary' +p2230 +sg1 +(g2 +g3 +VBIOMD0000000027 +p2231 +tp2232 +Rp2233 +(dp2234 +g8 +Nsg9 +I00 +sbS'Markevich2004_MAPK_orderedMM' +p2235 +sg1 +(g2 +g3 +VBIOMD0000000321 +p2236 +tp2237 +Rp2238 +(dp2239 +g8 +Nsg9 +I00 +sbS'Grange2001 - L Dopa PK model' +p2240 +sg1 +(g2 +g3 +VBIOMD0000000320 +p2241 +tp2242 +Rp2243 +(dp2244 +g8 +Nsg9 +I00 +sbS'Grange2001 - PK interaction of L-dopa and benserazide' +p2245 +sg1 +(g2 +g3 +VBIOMD0000000491 +p2246 +tp2247 +Rp2248 +(dp2249 +g8 +Nsg9 +I00 +sbS'Pathak2013 - MAPK activation in response to various abiotic stresses' +p2250 +sg1 +(g2 +g3 +VBIOMD0000000151 +p2251 +tp2252 +Rp2253 +(dp2254 +g8 +Nsg9 +I00 +sbS'Singh2006_IL6_Signal_Transduction' +p2255 +sg1 +(g2 +g3 +VBIOMD0000000154 +p2256 +tp2257 +Rp2258 +(dp2259 +g8 +Nsg9 +I00 +sbS'Zatorsky2006_p53_Model3' +p2260 +sg1 +(g2 +g3 +VBIOMD0000000155 +p2261 +tp2262 +Rp2263 +(dp2264 +g8 +Nsg9 +I00 +sbS'Zatorsky2006_p53_Model6' +p2265 +sg1 +(g2 +g3 +VBIOMD0000000156 +p2266 +tp2267 +Rp2268 +(dp2269 +g8 +Nsg9 +I00 +sbS'Zatorsky2006_p53_Model5' +p2270 +sg1 +(g2 +g3 +VBIOMD0000000157 +p2271 +tp2272 +Rp2273 +(dp2274 +g8 +Nsg9 +I00 +sbS'Zatorsky2006_p53_Model4' +p2275 +sg1 +(g2 +g3 +VBIOMD0000000150 +p2276 +tp2277 +Rp2278 +(dp2279 +g8 +Nsg9 +I00 +sbS'Morris2002_CellCycle_CDK2Cyclin' +p2280 +sg1 +(g2 +g3 +VBIOMD0000000098 +p2281 +tp2282 +Rp2283 +(dp2284 +g8 +Nsg9 +I00 +sbS'Goldbeter1990_CalciumSpike_CICR' +p2285 +sg1 +(g2 +g3 +VBIOMD0000000152 +p2286 +tp2287 +Rp2288 +(dp2289 +g8 +Nsg9 +I00 +sbS'Fernandez2006_ModelA' +p2290 +sg1 +(g2 +g3 +VBIOMD0000000153 +p2291 +tp2292 +Rp2293 +(dp2294 +g8 +Nsg9 +I00 +sbS'Fernandez2006_ModelB' +p2295 +sg1 +(g2 +g3 +VBIOMD0000000095 +p2296 +tp2297 +Rp2298 +(dp2299 +g8 +Nsg9 +I00 +sbS'Zeilinger2006_PRR7-PRR9-Y' +p2300 +sg1 +(g2 +g3 +VBIOMD0000000094 +p2301 +tp2302 +Rp2303 +(dp2304 +g8 +Nsg9 +I00 +sbS'Yamada2003_JAK_STAT_SOCS1_knockout' +p2305 +sg1 +(g2 +g3 +VBIOMD0000000097 +p2306 +tp2307 +Rp2308 +(dp2309 +g8 +Nsg9 +I00 +sbS'Zeilinger2006_PRR7-PRR9light-Yprime' +p2310 +sg1 +(g2 +g3 +VBIOMD0000000096 +p2311 +tp2312 +Rp2313 +(dp2314 +g8 +Nsg9 +I00 +sbS'Zeilinger2006_PRR7-PRR9light-Y' +p2315 +sg1 +(g2 +g3 +VBIOMD0000000091 +p2316 +tp2317 +Rp2318 +(dp2319 +g8 +Nsg9 +I00 +sbS'Proctor2005 - Actions of chaperones and their role in ageing' +p2320 +sg1 +(g2 +g3 +VBIOMD0000000090 +p2321 +tp2322 +Rp2323 +(dp2324 +g8 +Nsg9 +I00 +sbS'Wolf2001_Respiratory_Oscillations' +p2325 +sg1 +(g2 +g3 +VBIOMD0000000093 +p2326 +tp2327 +Rp2328 +(dp2329 +g8 +Nsg9 +I00 +sbS'Yamada2003_JAK_STAT_pathway' +p2330 +sg1 +(g2 +g3 +VBIOMD0000000092 +p2331 +tp2332 +Rp2333 +(dp2334 +g8 +Nsg9 +I00 +sbS'Fuentes2005_ZymogenActivation' +p2335 +sg1 +(g2 +g3 +VBIOMD0000000473 +p2336 +tp2337 +Rp2338 +(dp2339 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Yeast metabolic model with modular rate law, merged with Pritchard 2002' +p2340 +sg1 +(g2 +g3 +VBIOMD0000000472 +p2341 +tp2342 +Rp2343 +(dp2344 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Yeast metabolic model with modular rate law' +p2345 +sg1 +(g2 +g3 +VBIOMD0000000471 +p2346 +tp2347 +Rp2348 +(dp2349 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Yeast metabolic model with linlog rate law' +p2350 +sg1 +(g2 +g3 +VBIOMD0000000470 +p2351 +tp2352 +Rp2353 +(dp2354 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - E.coli metabolic model with modular rate law' +p2355 +sg1 +(g2 +g3 +VBIOMD0000000477 +p2356 +tp2357 +Rp2358 +(dp2359 +g8 +Nsg9 +I00 +sbS'Mol2013 - Immune Signal Transduction in Leishmaniasis' +p2360 +sg1 +(g2 +g3 +VBIOMD0000000476 +p2361 +tp2362 +Rp2363 +(dp2364 +g8 +Nsg9 +I00 +sbS'Adams2012 - Locke2006 Circadian Rhythm model refined with Input Signal Light Function' +p2365 +sg1 +(g2 +g3 +VBIOMD0000000475 +p2366 +tp2367 +Rp2368 +(dp2369 +g8 +Nsg9 +I00 +sbS'Amara2013 - PCNA ubiquitylation in the activation of PRR pathway' +p2370 +sg1 +(g2 +g3 +VBIOMD0000000474 +p2371 +tp2372 +Rp2373 +(dp2374 +g8 +Nsg9 +I00 +sbS'Smith2013 - Regulation of Insulin Signalling by Oxidative Stress' +p2375 +sg1 +(g2 +g3 +VBIOMD0000000558 +p2376 +tp2377 +Rp2378 +(dp2379 +g8 +Nsg9 +I00 +sbS"Cloutier2012 - Feedback motif for Parkinson's disease" +p2380 +sg1 +(g2 +g3 +VBIOMD0000000479 +p2381 +tp2382 +Rp2383 +(dp2384 +g8 +Nsg9 +I00 +sbS'Croft2013 - GPCR-RGS interaction that compartmentalizes RGS activity' +p2385 +sg1 +(g2 +g3 +VBIOMD0000000311 +p2386 +tp2387 +Rp2388 +(dp2389 +g8 +Nsg9 +I00 +sbS'Tyson2003_Mutual_Activation' +p2390 +sg1 +(g2 +g3 +VBIOMD0000000526 +p2391 +tp2392 +Rp2393 +(dp2394 +g8 +Nsg9 +I00 +sbS'Kallenberger2014 - CD95L induced apoptosis initiated by caspase-8, wild-type HeLa cells (cis/trans-cis/trans variant)' +p2395 +sg1 +(g2 +g3 +VBIOMD0000000488 +p2396 +tp2397 +Rp2398 +(dp2399 +g8 +Nsg9 +I00 +sbS"Proctor2013 - Effect of A\xce\xb2 immunisation in Alzheimer's disease" +p2400 +sg1 +(g2 +g3 +VBIOMD0000000489 +p2401 +tp2402 +Rp2403 +(dp2404 +g8 +Nsg9 +I00 +sbS'Sharp2013 - Lipopolysaccharide induced NFkB activation' +p2405 +sg1 +(g2 +g3 +VBIOMD0000000486 +p2406 +tp2407 +Rp2408 +(dp2409 +g8 +Nsg9 +I00 +sbS'Cao2013 - Application of ABSIS method in the reversible isomerization model' +p2410 +sg1 +(g2 +g3 +VBIOMD0000000487 +p2411 +tp2412 +Rp2413 +(dp2414 +g8 +Nsg9 +I00 +sbS'Cao2013 - Application of ABSIS in the the enzymatic futile cycle' +p2415 +sg1 +(g2 +g3 +VBIOMD0000000484 +p2416 +tp2417 +Rp2418 +(dp2419 +g8 +Nsg9 +I00 +sbS'Cao2013 - Application of ABSIS method in birth-death process' +p2420 +sg1 +(g2 +g3 +VBIOMD0000000485 +p2421 +tp2422 +Rp2423 +(dp2424 +g8 +Nsg9 +I00 +sbS'Cao2013 - Application of ABSIS method in the bistable Schl\xc3\xb6gl model' +p2425 +sg1 +(g2 +g3 +VBIOMD0000000482 +p2426 +tp2427 +Rp2428 +(dp2429 +g8 +Nsg9 +I00 +sbS'Noguchi2013 - Insulin dependent glucose metabolism' +p2430 +sg1 +(g2 +g3 +VBIOMD0000000483 +p2431 +tp2432 +Rp2433 +(dp2434 +g8 +Nsg9 +I00 +sbS'Cao2008 - Network of a toggle switch' +p2435 +sg1 +(g2 +g3 +VBIOMD0000000480 +p2436 +tp2437 +Rp2438 +(dp2439 +g8 +Nsg9 +I00 +sbS'Carbo2013 - Mucosal Immune Response during H.pylori Infection' +p2440 +sg1 +(g2 +g3 +VBIOMD0000000481 +p2441 +tp2442 +Rp2443 +(dp2444 +g8 +Nsg9 +I00 +sbS'St\xc3\xb6tzel2012 - Bovine estrous cycle, synchronization with prostaglandin F2\xce\xb1' +p2445 +sg1 +(g2 +g3 +VBIOMD0000000279 +p2446 +tp2447 +Rp2448 +(dp2449 +g8 +Nsg9 +I00 +sbS'Komarova2005_PTHaction_OsteoclastOsteoblastCoupling' +p2450 +sg1 +(g2 +g3 +VBIOMD0000000278 +p2451 +tp2452 +Rp2453 +(dp2454 +g8 +Nsg9 +I00 +sbS'Lemaire2004_BoneRemodeling_RANKRANKLOPGpathway' +p2455 +sg1 +(g2 +g3 +VBIOMD0000000372 +p2456 +tp2457 +Rp2458 +(dp2459 +g8 +Nsg9 +I00 +sbS'Tolic2000_InsulinGlucoseFeedback' +p2460 +sg1 +(g2 +g3 +VBIOMD0000000373 +p2461 +tp2462 +Rp2463 +(dp2464 +g8 +Nsg9 +I00 +sbS'Bertram2004_PancreaticBetaCell_modelB' +p2465 +sg1 +(g2 +g3 +VBIOMD0000000374 +p2466 +tp2467 +Rp2468 +(dp2469 +g8 +Nsg9 +I00 +sbS'Bertram1995_PancreaticBetaCell_CRAC' +p2470 +sg1 +(g2 +g3 +VBIOMD0000000251 +p2471 +tp2472 +Rp2473 +(dp2474 +g8 +Nsg9 +I00 +sbS'Nakakuki2010_CellFateDecision_Core' +p2475 +sg1 +(g2 +g3 +VBIOMD0000000376 +p2476 +tp2477 +Rp2478 +(dp2479 +g8 +Nsg9 +I00 +sbS'Bertram2007_IsletCell_Oscillations' +p2480 +sg1 +(g2 +g3 +VBIOMD0000000377 +p2481 +tp2482 +Rp2483 +(dp2484 +g8 +Nsg9 +I00 +sbS'Bertram2000_PancreaticBetaCells_Oscillations' +p2485 +sg1 +(g2 +g3 +VBIOMD0000000378 +p2486 +tp2487 +Rp2488 +(dp2489 +g8 +Nsg9 +I00 +sbS'Chay1997_CalciumConcentration' +p2490 +sg1 +(g2 +g3 +VBIOMD0000000379 +p2491 +tp2492 +Rp2493 +(dp2494 +g8 +Nsg9 +I00 +sbS'DallaMan2007_MealModel_GlucoseInsulinSystem' +p2495 +sg1 +(g2 +g3 +VBIOMD0000000273 +p2496 +tp2497 +Rp2498 +(dp2499 +g8 +Nsg9 +I00 +sbS'Pokhilko2010_CircClock' +p2500 +sg1 +(g2 +g3 +VBIOMD0000000272 +p2501 +tp2502 +Rp2503 +(dp2504 +g8 +Nsg9 +I00 +sbS'Becker2010_EpoR_AuxiliaryModel' +p2505 +sg1 +(g2 +g3 +VBIOMD0000000275 +p2506 +tp2507 +Rp2508 +(dp2509 +g8 +Nsg9 +I00 +sbS'Goldbeter2007_Somitogenesis_Switch' +p2510 +sg1 +(g2 +g3 +VBIOMD0000000274 +p2511 +tp2512 +Rp2513 +(dp2514 +g8 +Nsg9 +I00 +sbS'Rattanakul2003_BoneFormationModel' +p2515 +sg1 +(g2 +g3 +VBIOMD0000000277 +p2516 +tp2517 +Rp2518 +(dp2519 +g8 +Nsg9 +I00 +sbS'Shrestha2010_HyperCalcemia_PTHresponse' +p2520 +sg1 +(g2 +g3 +VBIOMD0000000276 +p2521 +tp2522 +Rp2523 +(dp2524 +g8 +Nsg9 +I00 +sbS'Shrestha2010_HypoCalcemia_PTHresponse' +p2525 +sg1 +(g2 +g3 +VBIOMD0000000509 +p2526 +tp2527 +Rp2528 +(dp2529 +g8 +Nsg9 +I00 +sbS'Barrack2014 - Calcium/cell cycle coupling - Rs dependent ATP release' +p2530 +sg1 +(g2 +g3 +VBIOMD0000000508 +p2531 +tp2532 +Rp2533 +(dp2534 +g8 +Nsg9 +I00 +sbS'Barrack2014 - Calcium/cell cycle coupling - Cyclin D dependent ATP release' +p2535 +sg1 +(g2 +g3 +VBIOMD0000000507 +p2536 +tp2537 +Rp2538 +(dp2539 +g8 +Nsg9 +I00 +sbS'Gardner2000 - genetic toggle switch in E.coli' +p2540 +sg1 +(g2 +g3 +VBIOMD0000000506 +p2541 +tp2542 +Rp2543 +(dp2544 +g8 +Nsg9 +I00 +sbS'vanEunen2013 - Network dynamics of fatty acid ?-oxidation (time-course model)' +p2545 +sg1 +(g2 +g3 +VBIOMD0000000505 +p2546 +tp2547 +Rp2548 +(dp2549 +g8 +Nsg9 +I00 +sbS'vanEunen2013 - Network dynamics of fatty acid ?-oxidation (steady-state model)' +p2550 +sg1 +(g2 +g3 +VBIOMD0000000504 +p2551 +tp2552 +Rp2553 +(dp2554 +g8 +Nsg9 +I00 +sbS'Proctor2013 - Cartilage breakdown, interventions to reduce collagen release' +p2555 +sg1 +(g2 +g3 +VBIOMD0000000503 +p2556 +tp2557 +Rp2558 +(dp2559 +g8 +Nsg9 +I00 +sbS'Messiha2013 - combined glycolysis and pentose phosphate pathway model' +p2560 +sg1 +(g2 +g3 +VBIOMD0000000502 +p2561 +tp2562 +Rp2563 +(dp2564 +g8 +Nsg9 +I00 +sbS'Messiha2013 - Pentose phosphate pathway model' +p2565 +sg1 +(g2 +g3 +VBIOMD0000000501 +p2566 +tp2567 +Rp2568 +(dp2569 +g8 +Nsg9 +I00 +sbS'Begitt2014 - STAT1 cooperative DNA binding - double GAS polymer model' +p2570 +sg1 +(g2 +g3 +VBIOMD0000000500 +p2571 +tp2572 +Rp2573 +(dp2574 +g8 +Nsg9 +I00 +sbS'Begitt2014 - STAT1 cooperative DNA binding - single GAS polymer model' +p2575 +sg1 +(g2 +g3 +VBIOMD0000000099 +p2576 +tp2577 +Rp2578 +(dp2579 +g8 +Nsg9 +I00 +sbS'Laub1998_SpontaneousOscillations' +p2580 +sg1 +(g2 +g3 +VBIOMD0000000323 +p2581 +tp2582 +Rp2583 +(dp2584 +g8 +Nsg9 +I00 +sbS'Kim2011_Oscillator_SimpleIII' +p2585 +sg1 +(g2 +g3 +VBIOMD0000000310 +p2586 +tp2587 +Rp2588 +(dp2589 +g8 +Nsg9 +I00 +sbS'Tyson2003_Mutual_Inhibition' +p2590 +sg1 +(g2 +g3 +VBIOMD0000000322 +p2591 +tp2592 +Rp2593 +(dp2594 +g8 +Nsg9 +I00 +sbS'Kim2011_Oscillator_SimpleI' +p2595 +sg1 +(g2 +g3 +VBIOMD0000000031 +p2596 +tp2597 +Rp2598 +(dp2599 +g8 +Nsg9 +I00 +sbS'Markevich2004_MAPK_orderedMM2kinases' +p2600 +sg1 +(g2 +g3 +VBIOMD0000000030 +p2601 +tp2602 +Rp2603 +(dp2604 +g8 +Nsg9 +I00 +sbS'Markevich2004_MAPK_AllRandomElementary' +p2605 +sg1 +(g2 +g3 +VBIOMD0000000288 +p2606 +tp2607 +Rp2608 +(dp2609 +g8 +Nsg9 +I00 +sbS'Wang2009 - PI3K Ras Crosstalk' +p2610 +sg1 +(g2 +g3 +VBIOMD0000000289 +p2611 +tp2612 +Rp2613 +(dp2614 +g8 +Nsg9 +I00 +sbS'Alexander2010_Tcell_Regulation_Sys1' +p2615 +sg1 +(g2 +g3 +VBIOMD0000000280 +p2616 +tp2617 +Rp2618 +(dp2619 +g8 +Nsg9 +I00 +sbS'Morris1981_MuscleFibre_Voltage_reduced' +p2620 +sg1 +(g2 +g3 +VBIOMD0000000281 +p2621 +tp2622 +Rp2623 +(dp2624 +g8 +Nsg9 +I00 +sbS'Chance1960_Glycolysis_Respiration' +p2625 +sg1 +(g2 +g3 +VBIOMD0000000282 +p2626 +tp2627 +Rp2628 +(dp2629 +g8 +Nsg9 +I00 +sbS'Chance1952_Catalase_Mechanism' +p2630 +sg1 +(g2 +g3 +VBIOMD0000000283 +p2631 +tp2632 +Rp2633 +(dp2634 +g8 +Nsg9 +I00 +sbS'Chance1943_Peroxidase_ES_Kinetics' +p2635 +sg1 +(g2 +g3 +VBIOMD0000000284 +p2636 +tp2637 +Rp2638 +(dp2639 +g8 +Nsg9 +I00 +sbS'Hofmeyer1986_SeqFb_Proc_AA_Synthesis' +p2640 +sg1 +(g2 +g3 +VBIOMD0000000285 +p2641 +tp2642 +Rp2643 +(dp2644 +g8 +Nsg9 +I00 +sbS'Tang2010_PolyGlutamate' +p2645 +sg1 +(g2 +g3 +VBIOMD0000000286 +p2646 +tp2647 +Rp2648 +(dp2649 +g8 +Nsg9 +I00 +sbS'Proctor2010_GSK3_p53_AlzheimerDisease' +p2650 +sg1 +(g2 +g3 +VBIOMD0000000287 +p2651 +tp2652 +Rp2653 +(dp2654 +g8 +Nsg9 +I00 +sbS'Passos2010_DNAdamage_CellularSenescence' +p2655 +sg1 +(g2 +g3 +VBIOMD0000000118 +p2656 +tp2657 +Rp2658 +(dp2659 +g8 +Nsg9 +I00 +sbS'Golomb2006_SomaticBursting' +p2660 +sg1 +(g2 +g3 +VBIOMD0000000119 +p2661 +tp2662 +Rp2663 +(dp2664 +g8 +Nsg9 +I00 +sbS'Golomb2006_SomaticBursting_nonzero[Ca]' +p2665 +sg1 +(g2 +g3 +VBIOMD0000000110 +p2666 +tp2667 +Rp2668 +(dp2669 +g8 +Nsg9 +I00 +sbS'Qu2003_CellCycle' +p2670 +sg1 +(g2 +g3 +VBIOMD0000000111 +p2671 +tp2672 +Rp2673 +(dp2674 +g8 +Nsg9 +I00 +sbS'Novak2001_FissionYeast_CellCycle' +p2675 +sg1 +(g2 +g3 +VBIOMD0000000112 +p2676 +tp2677 +Rp2678 +(dp2679 +g8 +Nsg9 +I00 +sbS'Clarke2006_Smad_signalling' +p2680 +sg1 +(g2 +g3 +VBIOMD0000000113 +p2681 +tp2682 +Rp2683 +(dp2684 +g8 +Nsg9 +I00 +sbS'Dupont1992_Ca_dpt_protein_phospho' +p2685 +sg1 +(g2 +g3 +VBIOMD0000000114 +p2686 +tp2687 +Rp2688 +(dp2689 +g8 +Nsg9 +I00 +sbS'Somogyi1990_CaOscillations' +p2690 +sg1 +(g2 +g3 +VBIOMD0000000115 +p2691 +tp2692 +Rp2693 +(dp2694 +g8 +Nsg9 +I00 +sbS'Somogyi1990_CaOscillations_SingleCaSpike' +p2695 +sg1 +(g2 +g3 +VBIOMD0000000116 +p2696 +tp2697 +Rp2698 +(dp2699 +g8 +Nsg9 +I00 +sbS'McClean2007_CrossTalk' +p2700 +sg1 +(g2 +g3 +VBIOMD0000000117 +p2701 +tp2702 +Rp2703 +(dp2704 +g8 +Nsg9 +I00 +sbS'Dupont1991_CaOscillation' +p2705 +sg1 +(g2 +g3 +VBIOMD0000000051 +p2706 +tp2707 +Rp2708 +(dp2709 +g8 +Nsg9 +I00 +sbS'Chassagnole2002_Carbon_Metabolism' +p2710 +sg1 +(g2 +g3 +VBIOMD0000000050 +p2711 +tp2712 +Rp2713 +(dp2714 +g8 +Nsg9 +I00 +sbS'Martins2003_AmadoriDegradation' +p2715 +sg1 +(g2 +g3 +VBIOMD0000000053 +p2716 +tp2717 +Rp2718 +(dp2719 +g8 +Nsg9 +I00 +sbS'Ferreira2003_CML_generation2' +p2720 +sg1 +(g2 +g3 +VBIOMD0000000052 +p2721 +tp2722 +Rp2723 +(dp2724 +g8 +Nsg9 +I00 +sbS'Brands2002 - Monosaccharide-casein systems' +p2725 +sg1 +(g2 +g3 +VBIOMD0000000055 +p2726 +tp2727 +Rp2728 +(dp2729 +g8 +Nsg9 +I00 +sbS'Locke2005 - Circadian Clock' +p2730 +sg1 +(g2 +g3 +VBIOMD0000000054 +p2731 +tp2732 +Rp2733 +(dp2734 +g8 +Nsg9 +I00 +sbS'Ataullahkhanov1996_Adenylate' +p2735 +sg1 +(g2 +g3 +VBIOMD0000000057 +p2736 +tp2737 +Rp2738 +(dp2739 +g8 +Nsg9 +I00 +sbS'Sneyd2002_IP3_Receptor' +p2740 +sg1 +(g2 +g3 +VBIOMD0000000056 +p2741 +tp2742 +Rp2743 +(dp2744 +g8 +Nsg9 +I00 +sbS'Chen2004 - Cell Cycle Regulation' +p2745 +sg1 +(g2 +g3 +VBIOMD0000000059 +p2746 +tp2747 +Rp2748 +(dp2749 +g8 +Nsg9 +I00 +sbS'Fridlyand2003_Calcium_flux' +p2750 +sg1 +(g2 +g3 +VBIOMD0000000058 +p2751 +tp2752 +Rp2753 +(dp2754 +g8 +Nsg9 +I00 +sbS'Bindschadler2001_coupled_Ca_oscillators' +p2755 +sg1 +(g2 +g3 +VBIOMD0000000246 +p2756 +tp2757 +Rp2758 +(dp2759 +g8 +Nsg9 +I00 +sbS'Vasalou2010_Pacemaker_Neuron_SCN' +p2760 +sg1 +(g2 +g3 +VBIOMD0000000239 +p2761 +tp2762 +Rp2763 +(dp2764 +g8 +Nsg9 +I00 +sbS'Jiang2007 - GSIS system, Pancreatic Beta Cells' +p2765 +sg1 +(g2 +g3 +VBIOMD0000000238 +p2766 +tp2767 +Rp2768 +(dp2769 +g8 +Nsg9 +I00 +sbS'Overgaard2007_PDmodel_IL21' +p2770 +sg1 +(g2 +g3 +VBIOMD0000000235 +p2771 +tp2772 +Rp2773 +(dp2774 +g8 +Nsg9 +I00 +sbS'Kuhn2009_EndoMesodermNetwork' +p2775 +sg1 +(g2 +g3 +VBIOMD0000000234 +p2776 +tp2777 +Rp2778 +(dp2779 +g8 +Nsg9 +I00 +sbS'Tham2008_PDmodel_TumourShrinkage' +p2780 +sg1 +(g2 +g3 +VBIOMD0000000237 +p2781 +tp2782 +Rp2783 +(dp2784 +g8 +Nsg9 +I00 +sbS'Schaber2006_Pheromone_Starvation_Crosstalk' +p2785 +sg1 +(g2 +g3 +VBIOMD0000000236 +p2786 +tp2787 +Rp2788 +(dp2789 +g8 +Nsg9 +I00 +sbS'Westermark2003_Pancreatic_GlycOsc_extended' +p2790 +sg1 +(g2 +g3 +VBIOMD0000000231 +p2791 +tp2792 +Rp2793 +(dp2794 +g8 +Nsg9 +I00 +sbS'Valero2006_Adenine_TernaryCycle' +p2795 +sg1 +(g2 +g3 +VBIOMD0000000230 +p2796 +tp2797 +Rp2798 +(dp2799 +g8 +Nsg9 +I00 +sbS'Ihekwaba2004_NFkB_Sensitivity' +p2800 +sg1 +(g2 +g3 +VBIOMD0000000233 +p2801 +tp2802 +Rp2803 +(dp2804 +g8 +Nsg9 +I00 +sbS'Wilhelm2009_BistableReaction' +p2805 +sg1 +(g2 +g3 +VBIOMD0000000232 +p2806 +tp2807 +Rp2808 +(dp2809 +g8 +Nsg9 +I00 +sbS'Nazaret2009_TCA_RC_ATP' +p2810 +s. \ No newline at end of file diff --git a/moose-gui/bioModels/getModelsIdByChEBI.pkl b/moose-gui/bioModels/getModelsIdByChEBI.pkl new file mode 100644 index 0000000000000000000000000000000000000000..b0cd9b24f3003fb4e903175220cbf56224f8e4db --- /dev/null +++ b/moose-gui/bioModels/getModelsIdByChEBI.pkl @@ -0,0 +1,3663 @@ +(dp0 +ccopy_reg +_reconstructor +p1 +(csuds.sax.text +Text +p2 +c__builtin__ +unicode +p3 +VBIOMD0000000460 +p4 +tp5 +Rp6 +(dp7 +S'lang' +p8 +NsS'escaped' +p9 +I00 +sbS'Liebal2012 - B.subtilis sigB proteolysis model' +p10 +sg1 +(g2 +g3 +VBIOMD0000000428 +p11 +tp12 +Rp13 +(dp14 +g8 +Nsg9 +I00 +sbS'Achcar2012 - Glycolysis in bloodstream form T. brucei' +p15 +sg1 +(g2 +g3 +VBIOMD0000000429 +p16 +tp17 +Rp18 +(dp19 +g8 +Nsg9 +I00 +sbS'Schaber2012 - Hog pathway in yeast' +p20 +sg1 +(g2 +g3 +VBIOMD0000000049 +p21 +tp22 +Rp23 +(dp24 +g8 +Nsg9 +I00 +sbS'Sasagawa2005_MAPK' +p25 +sg1 +(g2 +g3 +VBIOMD0000000182 +p26 +tp27 +Rp28 +(dp29 +g8 +Nsg9 +I00 +sbS'Neves2008 - Role of cell shape and size in controlling intracellular signalling' +p30 +sg1 +(g2 +g3 +VBIOMD0000000424 +p31 +tp32 +Rp33 +(dp34 +g8 +Nsg9 +I00 +sbS'Faratian2009_PTENrole_TrastuzumabResistance' +p35 +sg1 +(g2 +g3 +VBIOMD0000000327 +p36 +tp37 +Rp38 +(dp39 +g8 +Nsg9 +I00 +sbS'Whitcomb2004_Bicarbonate_Pancreas' +p40 +sg1 +(g2 +g3 +VBIOMD0000000426 +p41 +tp42 +Rp43 +(dp44 +g8 +Nsg9 +I00 +sbS'Mosca2012 - Central Carbon Metabolism Regulated by AKT' +p45 +sg1 +(g2 +g3 +VBIOMD0000000422 +p46 +tp47 +Rp48 +(dp49 +g8 +Nsg9 +I00 +sbS'Middleton2012_GibberellinSignalling' +p50 +sg1 +(g2 +g3 +VBIOMD0000000117 +p51 +tp52 +Rp53 +(dp54 +g8 +Nsg9 +I00 +sbS'Dupont1991_CaOscillation' +p55 +sg1 +(g2 +g3 +VBIOMD0000000380 +p56 +tp57 +Rp58 +(dp59 +g8 +Nsg9 +I00 +sbS'Smallbone2011_TrehaloseBiosynthesis' +p60 +sg1 +(g2 +g3 +VBIOMD0000000039 +p61 +tp62 +Rp63 +(dp64 +g8 +Nsg9 +I00 +sbS'Marhl2000_CaOscillations' +p65 +sg1 +(g2 +g3 +VBIOMD0000000229 +p66 +tp67 +Rp68 +(dp69 +g8 +Nsg9 +I00 +sbS'Ma2002_cAMP_oscillations' +p70 +sg1 +(g2 +g3 +VBIOMD0000000385 +p71 +tp72 +Rp73 +(dp74 +g8 +Nsg9 +I00 +sbS'Arnold2011_Schultz2003_RuBisCO-CalvinCycle' +p75 +sg1 +(g2 +g3 +VBIOMD0000000137 +p76 +tp77 +Rp78 +(dp79 +g8 +Nsg9 +I00 +sbS'Sedaghat2002_InsulinSignalling_noFeedback' +p80 +sg1 +(g2 +g3 +VBIOMD0000000387 +p81 +tp82 +Rp83 +(dp84 +g8 +Nsg9 +I00 +sbS'Arnold2011_Damour2007_RuBisCO-CalvinCycle' +p85 +sg1 +(g2 +g3 +VBIOMD0000000386 +p86 +tp87 +Rp88 +(dp89 +g8 +Nsg9 +I00 +sbS'Arnold2011_Sharkey2007_RuBisCO-CalvinCycle' +p90 +sg1 +(g2 +g3 +VBIOMD0000000222 +p91 +tp92 +Rp93 +(dp94 +g8 +Nsg9 +I00 +sbS'Singh2006_TCA_Ecoli_glucose' +p95 +sg1 +(g2 +g3 +VBIOMD0000000388 +p96 +tp97 +Rp98 +(dp99 +g8 +Nsg9 +I00 +sbS'Arnold2011_Zhu2009_CalvinCycle' +p100 +sg1 +(g2 +g3 +VBIOMD0000000138 +p101 +tp102 +Rp103 +(dp104 +g8 +Nsg9 +I00 +sbS'Tabak2007_dopamine' +p105 +sg1 +(g2 +g3 +VBIOMD0000000221 +p106 +tp107 +Rp108 +(dp109 +g8 +Nsg9 +I00 +sbS'Singh2006_TCA_Ecoli_acetate' +p110 +sg1 +(g2 +g3 +VBIOMD0000000037 +p111 +tp112 +Rp113 +(dp114 +g8 +Nsg9 +I00 +sbS'Marwan_Genetics_2003' +p115 +sg1 +(g2 +g3 +VBIOMD0000000202 +p116 +tp117 +Rp118 +(dp119 +g8 +Nsg9 +I00 +sbS'ChenXF2008_CICR' +p120 +sg1 +(g2 +g3 +VBIOMD0000000224 +p121 +tp122 +Rp123 +(dp124 +g8 +Nsg9 +I00 +sbS'Meyer1991_CalciumSpike_ICC' +p125 +sg1 +(g2 +g3 +VBIOMD0000000225 +p126 +tp127 +Rp128 +(dp129 +g8 +Nsg9 +I00 +sbS'Westermark2003_Pancreatic_GlycOsc_basic' +p130 +sg1 +(g2 +g3 +VBIOMD0000000309 +p131 +tp132 +Rp133 +(dp134 +g8 +Nsg9 +I00 +sbS'Tyson2003_NegFB_Homeostasis' +p135 +sg1 +(g2 +g3 +VBIOMD0000000308 +p136 +tp137 +Rp138 +(dp139 +g8 +Nsg9 +I00 +sbS'Tyson2003_NegFB_Oscillator' +p140 +sg1 +(g2 +g3 +VBIOMD0000000344 +p141 +tp142 +Rp143 +(dp144 +g8 +Nsg9 +I00 +sbS'Proctor2011_ProteinHomeostasis_NormalCondition' +p145 +sg1 +(g2 +g3 +VBIOMD0000000301 +p146 +tp147 +Rp148 +(dp149 +g8 +Nsg9 +I00 +sbS'Friedland2009_Ara_RTC3_counter' +p150 +sg1 +(g2 +g3 +VBIOMD0000000300 +p151 +tp152 +Rp153 +(dp154 +g8 +Nsg9 +I00 +sbS'Schmierer2010_FIH_Ankyrins' +p155 +sg1 +(g2 +g3 +VBIOMD0000000303 +p156 +tp157 +Rp158 +(dp159 +g8 +Nsg9 +I00 +sbS'Liu2011_Complement_System' +p160 +sg1 +(g2 +g3 +VBIOMD0000000100 +p161 +tp162 +Rp163 +(dp164 +g8 +Nsg9 +I00 +sbS'Rozi2003_GlycogenPhosphorylase_Activation' +p165 +sg1 +(g2 +g3 +VBIOMD0000000305 +p166 +tp167 +Rp168 +(dp169 +g8 +Nsg9 +I00 +sbS'Kolomeisky2003_MyosinV_Processivity' +p170 +sg1 +(g2 +g3 +VBIOMD0000000304 +p171 +tp172 +Rp173 +(dp174 +g8 +Nsg9 +I00 +sbS'Plant1981_BurstingNerveCells' +p175 +sg1 +(g2 +g3 +VBIOMD0000000307 +p176 +tp177 +Rp178 +(dp179 +g8 +Nsg9 +I00 +sbS'Tyson2003_Substrate_Depletion_Osc' +p180 +sg1 +(g2 +g3 +VBIOMD0000000306 +p181 +tp182 +Rp183 +(dp184 +g8 +Nsg9 +I00 +sbS'Tyson2003_Activator_Inhibitor' +p185 +sg1 +(g2 +g3 +VBIOMD0000000459 +p186 +tp187 +Rp188 +(dp189 +g8 +Nsg9 +I00 +sbS'Liebal2012 - B.subtilis post-transcriptional instability model' +p190 +sg1 +(g2 +g3 +VBIOMD0000000164 +p191 +tp192 +Rp193 +(dp194 +g8 +Nsg9 +I00 +sbS'SmithAE2002_RanTransport' +p195 +sg1 +(g2 +g3 +VBIOMD0000000329 +p196 +tp197 +Rp198 +(dp199 +g8 +Nsg9 +I00 +sbS'Kummer2000_CalciumSpiking' +p200 +sg1 +(g2 +g3 +VBIOMD0000000410 +p201 +tp202 +Rp203 +(dp204 +g8 +Nsg9 +I00 +sbS'Wegner2012_TGFbetaSignalling_FeedbackLoops' +p205 +sg1 +(g2 +g3 +VBIOMD0000000412 +p206 +tp207 +Rp208 +(dp209 +g8 +Nsg9 +I00 +sbS'Pokhilko2012_CircClock_RepressilatorFeedbackloop' +p210 +sg1 +(g2 +g3 +VBIOMD0000000415 +p211 +tp212 +Rp213 +(dp214 +g8 +Nsg9 +I00 +sbS'Mellor2012_LipooxygenasePathway' +p215 +sg1 +(g2 +g3 +VBIOMD0000000416 +p216 +tp217 +Rp218 +(dp219 +g8 +Nsg9 +I00 +sbS'Muraro2011_Cytokinin-Auxin_CrossRegulation' +p220 +sg1 +(g2 +g3 +VBIOMD0000000244 +p221 +tp222 +Rp223 +(dp224 +g8 +Nsg9 +I00 +sbS'Kotte2010_Ecoli_Metabolic_Adaption' +p225 +sg1 +(g2 +g3 +VBIOMD0000000398 +p226 +tp227 +Rp228 +(dp229 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_NeuralStemCellDifferentiation_Crosstalk' +p230 +sg1 +(g2 +g3 +VBIOMD0000000399 +p231 +tp232 +Rp233 +(dp234 +g8 +Nsg9 +I00 +sbS'Jenkinson2011_EGF_MAPK' +p235 +sg1 +(g2 +g3 +VBIOMD0000000396 +p236 +tp237 +Rp238 +(dp239 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_NotchSignalingPathway' +p240 +sg1 +(g2 +g3 +VBIOMD0000000397 +p241 +tp242 +Rp243 +(dp244 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_WntSignalingPathway' +p245 +sg1 +(g2 +g3 +VBIOMD0000000394 +p246 +tp247 +Rp248 +(dp249 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_EGFReceptorSignalingPathway' +p250 +sg1 +(g2 +g3 +VBIOMD0000000395 +p251 +tp252 +Rp253 +(dp254 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_HedgehogSignalingPathway' +p255 +sg1 +(g2 +g3 +VBIOMD0000000392 +p256 +tp257 +Rp258 +(dp259 +g8 +Nsg9 +I00 +sbS'Arnold2011_Laisk2006_CalvinCycle_Starch_Sucrose' +p260 +sg1 +(g2 +g3 +VBIOMD0000000393 +p261 +tp262 +Rp263 +(dp264 +g8 +Nsg9 +I00 +sbS'Arnold2011_Zhu2007_CalvinCycle_Starch_Sucrose_Photorespiration' +p265 +sg1 +(g2 +g3 +VBIOMD0000000390 +p266 +tp267 +Rp268 +(dp269 +g8 +Nsg9 +I00 +sbS'Arnold2011_Giersch1990_CalvinCycle' +p270 +sg1 +(g2 +g3 +VBIOMD0000000391 +p271 +tp272 +Rp273 +(dp274 +g8 +Nsg9 +I00 +sbS'Arnold2011_Poolman2000_CalvinCycle_Starch' +p275 +sg1 +(g2 +g3 +VBIOMD0000000096 +p276 +tp277 +Rp278 +(dp279 +g8 +Nsg9 +I00 +sbS'Zeilinger2006_PRR7-PRR9light-Y' +p280 +sg1 +(g2 +g3 +VBIOMD0000000021 +p281 +tp282 +Rp283 +(dp284 +g8 +Nsg9 +I00 +sbS'Leloup1999_CircClock' +p285 +sg1 +(g2 +g3 +VBIOMD0000000022 +p286 +tp287 +Rp288 +(dp289 +g8 +Nsg9 +I00 +sbS'Ueda2001_CircClock' +p290 +sg1 +(g2 +g3 +VBIOMD0000000023 +p291 +tp292 +Rp293 +(dp294 +g8 +Nsg9 +I00 +sbS'Rohwer2001_Sucrose' +p295 +sg1 +(g2 +g3 +VBIOMD0000000024 +p296 +tp297 +Rp298 +(dp299 +g8 +Nsg9 +I00 +sbS'Scheper1999_CircClock' +p300 +sg1 +(g2 +g3 +VBIOMD0000000090 +p301 +tp302 +Rp303 +(dp304 +g8 +Nsg9 +I00 +sbS'Wolf2001_Respiratory_Oscillations' +p305 +sg1 +(g2 +g3 +VBIOMD0000000316 +p306 +tp307 +Rp308 +(dp309 +g8 +Nsg9 +I00 +sbS'Shen-Orr2002_FeedForward_AND_gate' +p310 +sg1 +(g2 +g3 +VBIOMD0000000317 +p311 +tp312 +Rp313 +(dp314 +g8 +Nsg9 +I00 +sbS'Shen-Orr2002_Single_Input_Module' +p315 +sg1 +(g2 +g3 +VBIOMD0000000314 +p316 +tp317 +Rp318 +(dp319 +g8 +Nsg9 +I00 +sbS'Raia2011_IL13_L1236' +p320 +sg1 +(g2 +g3 +VBIOMD0000000315 +p321 +tp322 +Rp323 +(dp324 +g8 +Nsg9 +I00 +sbS'Montagne2011_Oligator_optimised' +p325 +sg1 +(g2 +g3 +VBIOMD0000000312 +p326 +tp327 +Rp328 +(dp329 +g8 +Nsg9 +I00 +sbS'Tyson2003_Perfect_Adaption' +p330 +sg1 +(g2 +g3 +VBIOMD0000000313 +p331 +tp332 +Rp333 +(dp334 +g8 +Nsg9 +I00 +sbS'Raia2010_IL13_Signalling_MedB1' +p335 +sg1 +(g2 +g3 +VBIOMD0000000310 +p336 +tp337 +Rp338 +(dp339 +g8 +Nsg9 +I00 +sbS'Tyson2003_Mutual_Inhibition' +p340 +sg1 +(g2 +g3 +VBIOMD0000000311 +p341 +tp342 +Rp343 +(dp344 +g8 +Nsg9 +I00 +sbS'Tyson2003_Mutual_Activation' +p345 +sg1 +(g2 +g3 +VBIOMD0000000255 +p346 +tp347 +Rp348 +(dp349 +g8 +Nsg9 +I00 +sbS'Chen2009_ErbB_Signaling' +p350 +sg1 +(g2 +g3 +VBIOMD0000000254 +p351 +tp352 +Rp353 +(dp354 +g8 +Nsg9 +I00 +sbS'Bier2000_GlycolyticOscillation' +p355 +sg1 +(g2 +g3 +VBIOMD0000000253 +p356 +tp357 +Rp358 +(dp359 +g8 +Nsg9 +I00 +sbS'Teusink1998_Glycolysis_TurboDesign' +p360 +sg1 +(g2 +g3 +VBIOMD0000000252 +p361 +tp362 +Rp363 +(dp364 +g8 +Nsg9 +I00 +sbS'Hunziker2010_p53_StressSpecificResponse' +p365 +sg1 +(g2 +g3 +VBIOMD0000000406 +p366 +tp367 +Rp368 +(dp369 +g8 +Nsg9 +I00 +sbS'Moriya2011_CellCycle_FissionYeast' +p370 +sg1 +(g2 +g3 +VBIOMD0000000404 +p371 +tp372 +Rp373 +(dp374 +g8 +Nsg9 +I00 +sbS'Bray1993_chemotaxis' +p375 +sg1 +(g2 +g3 +VBIOMD0000000405 +p376 +tp377 +Rp378 +(dp379 +g8 +Nsg9 +I00 +sbS'Cookson2011_EnzymaticQueueingCoupling' +p380 +sg1 +(g2 +g3 +VBIOMD0000000400 +p381 +tp382 +Rp383 +(dp384 +g8 +Nsg9 +I00 +sbS'Cooling2007_IP3transients_CardiacMyocyte' +p385 +sg1 +(g2 +g3 +VBIOMD0000000408 +p386 +tp387 +Rp388 +(dp389 +g8 +Nsg9 +I00 +sbS'Hettling2011_CreatineKinase' +p390 +sg1 +(g2 +g3 +VBIOMD0000000409 +p391 +tp392 +Rp393 +(dp394 +g8 +Nsg9 +I00 +sbS'Queralt2006_MitoticExit_Cdc55DownregulationBySeparase' +p395 +sg1 +(g2 +g3 +VBIOMD0000000105 +p396 +tp397 +Rp398 +(dp399 +g8 +Nsg9 +I00 +sbS'Proctor2007_ubiquitine' +p400 +sg1 +(g2 +g3 +VBIOMD0000000015 +p401 +tp402 +Rp403 +(dp404 +g8 +Nsg9 +I00 +sbS'Curto1998_purineMetabol' +p405 +sg1 +(g2 +g3 +VBIOMD0000000213 +p406 +tp407 +Rp408 +(dp409 +g8 +Nsg9 +I00 +sbS'Nijhout2004_Folate_Cycle' +p410 +sg1 +(g2 +g3 +VBIOMD0000000017 +p411 +tp412 +Rp413 +(dp414 +g8 +Nsg9 +I00 +sbS'Hoefnagel2002_PyruvateBranches' +p415 +sg1 +(g2 +g3 +VBIOMD0000000016 +p416 +tp417 +Rp418 +(dp419 +g8 +Nsg9 +I00 +sbS'Goldbeter1995_CircClock' +p420 +sg1 +(g2 +g3 +VBIOMD0000000013 +p421 +tp422 +Rp423 +(dp424 +g8 +Nsg9 +I00 +sbS'Poolman2004_CalvinCycle' +p425 +sg1 +(g2 +g3 +VBIOMD0000000146 +p426 +tp427 +Rp428 +(dp429 +g8 +Nsg9 +I00 +sbS'Hatakeyama2003_MAPK' +p430 +sg1 +(g2 +g3 +VBIOMD0000000201 +p431 +tp432 +Rp433 +(dp434 +g8 +Nsg9 +I00 +sbS'Goldbeter2008_Somite_Segmentation_Clock_Notch_Wnt_FGF' +p435 +sg1 +(g2 +g3 +VBIOMD0000000019 +p436 +tp437 +Rp438 +(dp439 +g8 +Nsg9 +I00 +sbS'Schoeberl2002_EGF_MAPK' +p440 +sg1 +(g2 +g3 +VBIOMD0000000018 +p441 +tp442 +Rp443 +(dp444 +g8 +Nsg9 +I00 +sbS'Morrison1989_FolateCycle' +p445 +sg1 +(g2 +g3 +VBIOMD0000000144 +p446 +tp447 +Rp448 +(dp449 +g8 +Nsg9 +I00 +sbS'Calzone2007_CellCycle' +p450 +sg1 +(g2 +g3 +VBIOMD0000000099 +p451 +tp452 +Rp453 +(dp454 +g8 +Nsg9 +I00 +sbS'Laub1998_SpontaneousOscillations' +p455 +sg1 +(g2 +g3 +VBIOMD0000000098 +p456 +tp457 +Rp458 +(dp459 +g8 +Nsg9 +I00 +sbS'Goldbeter1990_CalciumSpike_CICR' +p460 +sg1 +(g2 +g3 +VBIOMD0000000152 +p461 +tp462 +Rp463 +(dp464 +g8 +Nsg9 +I00 +sbS'Fernandez2006_ModelA' +p465 +sg1 +(g2 +g3 +VBIOMD0000000153 +p466 +tp467 +Rp468 +(dp469 +g8 +Nsg9 +I00 +sbS'Fernandez2006_ModelB' +p470 +sg1 +(g2 +g3 +VBIOMD0000000095 +p471 +tp472 +Rp473 +(dp474 +g8 +Nsg9 +I00 +sbS'Zeilinger2006_PRR7-PRR9-Y' +p475 +sg1 +(g2 +g3 +VBIOMD0000000094 +p476 +tp477 +Rp478 +(dp479 +g8 +Nsg9 +I00 +sbS'Yamada2003_JAK_STAT_SOCS1_knockout' +p480 +sg1 +(g2 +g3 +VBIOMD0000000097 +p481 +tp482 +Rp483 +(dp484 +g8 +Nsg9 +I00 +sbS'Zeilinger2006_PRR7-PRR9light-Yprime' +p485 +sg1 +(g2 +g3 +VBIOMD0000000247 +p486 +tp487 +Rp488 +(dp489 +g8 +Nsg9 +I00 +sbS'Ralser2007_Carbohydrate_Rerouting_ROS' +p490 +sg1 +(g2 +g3 +VBIOMD0000000091 +p491 +tp492 +Rp493 +(dp494 +g8 +Nsg9 +I00 +sbS'Proctor2005 - Actions of chaperones and their role in ageing' +p495 +sg1 +(g2 +g3 +VBIOMD0000000241 +p496 +tp497 +Rp498 +(dp499 +g8 +Nsg9 +I00 +sbS'Shi1993_Caffeine_pressor_tolerance' +p500 +sg1 +(g2 +g3 +VBIOMD0000000093 +p501 +tp502 +Rp503 +(dp504 +g8 +Nsg9 +I00 +sbS'Yamada2003_JAK_STAT_pathway' +p505 +sg1 +(g2 +g3 +VBIOMD0000000216 +p506 +tp507 +Rp508 +(dp509 +g8 +Nsg9 +I00 +sbS'Hong2009_CircadianClock' +p510 +sg1 +(g2 +g3 +VBIOMD0000000473 +p511 +tp512 +Rp513 +(dp514 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Yeast metabolic model with modular rate law, merged with Pritchard 2002' +p515 +sg1 +(g2 +g3 +VBIOMD0000000472 +p516 +tp517 +Rp518 +(dp519 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Yeast metabolic model with modular rate law' +p520 +sg1 +(g2 +g3 +VBIOMD0000000471 +p521 +tp522 +Rp523 +(dp524 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Yeast metabolic model with linlog rate law' +p525 +sg1 +(g2 +g3 +VBIOMD0000000470 +p526 +tp527 +Rp528 +(dp529 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - E.coli metabolic model with modular rate law' +p530 +sg1 +(g2 +g3 +VBIOMD0000000476 +p531 +tp532 +Rp533 +(dp534 +g8 +Nsg9 +I00 +sbS'Adams2012 - Locke2006 Circadian Rhythm model refined with Input Signal Light Function' +p535 +sg1 +(g2 +g3 +VBIOMD0000000214 +p536 +tp537 +Rp538 +(dp539 +g8 +Nsg9 +I00 +sbS'Akman2008_Circadian_Clock_Model2' +p540 +sg1 +(g2 +g3 +VBIOMD0000000383 +p541 +tp542 +Rp543 +(dp544 +g8 +Nsg9 +I00 +sbS'Arnold2011_Farquhar1980_RuBisCO-CalvinCycle' +p545 +sg1 +(g2 +g3 +VBIOMD0000000260 +p546 +tp547 +Rp548 +(dp549 +g8 +Nsg9 +I00 +sbS'Tiago2010_FeMetabolism_FeAdequate' +p550 +sg1 +(g2 +g3 +VBIOMD0000000326 +p551 +tp552 +Rp553 +(dp554 +g8 +Nsg9 +I00 +sbS'DellOrco2009_phototransduction' +p555 +sg1 +(g2 +g3 +VBIOMD0000000038 +p556 +tp557 +Rp558 +(dp559 +g8 +Nsg9 +I00 +sbS'Rohwer2000_Phosphotransferase_System' +p560 +sg1 +(g2 +g3 +VBIOMD0000000458 +p561 +tp562 +Rp563 +(dp564 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Serine biosynthesis' +p565 +sg1 +(g2 +g3 +VBIOMD0000000384 +p566 +tp567 +Rp568 +(dp569 +g8 +Nsg9 +I00 +sbS'Arnold2011_Medlyn2002_RuBisCO-CalvinCycle' +p570 +sg1 +(g2 +g3 +VBIOMD0000000002 +p571 +tp572 +Rp573 +(dp574 +g8 +Nsg9 +I00 +sbS'Edelstein1996 - EPSP ACh species' +p575 +sg1 +(g2 +g3 +VBIOMD0000000218 +p576 +tp577 +Rp578 +(dp579 +g8 +Nsg9 +I00 +sbS'Singh2006_TCA_mtu_model2' +p580 +sg1 +(g2 +g3 +VBIOMD0000000488 +p581 +tp582 +Rp583 +(dp584 +g8 +Nsg9 +I00 +sbS"Proctor2013 - Effect of A\xce\xb2 immunisation in Alzheimer's disease" +p585 +sg1 +(g2 +g3 +VBIOMD0000000482 +p586 +tp587 +Rp588 +(dp589 +g8 +Nsg9 +I00 +sbS'Noguchi2013 - Insulin dependent glucose metabolism' +p590 +sg1 +(g2 +g3 +VBIOMD0000000325 +p591 +tp592 +Rp593 +(dp594 +g8 +Nsg9 +I00 +sbS'Palini2011_Minimal_2_Feedback_Model' +p595 +sg1 +(g2 +g3 +VBIOMD0000000161 +p596 +tp597 +Rp598 +(dp599 +g8 +Nsg9 +I00 +sbS'Eungdamrong2007_Ras_Activation' +p600 +sg1 +(g2 +g3 +VBIOMD0000000389 +p601 +tp602 +Rp603 +(dp604 +g8 +Nsg9 +I00 +sbS'Arnold2011_Hahn1986_CalvinCycle_Starch_Sucrose' +p605 +sg1 +(g2 +g3 +VBIOMD0000000088 +p606 +tp607 +Rp608 +(dp609 +g8 +Nsg9 +I00 +sbS'Maeda2006_MyosinPhosphorylation' +p610 +sg1 +(g2 +g3 +VBIOMD0000000162 +p611 +tp612 +Rp613 +(dp614 +g8 +Nsg9 +I00 +sbS'Hernjak2005_Calcium_Signaling' +p615 +sg1 +(g2 +g3 +VBIOMD0000000374 +p616 +tp617 +Rp618 +(dp619 +g8 +Nsg9 +I00 +sbS'Bertram1995_PancreaticBetaCell_CRAC' +p620 +sg1 +(g2 +g3 +VBIOMD0000000375 +p621 +tp622 +Rp623 +(dp624 +g8 +Nsg9 +I00 +sbS'Mears1997_CRAC_PancreaticBetaCells' +p625 +sg1 +(g2 +g3 +VBIOMD0000000376 +p626 +tp627 +Rp628 +(dp629 +g8 +Nsg9 +I00 +sbS'Bertram2007_IsletCell_Oscillations' +p630 +sg1 +(g2 +g3 +VBIOMD0000000166 +p631 +tp632 +Rp633 +(dp634 +g8 +Nsg9 +I00 +sbS'Zhu2007_TF_modulated_by_Calcium' +p635 +sg1 +(g2 +g3 +VBIOMD0000000082 +p636 +tp637 +Rp638 +(dp639 +g8 +Nsg9 +I00 +sbS'Thomsen1988_AdenylateCyclase_Inhibition' +p640 +sg1 +(g2 +g3 +VBIOMD0000000083 +p641 +tp642 +Rp643 +(dp644 +g8 +Nsg9 +I00 +sbS'Leloup2003_CircClock_LD_REV-ERBalpha' +p645 +sg1 +(g2 +g3 +VBIOMD0000000080 +p646 +tp647 +Rp648 +(dp649 +g8 +Nsg9 +I00 +sbS'Thomsen1989_AdenylateCyclase' +p650 +sg1 +(g2 +g3 +VBIOMD0000000081 +p651 +tp652 +Rp653 +(dp654 +g8 +Nsg9 +I00 +sbS'Suh2004_KCNQ_Regulation' +p655 +sg1 +(g2 +g3 +VBIOMD0000000086 +p656 +tp657 +Rp658 +(dp659 +g8 +Nsg9 +I00 +sbS'Bornheimer2004_GTPaseCycle' +p660 +sg1 +(g2 +g3 +VBIOMD0000000087 +p661 +tp662 +Rp663 +(dp664 +g8 +Nsg9 +I00 +sbS'Proctor2006_telomere' +p665 +sg1 +(g2 +g3 +VBIOMD0000000277 +p666 +tp667 +Rp668 +(dp669 +g8 +Nsg9 +I00 +sbS'Shrestha2010_HyperCalcemia_PTHresponse' +p670 +sg1 +(g2 +g3 +VBIOMD0000000085 +p671 +tp672 +Rp673 +(dp674 +g8 +Nsg9 +I00 +sbS'Maurya2005_GTPaseCycle_reducedOrder' +p675 +sg1 +(g2 +g3 +VBIOMD0000000183 +p676 +tp677 +Rp678 +(dp679 +g8 +Nsg9 +I00 +sbS'Stefan2008_calmodulin_allostery' +p680 +sg1 +(g2 +g3 +VBIOMD0000000461 +p681 +tp682 +Rp683 +(dp684 +g8 +Nsg9 +I00 +sbS'Liebal2012 - B.subtilis transcription inhibition model' +p685 +sg1 +(g2 +g3 +VBIOMD0000000462 +p686 +tp687 +Rp688 +(dp689 +g8 +Nsg9 +I00 +sbS'Proctor2012 - Amyloid-beta aggregation' +p690 +sg1 +(g2 +g3 +VBIOMD0000000180 +p691 +tp692 +Rp693 +(dp694 +g8 +Nsg9 +I00 +sbS'Kim2007_CellularMemory_SymmetricModel' +p695 +sg1 +(g2 +g3 +VBIOMD0000000464 +p696 +tp697 +Rp698 +(dp699 +g8 +Nsg9 +I00 +sbS'Koo2013 - Shear stress induced calcium influx and eNOS activation - Model 1' +p700 +sg1 +(g2 +g3 +VBIOMD0000000465 +p701 +tp702 +Rp703 +(dp704 +g8 +Nsg9 +I00 +sbS'Koo2013 - Shear stress induced AKT and eNOS phosphorylation - Model 2' +p705 +sg1 +(g2 +g3 +VBIOMD0000000466 +p706 +tp707 +Rp708 +(dp709 +g8 +Nsg9 +I00 +sbS'Koo2013 - Shear stress induced eNOS expression - Model 3' +p710 +sg1 +(g2 +g3 +VBIOMD0000000467 +p711 +tp712 +Rp713 +(dp714 +g8 +Nsg9 +I00 +sbS'Koo2013 - Shear stress induced NO production - Model 4' +p715 +sg1 +(g2 +g3 +VBIOMD0000000468 +p716 +tp717 +Rp718 +(dp719 +g8 +Nsg9 +I00 +sbS'Koo2013 - Integrated shear stress induced NO production model' +p720 +sg1 +(g2 +g3 +VBIOMD0000000469 +p721 +tp722 +Rp723 +(dp724 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - E.coli metabolic model with linlog rate law' +p725 +sg1 +(g2 +g3 +VBIOMD0000000189 +p726 +tp727 +Rp728 +(dp729 +g8 +Nsg9 +I00 +sbS'Proctor2008_p53_Mdm2_ARF' +p730 +sg1 +(g2 +g3 +VBIOMD0000000188 +p731 +tp732 +Rp733 +(dp734 +g8 +Nsg9 +I00 +sbS'Proctor2008_p53_Mdm2_ATM' +p735 +sg1 +(g2 +g3 +VBIOMD0000000035 +p736 +tp737 +Rp738 +(dp739 +g8 +Nsg9 +I00 +sbS'Vilar2002_Oscillator' +p740 +sg1 +(g2 +g3 +VBIOMD0000000339 +p741 +tp742 +Rp743 +(dp744 +g8 +Nsg9 +I00 +sbS'Wajima2009_BloodCoagulation_PTtest' +p745 +sg1 +(g2 +g3 +VBIOMD0000000347 +p746 +tp747 +Rp748 +(dp749 +g8 +Nsg9 +I00 +sbS'Bachmann2011_JAK2-STAT5_FeedbackControl' +p750 +sg1 +(g2 +g3 +VBIOMD0000000349 +p751 +tp752 +Rp753 +(dp754 +g8 +Nsg9 +I00 +sbS'Fridlyand2010_GlucoseSensitivity_B' +p755 +sg1 +(g2 +g3 +VBIOMD0000000348 +p756 +tp757 +Rp758 +(dp759 +g8 +Nsg9 +I00 +sbS'Fridlyand2010_GlucoseSensitivity_A' +p760 +sg1 +(g2 +g3 +VBIOMD0000000322 +p761 +tp762 +Rp763 +(dp764 +g8 +Nsg9 +I00 +sbS'Kim2011_Oscillator_SimpleI' +p765 +sg1 +(g2 +g3 +VBIOMD0000000179 +p766 +tp767 +Rp768 +(dp769 +g8 +Nsg9 +I00 +sbS'Kim2007_CellularMemory_AsymmetricModel' +p770 +sg1 +(g2 +g3 +VBIOMD0000000176 +p771 +tp772 +Rp773 +(dp774 +g8 +Nsg9 +I00 +sbS'Conant2007_WGD_glycolysis_2A3AB' +p775 +sg1 +(g2 +g3 +VBIOMD0000000177 +p776 +tp777 +Rp778 +(dp779 +g8 +Nsg9 +I00 +sbS'Conant2007_glycolysis_2C' +p780 +sg1 +(g2 +g3 +VBIOMD0000000174 +p781 +tp782 +Rp783 +(dp784 +g8 +Nsg9 +I00 +sbS'Del_Conte_Zerial2008_Rab5_Rab7_cut_out_switch' +p785 +sg1 +(g2 +g3 +VBIOMD0000000175 +p786 +tp787 +Rp788 +(dp789 +g8 +Nsg9 +I00 +sbS'Birtwistle2007_ErbB_Signalling' +p790 +sg1 +(g2 +g3 +VBIOMD0000000172 +p791 +tp792 +Rp793 +(dp794 +g8 +Nsg9 +I00 +sbS'Pritchard2002_glycolysis' +p795 +sg1 +(g2 +g3 +VBIOMD0000000340 +p796 +tp797 +Rp798 +(dp799 +g8 +Nsg9 +I00 +sbS'Wajima2009_BloodCoagulation_warfarin_heparin' +p800 +sg1 +(g2 +g3 +VBIOMD0000000343 +p801 +tp802 +Rp803 +(dp804 +g8 +Nsg9 +I00 +sbS'Brannmark2010_InsulinSignalling_Mifamodel' +p805 +sg1 +(g2 +g3 +VBIOMD0000000171 +p806 +tp807 +Rp808 +(dp809 +g8 +Nsg9 +I00 +sbS'Leloup1998_CircClock_LD' +p810 +sg1 +(g2 +g3 +VBIOMD0000000077 +p811 +tp812 +Rp813 +(dp814 +g8 +Nsg9 +I00 +sbS'Blum2000_LHsecretion_1' +p815 +sg1 +(g2 +g3 +VBIOMD0000000076 +p816 +tp817 +Rp818 +(dp819 +g8 +Nsg9 +I00 +sbS'Cronwright2002_Glycerol_Synthesis' +p820 +sg1 +(g2 +g3 +VBIOMD0000000264 +p821 +tp822 +Rp823 +(dp824 +g8 +Nsg9 +I00 +sbS'Fujita2010_Akt_Signalling_EGFRinhib' +p825 +sg1 +(g2 +g3 +VBIOMD0000000074 +p826 +tp827 +Rp828 +(dp829 +g8 +Nsg9 +I00 +sbS'Leloup2003_CircClock_DD_REV-ERBalpha' +p830 +sg1 +(g2 +g3 +VBIOMD0000000073 +p831 +tp832 +Rp833 +(dp834 +g8 +Nsg9 +I00 +sbS'Leloup2003_CircClock_DD' +p835 +sg1 +(g2 +g3 +VBIOMD0000000072 +p836 +tp837 +Rp838 +(dp839 +g8 +Nsg9 +I00 +sbS'Yi2003_GproteinCycle' +p840 +sg1 +(g2 +g3 +VBIOMD0000000165 +p841 +tp842 +Rp843 +(dp844 +g8 +Nsg9 +I00 +sbS'Saucerman2006_PKA' +p845 +sg1 +(g2 +g3 +VBIOMD0000000070 +p846 +tp847 +Rp848 +(dp849 +g8 +Nsg9 +I00 +sbS'Holzhutter2004_Erythrocyte_Metabolism' +p850 +sg1 +(g2 +g3 +VBIOMD0000000245 +p851 +tp852 +Rp853 +(dp854 +g8 +Nsg9 +I00 +sbS'Lei2001_Yeast_Aerobic_Metabolism' +p855 +sg1 +(g2 +g3 +VBIOMD0000000268 +p856 +tp857 +Rp858 +(dp859 +g8 +Nsg9 +I00 +sbS'Reed2008_Glutathione_Metabolism' +p860 +sg1 +(g2 +g3 +VBIOMD0000000269 +p861 +tp862 +Rp863 +(dp864 +g8 +Nsg9 +I00 +sbS'Liu2010_Hormonal_Crosstalk_Arabidopsis' +p865 +sg1 +(g2 +g3 +VBIOMD0000000190 +p866 +tp867 +Rp868 +(dp869 +g8 +Nsg9 +I00 +sbS'Rodriguez-Caso2006_Polyamine_Metabolism' +p870 +sg1 +(g2 +g3 +VBIOMD0000000191 +p871 +tp872 +Rp873 +(dp874 +g8 +Nsg9 +I00 +sbS'Monta\xc3\xb1ez2008_Arginine_catabolism' +p875 +sg1 +(g2 +g3 +VBIOMD0000000192 +p876 +tp877 +Rp878 +(dp879 +g8 +Nsg9 +I00 +sbS'G\xc3\xb6rlich2003_RanGTP_gradient' +p880 +sg1 +(g2 +g3 +VBIOMD0000000071 +p881 +tp882 +Rp883 +(dp884 +g8 +Nsg9 +I00 +sbS'Bakker2001_Glycolysis' +p885 +sg1 +(g2 +g3 +VBIOMD0000000124 +p886 +tp887 +Rp888 +(dp889 +g8 +Nsg9 +I00 +sbS'Wu2006_K+Channel' +p890 +sg1 +(g2 +g3 +VBIOMD0000000198 +p891 +tp892 +Rp893 +(dp894 +g8 +Nsg9 +I00 +sbS'Stone1996_NOsGC' +p895 +sg1 +(g2 +g3 +VBIOMD0000000199 +p896 +tp897 +Rp898 +(dp899 +g8 +Nsg9 +I00 +sbS'Santolini2001_nNOS_Mechanism_Regulation' +p900 +sg1 +(g2 +g3 +VBIOMD0000000261 +p901 +tp902 +Rp903 +(dp904 +g8 +Nsg9 +I00 +sbS'Tiago2010_FeMetabolism_FeLoaded' +p905 +sg1 +(g2 +g3 +VBIOMD0000000052 +p906 +tp907 +Rp908 +(dp909 +g8 +Nsg9 +I00 +sbS'Brands2002 - Monosaccharide-casein systems' +p910 +sg1 +(g2 +g3 +VBIOMD0000000299 +p911 +tp912 +Rp913 +(dp914 +g8 +Nsg9 +I00 +sbS'Leloup1999_CircadianRhythms_Neurospora' +p915 +sg1 +(g2 +g3 +VBIOMD0000000298 +p916 +tp917 +Rp918 +(dp919 +g8 +Nsg9 +I00 +sbS'Leloup1999_CircadianRhythms_Drosophila' +p920 +sg1 +(g2 +g3 +VBIOMD0000000293 +p921 +tp922 +Rp923 +(dp924 +g8 +Nsg9 +I00 +sbS'Proctor2010_UCHL1_ProteinAggregation' +p925 +sg1 +(g2 +g3 +VBIOMD0000000292 +p926 +tp927 +Rp928 +(dp929 +g8 +Nsg9 +I00 +sbS'Rovers1995_Photsynthetic_Oscillations' +p930 +sg1 +(g2 +g3 +VBIOMD0000000291 +p931 +tp932 +Rp933 +(dp934 +g8 +Nsg9 +I00 +sbS'Nikolaev2005_AlbuminBilirubinAdsorption' +p935 +sg1 +(g2 +g3 +VBIOMD0000000170 +p936 +tp937 +Rp938 +(dp939 +g8 +Nsg9 +I00 +sbS'Weimann2004_CircadianOscillator' +p940 +sg1 +(g2 +g3 +VBIOMD0000000296 +p941 +tp942 +Rp943 +(dp944 +g8 +Nsg9 +I00 +sbS'Balagadd\xc3\xa92008_E_coli_Predator_Prey' +p945 +sg1 +(g2 +g3 +VBIOMD0000000212 +p946 +tp947 +Rp948 +(dp949 +g8 +Nsg9 +I00 +sbS'Curien2009_Aspartate_Metabolism' +p950 +sg1 +(g2 +g3 +VBIOMD0000000108 +p951 +tp952 +Rp953 +(dp954 +g8 +Nsg9 +I00 +sbS'Kowald2006_SOD' +p955 +sg1 +(g2 +g3 +VBIOMD0000000321 +p956 +tp957 +Rp958 +(dp959 +g8 +Nsg9 +I00 +sbS'Grange2001 - L Dopa PK model' +p960 +sg1 +(g2 +g3 +VBIOMD0000000352 +p961 +tp962 +Rp963 +(dp964 +g8 +Nsg9 +I00 +sbS'Vernoux2011_AuxinSignaling_AuxinFluctuating' +p965 +sg1 +(g2 +g3 +VBIOMD0000000353 +p966 +tp967 +Rp968 +(dp969 +g8 +Nsg9 +I00 +sbS'Nag2011_ChloroplasticStarchDegradation' +p970 +sg1 +(g2 +g3 +VBIOMD0000000350 +p971 +tp972 +Rp973 +(dp974 +g8 +Nsg9 +I00 +sbS'Troein2011_ClockCircuit_OstreococcusTauri' +p975 +sg1 +(g2 +g3 +VBIOMD0000000351 +p976 +tp977 +Rp978 +(dp979 +g8 +Nsg9 +I00 +sbS'Vernoux2011_AuxinSignaling_AuxinSingleStepInput' +p980 +sg1 +(g2 +g3 +VBIOMD0000000356 +p981 +tp982 +Rp983 +(dp984 +g8 +Nsg9 +I00 +sbS'Nyman2011_M3Hierarachical_InsulinGlucosedynamics' +p985 +sg1 +(g2 +g3 +VBIOMD0000000106 +p986 +tp987 +Rp988 +(dp989 +g8 +Nsg9 +I00 +sbS'Yang2007_ArachidonicAcid' +p990 +sg1 +(g2 +g3 +VBIOMD0000000354 +p991 +tp992 +Rp993 +(dp994 +g8 +Nsg9 +I00 +sbS'Abell2011_CalciumSignaling_WithoutAdaptation' +p995 +sg1 +(g2 +g3 +VBIOMD0000000355 +p996 +tp997 +Rp998 +(dp999 +g8 +Nsg9 +I00 +sbS'Abell2011_CalciumSignaling_WithAdaptation' +p1000 +sg1 +(g2 +g3 +VBIOMD0000000064 +p1001 +tp1002 +Rp1003 +(dp1004 +g8 +Nsg9 +I00 +sbS'Teusink2000_Glycolysis' +p1005 +sg1 +(g2 +g3 +VBIOMD0000000065 +p1006 +tp1007 +Rp1008 +(dp1009 +g8 +Nsg9 +I00 +sbS'Yildirim2003_Lac_Operon' +p1010 +sg1 +(g2 +g3 +VBIOMD0000000211 +p1011 +tp1012 +Rp1013 +(dp1014 +g8 +Nsg9 +I00 +sbS'Albert2005_Glycolysis' +p1015 +sg1 +(g2 +g3 +VBIOMD0000000067 +p1016 +tp1017 +Rp1018 +(dp1019 +g8 +Nsg9 +I00 +sbS'Fung2005_Metabolic_Oscillator' +p1020 +sg1 +(g2 +g3 +VBIOMD0000000217 +p1021 +tp1022 +Rp1023 +(dp1024 +g8 +Nsg9 +I00 +sbS'Bruggeman2005_AmmoniumAssimilation' +p1025 +sg1 +(g2 +g3 +VBIOMD0000000061 +p1026 +tp1027 +Rp1028 +(dp1029 +g8 +Nsg9 +I00 +sbS'Hynne2001_Glycolysis' +p1030 +sg1 +(g2 +g3 +VBIOMD0000000062 +p1031 +tp1032 +Rp1033 +(dp1034 +g8 +Nsg9 +I00 +sbS'Bhartiya2003_Tryptophan_operon' +p1035 +sg1 +(g2 +g3 +VBIOMD0000000063 +p1036 +tp1037 +Rp1038 +(dp1039 +g8 +Nsg9 +I00 +sbS'Galazzo1990_FermentationPathwayKinetics' +p1040 +sg1 +(g2 +g3 +VBIOMD0000000054 +p1041 +tp1042 +Rp1043 +(dp1044 +g8 +Nsg9 +I00 +sbS'Ataullahkhanov1996_Adenylate' +p1045 +sg1 +(g2 +g3 +VBIOMD0000000219 +p1046 +tp1047 +Rp1048 +(dp1049 +g8 +Nsg9 +I00 +sbS'Singh2006_TCA_mtu_model1' +p1050 +sg1 +(g2 +g3 +VBIOMD0000000078 +p1051 +tp1052 +Rp1053 +(dp1054 +g8 +Nsg9 +I00 +sbS'Leloup2003_CircClock_LD' +p1055 +sg1 +(g2 +g3 +VBIOMD0000000068 +p1056 +tp1057 +Rp1058 +(dp1059 +g8 +Nsg9 +I00 +sbS'Curien2003_MetThr_synthesis' +p1060 +sg1 +(g2 +g3 +VBIOMD0000000236 +p1061 +tp1062 +Rp1063 +(dp1064 +g8 +Nsg9 +I00 +sbS'Westermark2003_Pancreatic_GlycOsc_extended' +p1065 +sg1 +(g2 +g3 +VBIOMD0000000320 +p1066 +tp1067 +Rp1068 +(dp1069 +g8 +Nsg9 +I00 +sbS'Grange2001 - PK interaction of L-dopa and benserazide' +p1070 +sg1 +(g2 +g3 +VBIOMD0000000042 +p1071 +tp1072 +Rp1073 +(dp1074 +g8 +Nsg9 +I00 +sbS'Nielsen1998_Glycolysis' +p1075 +sg1 +(g2 +g3 +VBIOMD0000000066 +p1076 +tp1077 +Rp1078 +(dp1079 +g8 +Nsg9 +I00 +sbS'Chassagnole2001_Threonine Synthesis' +p1080 +sg1 +(g2 +g3 +VBIOMD0000000043 +p1081 +tp1082 +Rp1083 +(dp1084 +g8 +Nsg9 +I00 +sbS'Borghans1997 - Calcium Oscillation - Model 1' +p1085 +sg1 +(g2 +g3 +VBIOMD0000000145 +p1086 +tp1087 +Rp1088 +(dp1089 +g8 +Nsg9 +I00 +sbS'Wang2007_ATP_induced_Ca_Oscillation' +p1090 +sg1 +(g2 +g3 +VBIOMD0000000281 +p1091 +tp1092 +Rp1093 +(dp1094 +g8 +Nsg9 +I00 +sbS'Chance1960_Glycolysis_Respiration' +p1095 +sg1 +(g2 +g3 +VBIOMD0000000282 +p1096 +tp1097 +Rp1098 +(dp1099 +g8 +Nsg9 +I00 +sbS'Chance1952_Catalase_Mechanism' +p1100 +sg1 +(g2 +g3 +VBIOMD0000000283 +p1101 +tp1102 +Rp1103 +(dp1104 +g8 +Nsg9 +I00 +sbS'Chance1943_Peroxidase_ES_Kinetics' +p1105 +sg1 +(g2 +g3 +VBIOMD0000000286 +p1106 +tp1107 +Rp1108 +(dp1109 +g8 +Nsg9 +I00 +sbS'Proctor2010_GSK3_p53_AlzheimerDisease' +p1110 +sg1 +(g2 +g3 +VBIOMD0000000287 +p1111 +tp1112 +Rp1113 +(dp1114 +g8 +Nsg9 +I00 +sbS'Passos2010_DNAdamage_CellularSenescence' +p1115 +sg1 +(g2 +g3 +VBIOMD0000000119 +p1116 +tp1117 +Rp1118 +(dp1119 +g8 +Nsg9 +I00 +sbS'Golomb2006_SomaticBursting_nonzero[Ca]' +p1120 +sg1 +(g2 +g3 +VBIOMD0000000047 +p1121 +tp1122 +Rp1123 +(dp1124 +g8 +Nsg9 +I00 +sbS'Oxhamre2005_Ca_oscillation' +p1125 +sg1 +(g2 +g3 +VBIOMD0000000248 +p1126 +tp1127 +Rp1128 +(dp1129 +g8 +Nsg9 +I00 +sbS'Lai2007_O2_Transport_Metabolism' +p1130 +sg1 +(g2 +g3 +VBIOMD0000000112 +p1131 +tp1132 +Rp1133 +(dp1134 +g8 +Nsg9 +I00 +sbS'Clarke2006_Smad_signalling' +p1135 +sg1 +(g2 +g3 +VBIOMD0000000113 +p1136 +tp1137 +Rp1138 +(dp1139 +g8 +Nsg9 +I00 +sbS'Dupont1992_Ca_dpt_protein_phospho' +p1140 +sg1 +(g2 +g3 +VBIOMD0000000114 +p1141 +tp1142 +Rp1143 +(dp1144 +g8 +Nsg9 +I00 +sbS'Somogyi1990_CaOscillations' +p1145 +sg1 +(g2 +g3 +VBIOMD0000000115 +p1146 +tp1147 +Rp1148 +(dp1149 +g8 +Nsg9 +I00 +sbS'Somogyi1990_CaOscillations_SingleCaSpike' +p1150 +sg1 +(g2 +g3 +VBIOMD0000000266 +p1151 +tp1152 +Rp1153 +(dp1154 +g8 +Nsg9 +I00 +sbS'Voit2003_Trehalose_Cycle' +p1155 +sg1 +(g2 +g3 +VBIOMD0000000051 +p1156 +tp1157 +Rp1158 +(dp1159 +g8 +Nsg9 +I00 +sbS'Chassagnole2002_Carbon_Metabolism' +p1160 +sg1 +(g2 +g3 +VBIOMD0000000050 +p1161 +tp1162 +Rp1163 +(dp1164 +g8 +Nsg9 +I00 +sbS'Martins2003_AmadoriDegradation' +p1165 +sg1 +(g2 +g3 +VBIOMD0000000053 +p1166 +tp1167 +Rp1168 +(dp1169 +g8 +Nsg9 +I00 +sbS'Ferreira2003_CML_generation2' +p1170 +sg1 +(g2 +g3 +VBIOMD0000000089 +p1171 +tp1172 +Rp1173 +(dp1174 +g8 +Nsg9 +I00 +sbS'Locke2006_CircClock_LL' +p1175 +sg1 +(g2 +g3 +VBIOMD0000000055 +p1176 +tp1177 +Rp1178 +(dp1179 +g8 +Nsg9 +I00 +sbS'Locke2005 - Circadian Clock' +p1180 +sg1 +(g2 +g3 +VBIOMD0000000205 +p1181 +tp1182 +Rp1183 +(dp1184 +g8 +Nsg9 +I00 +sbS'Ung2008_EGFR_Endocytosis' +p1185 +sg1 +(g2 +g3 +VBIOMD0000000206 +p1186 +tp1187 +Rp1188 +(dp1189 +g8 +Nsg9 +I00 +sbS'Wolf2000_Glycolytic_Oscillations' +p1190 +sg1 +(g2 +g3 +VBIOMD0000000328 +p1191 +tp1192 +Rp1193 +(dp1194 +g8 +Nsg9 +I00 +sbS'Bucher2011_Atorvastatin_Metabolism' +p1195 +sg1 +(g2 +g3 +VBIOMD0000000059 +p1196 +tp1197 +Rp1198 +(dp1199 +g8 +Nsg9 +I00 +sbS'Fridlyand2003_Calcium_flux' +p1200 +sg1 +(g2 +g3 +VBIOMD0000000058 +p1201 +tp1202 +Rp1203 +(dp1204 +g8 +Nsg9 +I00 +sbS'Bindschadler2001_coupled_Ca_oscillators' +p1205 +sg1 +(g2 +g3 +VBIOMD0000000457 +p1206 +tp1207 +Rp1208 +(dp1209 +g8 +Nsg9 +I00 +sbS'Firczuk2013 - Eukaryotic mRNA translation machinery' +p1210 +sg1 +(g2 +g3 +VBIOMD0000000323 +p1211 +tp1212 +Rp1213 +(dp1214 +g8 +Nsg9 +I00 +sbS'Kim2011_Oscillator_SimpleIII' +p1215 +sg1 +(g2 +g3 +VBIOMD0000000450 +p1216 +tp1217 +Rp1218 +(dp1219 +g8 +Nsg9 +I00 +sbS'Reyes-Palomares2012 - a combined model hepatic polyamine and sulfur aminoacid metabolism - version2' +p1220 +sg1 +(g2 +g3 +VBIOMD0000000453 +p1221 +tp1222 +Rp1223 +(dp1224 +g8 +Nsg9 +I00 +sbS'Bidkhori2012 - EGFR signalling in NSCLC' +p1225 +sg1 +(g2 +g3 +VBIOMD0000000452 +p1226 +tp1227 +Rp1228 +(dp1229 +g8 +Nsg9 +I00 +sbS'Bidkhori2012 - normal EGFR signalling' +p1230 +sg1 +(g2 +g3 +VBIOMD0000000438 +p1231 +tp1232 +Rp1233 +(dp1234 +g8 +Nsg9 +I00 +sbS'Saeidi2012 - Quorum sensing device that produces GFP' +p1235 +sg1 +(g2 +g3 +VBIOMD0000000437 +p1236 +tp1237 +Rp1238 +(dp1239 +g8 +Nsg9 +I00 +sbS'Tseng2012 - Circadian clock of N.crassa' +p1240 +sg1 +(g2 +g3 +VBIOMD0000000436 +p1241 +tp1242 +Rp1243 +(dp1244 +g8 +Nsg9 +I00 +sbS'Gupta2009 - Eicosanoid Metabolism' +p1245 +sg1 +(g2 +g3 +VBIOMD0000000434 +p1246 +tp1247 +Rp1248 +(dp1249 +g8 +Nsg9 +I00 +sbS'McAuley2012 - Whole-body Cholesterol Metabolism' +p1250 +sg1 +(g2 +g3 +VBIOMD0000000041 +p1251 +tp1252 +Rp1253 +(dp1254 +g8 +Nsg9 +I00 +sbS'Kongas2007 - Creatine Kinase in energy metabolic signaling in muscle' +p1255 +sg1 +(g2 +g3 +VBIOMD0000000259 +p1256 +tp1257 +Rp1258 +(dp1259 +g8 +Nsg9 +I00 +sbS'Tiago2010_FeMetabolism_FeDeficient' +p1260 +sg1 +(g2 +g3 +VBIOMD0000000378 +p1261 +tp1262 +Rp1263 +(dp1264 +g8 +Nsg9 +I00 +sbS'Chay1997_CalciumConcentration' +p1265 +sg1 +(g2 +g3 +VBIOMD0000000185 +p1266 +tp1267 +Rp1268 +(dp1269 +g8 +Nsg9 +I00 +sbS'Locke2008_Circadian_Clock' +p1270 +sg1 +(g2 +g3 +VBIOMD0000000246 +p1271 +tp1272 +Rp1273 +(dp1274 +g8 +Nsg9 +I00 +sbS'Vasalou2010_Pacemaker_Neuron_SCN' +p1275 +sg1 +(g2 +g3 +VBIOMD0000000379 +p1276 +tp1277 +Rp1278 +(dp1279 +g8 +Nsg9 +I00 +sbS'DallaMan2007_MealModel_GlucoseInsulinSystem' +p1280 +sg1 +(g2 +g3 +VBIOMD0000000372 +p1281 +tp1282 +Rp1283 +(dp1284 +g8 +Nsg9 +I00 +sbS'Tolic2000_InsulinGlucoseFeedback' +p1285 +sg1 +(g2 +g3 +VBIOMD0000000341 +p1286 +tp1287 +Rp1288 +(dp1289 +g8 +Nsg9 +I00 +sbS'Topp2000_BetaCellMass_Diabetes' +p1290 +sg1 +(g2 +g3 +VBIOMD0000000273 +p1291 +tp1292 +Rp1293 +(dp1294 +g8 +Nsg9 +I00 +sbS'Pokhilko2010_CircClock' +p1295 +sg1 +(g2 +g3 +VBIOMD0000000045 +p1296 +tp1297 +Rp1298 +(dp1299 +g8 +Nsg9 +I00 +sbS'Borghans1997 - Calcium Oscillation - Model 3' +p1300 +sg1 +(g2 +g3 +VBIOMD0000000143 +p1301 +tp1302 +Rp1303 +(dp1304 +g8 +Nsg9 +I00 +sbS'Olsen2003_neutrophil_oscillatory_metabolism' +p1305 +sg1 +(g2 +g3 +VBIOMD0000000239 +p1306 +tp1307 +Rp1308 +(dp1309 +g8 +Nsg9 +I00 +sbS'Jiang2007 - GSIS system, Pancreatic Beta Cells' +p1310 +sg1 +(g2 +g3 +VBIOMD0000000123 +p1311 +tp1312 +Rp1313 +(dp1314 +g8 +Nsg9 +I00 +sbS'Fisher2006_NFAT_Activation' +p1315 +sg1 +(g2 +g3 +VBIOMD0000000122 +p1316 +tp1317 +Rp1318 +(dp1319 +g8 +Nsg9 +I00 +sbS'Fisher2006_Ca_Oscillation_dpdnt_NFAT_dynamics' +p1320 +sg1 +(g2 +g3 +VBIOMD0000000046 +p1321 +tp1322 +Rp1323 +(dp1324 +g8 +Nsg9 +I00 +sbS'Olsen2003_peroxidase' +p1325 +sg1 +(g2 +g3 +VBIOMD0000000275 +p1326 +tp1327 +Rp1328 +(dp1329 +g8 +Nsg9 +I00 +sbS'Goldbeter2007_Somitogenesis_Switch' +p1330 +sg1 +(g2 +g3 +VBIOMD0000000044 +p1331 +tp1332 +Rp1333 +(dp1334 +g8 +Nsg9 +I00 +sbS'Borghans1997 - Calcium Oscillation - Model 2' +p1335 +sg1 +(g2 +g3 +VBIOMD0000000012 +p1336 +tp1337 +Rp1338 +(dp1339 +g8 +Nsg9 +I00 +sbS'Elowitz2000 - Repressilator' +p1340 +sg1 +(g2 +g3 +VBIOMD0000000231 +p1341 +tp1342 +Rp1343 +(dp1344 +g8 +Nsg9 +I00 +sbS'Valero2006_Adenine_TernaryCycle' +p1345 +sg1 +(g2 +g3 +VBIOMD0000000128 +p1346 +tp1347 +Rp1348 +(dp1349 +g8 +Nsg9 +I00 +sbS'Bertram2006_Endothelin' +p1350 +sg1 +(g2 +g3 +VBIOMD0000000040 +p1351 +tp1352 +Rp1353 +(dp1354 +g8 +Nsg9 +I00 +sbS'Field1974_Oregonator' +p1355 +sg1 +(g2 +g3 +VBIOMD0000000232 +p1356 +tp1357 +Rp1358 +(dp1359 +g8 +Nsg9 +I00 +sbS'Nazaret2009_TCA_RC_ATP' +p1360 +sg1 +(g2 +g3 +VBIOMD0000000184 +p1361 +tp1362 +Rp1363 +(dp1364 +g8 +Nsg9 +I00 +sbS'Lavrentovich2008_Ca_Oscillations' +p1365 +sg1 +(g2 +g3 +VBIOMD0000000382 +p1366 +tp1367 +Rp1368 +(dp1369 +g8 +Nsg9 +I00 +sbS'Sturis1991_InsulinGlucoseModel_UltradianOscillation' +p1370 +sg1 +(g2 +g3 +VBIOMD0000000448 +p1371 +tp1372 +Rp1373 +(dp1374 +g8 +Nsg9 +I00 +sbS'Br\xc3\xa4nnmark2013 - Insulin signalling in human adipocytes (normal condition)' +p1375 +sg1 +(g2 +g3 +VBIOMD0000000449 +p1376 +tp1377 +Rp1378 +(dp1379 +g8 +Nsg9 +I00 +sbS'Br\xc3\xa4nnmark2013 - Insulin signalling in human adipocytes (diabetic condition)' +p1380 +sg1 +(g2 +g3 +VBIOMD0000000338 +p1381 +tp1382 +Rp1383 +(dp1384 +g8 +Nsg9 +I00 +sbS'Wajima2009_BloodCoagulation_aPTTtest' +p1385 +sg1 +(g2 +g3 +VBIOMD0000000215 +p1386 +tp1387 +Rp1388 +(dp1389 +g8 +Nsg9 +I00 +sbS'Schulz2009_Th1_differentiation' +p1390 +sg1 +(g2 +g3 +VBIOMD0000000373 +p1391 +tp1392 +Rp1393 +(dp1394 +g8 +Nsg9 +I00 +sbS'Bertram2004_PancreaticBetaCell_modelB' +p1395 +sg1 +(g2 +g3 +VBIOMD0000000276 +p1396 +tp1397 +Rp1398 +(dp1399 +g8 +Nsg9 +I00 +sbS'Shrestha2010_HypoCalcemia_PTHresponse' +p1400 +sg1 +(g2 +g3 +VBIOMD0000000330 +p1401 +tp1402 +Rp1403 +(dp1404 +g8 +Nsg9 +I00 +sbS'Larsen2004_CalciumSpiking' +p1405 +sg1 +(g2 +g3 +VBIOMD0000000445 +p1406 +tp1407 +Rp1408 +(dp1409 +g8 +Nsg9 +I00 +sbS'Pokhilko2013 - TOC1 signalling in Arabidopsis circadian clock' +p1410 +s. \ No newline at end of file diff --git a/moose-gui/bioModels/getModelsIdByChEBIId.pkl b/moose-gui/bioModels/getModelsIdByChEBIId.pkl new file mode 100644 index 0000000000000000000000000000000000000000..8fa0309c1bd440e11b250435747645c4c25c4836 --- /dev/null +++ b/moose-gui/bioModels/getModelsIdByChEBIId.pkl @@ -0,0 +1,3663 @@ +(dp0 +ccopy_reg +_reconstructor +p1 +(csuds.sax.text +Text +p2 +c__builtin__ +unicode +p3 +VBIOMD0000000183 +p4 +tp5 +Rp6 +(dp7 +S'lang' +p8 +NsS'escaped' +p9 +I00 +sbS'Stefan2008_calmodulin_allostery' +p10 +sg1 +(g2 +g3 +VBIOMD0000000428 +p11 +tp12 +Rp13 +(dp14 +g8 +Nsg9 +I00 +sbS'Achcar2012 - Glycolysis in bloodstream form T. brucei' +p15 +sg1 +(g2 +g3 +VBIOMD0000000429 +p16 +tp17 +Rp18 +(dp19 +g8 +Nsg9 +I00 +sbS'Schaber2012 - Hog pathway in yeast' +p20 +sg1 +(g2 +g3 +VBIOMD0000000162 +p21 +tp22 +Rp23 +(dp24 +g8 +Nsg9 +I00 +sbS'Hernjak2005_Calcium_Signaling' +p25 +sg1 +(g2 +g3 +VBIOMD0000000424 +p26 +tp27 +Rp28 +(dp29 +g8 +Nsg9 +I00 +sbS'Faratian2009_PTENrole_TrastuzumabResistance' +p30 +sg1 +(g2 +g3 +VBIOMD0000000426 +p31 +tp32 +Rp33 +(dp34 +g8 +Nsg9 +I00 +sbS'Mosca2012 - Central Carbon Metabolism Regulated by AKT' +p35 +sg1 +(g2 +g3 +VBIOMD0000000422 +p36 +tp37 +Rp38 +(dp39 +g8 +Nsg9 +I00 +sbS'Middleton2012_GibberellinSignalling' +p40 +sg1 +(g2 +g3 +VBIOMD0000000018 +p41 +tp42 +Rp43 +(dp44 +g8 +Nsg9 +I00 +sbS'Morrison1989_FolateCycle' +p45 +sg1 +(g2 +g3 +VBIOMD0000000241 +p46 +tp47 +Rp48 +(dp49 +g8 +Nsg9 +I00 +sbS'Shi1993_Caffeine_pressor_tolerance' +p50 +sg1 +(g2 +g3 +VBIOMD0000000180 +p51 +tp52 +Rp53 +(dp54 +g8 +Nsg9 +I00 +sbS'Kim2007_CellularMemory_SymmetricModel' +p55 +sg1 +(g2 +g3 +VBIOMD0000000374 +p56 +tp57 +Rp58 +(dp59 +g8 +Nsg9 +I00 +sbS'Bertram1995_PancreaticBetaCell_CRAC' +p60 +sg1 +(g2 +g3 +VBIOMD0000000269 +p61 +tp62 +Rp63 +(dp64 +g8 +Nsg9 +I00 +sbS'Liu2010_Hormonal_Crosstalk_Arabidopsis' +p65 +sg1 +(g2 +g3 +VBIOMD0000000146 +p66 +tp67 +Rp68 +(dp69 +g8 +Nsg9 +I00 +sbS'Hatakeyama2003_MAPK' +p70 +sg1 +(g2 +g3 +VBIOMD0000000380 +p71 +tp72 +Rp73 +(dp74 +g8 +Nsg9 +I00 +sbS'Smallbone2011_TrehaloseBiosynthesis' +p75 +sg1 +(g2 +g3 +VBIOMD0000000039 +p76 +tp77 +Rp78 +(dp79 +g8 +Nsg9 +I00 +sbS'Marhl2000_CaOscillations' +p80 +sg1 +(g2 +g3 +VBIOMD0000000229 +p81 +tp82 +Rp83 +(dp84 +g8 +Nsg9 +I00 +sbS'Ma2002_cAMP_oscillations' +p85 +sg1 +(g2 +g3 +VBIOMD0000000385 +p86 +tp87 +Rp88 +(dp89 +g8 +Nsg9 +I00 +sbS'Arnold2011_Schultz2003_RuBisCO-CalvinCycle' +p90 +sg1 +(g2 +g3 +VBIOMD0000000137 +p91 +tp92 +Rp93 +(dp94 +g8 +Nsg9 +I00 +sbS'Sedaghat2002_InsulinSignalling_noFeedback' +p95 +sg1 +(g2 +g3 +VBIOMD0000000387 +p96 +tp97 +Rp98 +(dp99 +g8 +Nsg9 +I00 +sbS'Arnold2011_Damour2007_RuBisCO-CalvinCycle' +p100 +sg1 +(g2 +g3 +VBIOMD0000000201 +p101 +tp102 +Rp103 +(dp104 +g8 +Nsg9 +I00 +sbS'Goldbeter2008_Somite_Segmentation_Clock_Notch_Wnt_FGF' +p105 +sg1 +(g2 +g3 +VBIOMD0000000222 +p106 +tp107 +Rp108 +(dp109 +g8 +Nsg9 +I00 +sbS'Singh2006_TCA_Ecoli_glucose' +p110 +sg1 +(g2 +g3 +VBIOMD0000000388 +p111 +tp112 +Rp113 +(dp114 +g8 +Nsg9 +I00 +sbS'Arnold2011_Zhu2009_CalvinCycle' +p115 +sg1 +(g2 +g3 +VBIOMD0000000138 +p116 +tp117 +Rp118 +(dp119 +g8 +Nsg9 +I00 +sbS'Tabak2007_dopamine' +p120 +sg1 +(g2 +g3 +VBIOMD0000000221 +p121 +tp122 +Rp123 +(dp124 +g8 +Nsg9 +I00 +sbS'Singh2006_TCA_Ecoli_acetate' +p125 +sg1 +(g2 +g3 +VBIOMD0000000037 +p126 +tp127 +Rp128 +(dp129 +g8 +Nsg9 +I00 +sbS'Marwan_Genetics_2003' +p130 +sg1 +(g2 +g3 +VBIOMD0000000053 +p131 +tp132 +Rp133 +(dp134 +g8 +Nsg9 +I00 +sbS'Ferreira2003_CML_generation2' +p135 +sg1 +(g2 +g3 +VBIOMD0000000224 +p136 +tp137 +Rp138 +(dp139 +g8 +Nsg9 +I00 +sbS'Meyer1991_CalciumSpike_ICC' +p140 +sg1 +(g2 +g3 +VBIOMD0000000225 +p141 +tp142 +Rp143 +(dp144 +g8 +Nsg9 +I00 +sbS'Westermark2003_Pancreatic_GlycOsc_basic' +p145 +sg1 +(g2 +g3 +VBIOMD0000000309 +p146 +tp147 +Rp148 +(dp149 +g8 +Nsg9 +I00 +sbS'Tyson2003_NegFB_Homeostasis' +p150 +sg1 +(g2 +g3 +VBIOMD0000000308 +p151 +tp152 +Rp153 +(dp154 +g8 +Nsg9 +I00 +sbS'Tyson2003_NegFB_Oscillator' +p155 +sg1 +(g2 +g3 +VBIOMD0000000375 +p156 +tp157 +Rp158 +(dp159 +g8 +Nsg9 +I00 +sbS'Mears1997_CRAC_PancreaticBetaCells' +p160 +sg1 +(g2 +g3 +VBIOMD0000000301 +p161 +tp162 +Rp163 +(dp164 +g8 +Nsg9 +I00 +sbS'Friedland2009_Ara_RTC3_counter' +p165 +sg1 +(g2 +g3 +VBIOMD0000000300 +p166 +tp167 +Rp168 +(dp169 +g8 +Nsg9 +I00 +sbS'Schmierer2010_FIH_Ankyrins' +p170 +sg1 +(g2 +g3 +VBIOMD0000000303 +p171 +tp172 +Rp173 +(dp174 +g8 +Nsg9 +I00 +sbS'Liu2011_Complement_System' +p175 +sg1 +(g2 +g3 +VBIOMD0000000305 +p176 +tp177 +Rp178 +(dp179 +g8 +Nsg9 +I00 +sbS'Kolomeisky2003_MyosinV_Processivity' +p180 +sg1 +(g2 +g3 +VBIOMD0000000304 +p181 +tp182 +Rp183 +(dp184 +g8 +Nsg9 +I00 +sbS'Plant1981_BurstingNerveCells' +p185 +sg1 +(g2 +g3 +VBIOMD0000000307 +p186 +tp187 +Rp188 +(dp189 +g8 +Nsg9 +I00 +sbS'Tyson2003_Substrate_Depletion_Osc' +p190 +sg1 +(g2 +g3 +VBIOMD0000000054 +p191 +tp192 +Rp193 +(dp194 +g8 +Nsg9 +I00 +sbS'Ataullahkhanov1996_Adenylate' +p195 +sg1 +(g2 +g3 +VBIOMD0000000351 +p196 +tp197 +Rp198 +(dp199 +g8 +Nsg9 +I00 +sbS'Vernoux2011_AuxinSignaling_AuxinSingleStepInput' +p200 +sg1 +(g2 +g3 +VBIOMD0000000329 +p201 +tp202 +Rp203 +(dp204 +g8 +Nsg9 +I00 +sbS'Kummer2000_CalciumSpiking' +p205 +sg1 +(g2 +g3 +VBIOMD0000000410 +p206 +tp207 +Rp208 +(dp209 +g8 +Nsg9 +I00 +sbS'Wegner2012_TGFbetaSignalling_FeedbackLoops' +p210 +sg1 +(g2 +g3 +VBIOMD0000000412 +p211 +tp212 +Rp213 +(dp214 +g8 +Nsg9 +I00 +sbS'Pokhilko2012_CircClock_RepressilatorFeedbackloop' +p215 +sg1 +(g2 +g3 +VBIOMD0000000415 +p216 +tp217 +Rp218 +(dp219 +g8 +Nsg9 +I00 +sbS'Mellor2012_LipooxygenasePathway' +p220 +sg1 +(g2 +g3 +VBIOMD0000000416 +p221 +tp222 +Rp223 +(dp224 +g8 +Nsg9 +I00 +sbS'Muraro2011_Cytokinin-Auxin_CrossRegulation' +p225 +sg1 +(g2 +g3 +VBIOMD0000000327 +p226 +tp227 +Rp228 +(dp229 +g8 +Nsg9 +I00 +sbS'Whitcomb2004_Bicarbonate_Pancreas' +p230 +sg1 +(g2 +g3 +VBIOMD0000000398 +p231 +tp232 +Rp233 +(dp234 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_NeuralStemCellDifferentiation_Crosstalk' +p235 +sg1 +(g2 +g3 +VBIOMD0000000399 +p236 +tp237 +Rp238 +(dp239 +g8 +Nsg9 +I00 +sbS'Jenkinson2011_EGF_MAPK' +p240 +sg1 +(g2 +g3 +VBIOMD0000000396 +p241 +tp242 +Rp243 +(dp244 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_NotchSignalingPathway' +p245 +sg1 +(g2 +g3 +VBIOMD0000000397 +p246 +tp247 +Rp248 +(dp249 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_WntSignalingPathway' +p250 +sg1 +(g2 +g3 +VBIOMD0000000394 +p251 +tp252 +Rp253 +(dp254 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_EGFReceptorSignalingPathway' +p255 +sg1 +(g2 +g3 +VBIOMD0000000395 +p256 +tp257 +Rp258 +(dp259 +g8 +Nsg9 +I00 +sbS'Sivakumar2011_HedgehogSignalingPathway' +p260 +sg1 +(g2 +g3 +VBIOMD0000000392 +p261 +tp262 +Rp263 +(dp264 +g8 +Nsg9 +I00 +sbS'Arnold2011_Laisk2006_CalvinCycle_Starch_Sucrose' +p265 +sg1 +(g2 +g3 +VBIOMD0000000457 +p266 +tp267 +Rp268 +(dp269 +g8 +Nsg9 +I00 +sbS'Firczuk2013 - Eukaryotic mRNA translation machinery' +p270 +sg1 +(g2 +g3 +VBIOMD0000000390 +p271 +tp272 +Rp273 +(dp274 +g8 +Nsg9 +I00 +sbS'Arnold2011_Giersch1990_CalvinCycle' +p275 +sg1 +(g2 +g3 +VBIOMD0000000391 +p276 +tp277 +Rp278 +(dp279 +g8 +Nsg9 +I00 +sbS'Arnold2011_Poolman2000_CalvinCycle_Starch' +p280 +sg1 +(g2 +g3 +VBIOMD0000000247 +p281 +tp282 +Rp283 +(dp284 +g8 +Nsg9 +I00 +sbS'Ralser2007_Carbohydrate_Rerouting_ROS' +p285 +sg1 +(g2 +g3 +VBIOMD0000000021 +p286 +tp287 +Rp288 +(dp289 +g8 +Nsg9 +I00 +sbS'Leloup1999_CircClock' +p290 +sg1 +(g2 +g3 +VBIOMD0000000022 +p291 +tp292 +Rp293 +(dp294 +g8 +Nsg9 +I00 +sbS'Ueda2001_CircClock' +p295 +sg1 +(g2 +g3 +VBIOMD0000000023 +p296 +tp297 +Rp298 +(dp299 +g8 +Nsg9 +I00 +sbS'Rohwer2001_Sucrose' +p300 +sg1 +(g2 +g3 +VBIOMD0000000024 +p301 +tp302 +Rp303 +(dp304 +g8 +Nsg9 +I00 +sbS'Scheper1999_CircClock' +p305 +sg1 +(g2 +g3 +VBIOMD0000000177 +p306 +tp307 +Rp308 +(dp309 +g8 +Nsg9 +I00 +sbS'Conant2007_glycolysis_2C' +p310 +sg1 +(g2 +g3 +VBIOMD0000000450 +p311 +tp312 +Rp313 +(dp314 +g8 +Nsg9 +I00 +sbS'Reyes-Palomares2012 - a combined model hepatic polyamine and sulfur aminoacid metabolism - version2' +p315 +sg1 +(g2 +g3 +VBIOMD0000000316 +p316 +tp317 +Rp318 +(dp319 +g8 +Nsg9 +I00 +sbS'Shen-Orr2002_FeedForward_AND_gate' +p320 +sg1 +(g2 +g3 +VBIOMD0000000317 +p321 +tp322 +Rp323 +(dp324 +g8 +Nsg9 +I00 +sbS'Shen-Orr2002_Single_Input_Module' +p325 +sg1 +(g2 +g3 +VBIOMD0000000314 +p326 +tp327 +Rp328 +(dp329 +g8 +Nsg9 +I00 +sbS'Raia2011_IL13_L1236' +p330 +sg1 +(g2 +g3 +VBIOMD0000000315 +p331 +tp332 +Rp333 +(dp334 +g8 +Nsg9 +I00 +sbS'Montagne2011_Oligator_optimised' +p335 +sg1 +(g2 +g3 +VBIOMD0000000312 +p336 +tp337 +Rp338 +(dp339 +g8 +Nsg9 +I00 +sbS'Tyson2003_Perfect_Adaption' +p340 +sg1 +(g2 +g3 +VBIOMD0000000313 +p341 +tp342 +Rp343 +(dp344 +g8 +Nsg9 +I00 +sbS'Raia2010_IL13_Signalling_MedB1' +p345 +sg1 +(g2 +g3 +VBIOMD0000000310 +p346 +tp347 +Rp348 +(dp349 +g8 +Nsg9 +I00 +sbS'Tyson2003_Mutual_Inhibition' +p350 +sg1 +(g2 +g3 +VBIOMD0000000311 +p351 +tp352 +Rp353 +(dp354 +g8 +Nsg9 +I00 +sbS'Tyson2003_Mutual_Activation' +p355 +sg1 +(g2 +g3 +VBIOMD0000000255 +p356 +tp357 +Rp358 +(dp359 +g8 +Nsg9 +I00 +sbS'Chen2009_ErbB_Signaling' +p360 +sg1 +(g2 +g3 +VBIOMD0000000254 +p361 +tp362 +Rp363 +(dp364 +g8 +Nsg9 +I00 +sbS'Bier2000_GlycolyticOscillation' +p365 +sg1 +(g2 +g3 +VBIOMD0000000253 +p366 +tp367 +Rp368 +(dp369 +g8 +Nsg9 +I00 +sbS'Teusink1998_Glycolysis_TurboDesign' +p370 +sg1 +(g2 +g3 +VBIOMD0000000252 +p371 +tp372 +Rp373 +(dp374 +g8 +Nsg9 +I00 +sbS'Hunziker2010_p53_StressSpecificResponse' +p375 +sg1 +(g2 +g3 +VBIOMD0000000406 +p376 +tp377 +Rp378 +(dp379 +g8 +Nsg9 +I00 +sbS'Moriya2011_CellCycle_FissionYeast' +p380 +sg1 +(g2 +g3 +VBIOMD0000000404 +p381 +tp382 +Rp383 +(dp384 +g8 +Nsg9 +I00 +sbS'Bray1993_chemotaxis' +p385 +sg1 +(g2 +g3 +VBIOMD0000000405 +p386 +tp387 +Rp388 +(dp389 +g8 +Nsg9 +I00 +sbS'Cookson2011_EnzymaticQueueingCoupling' +p390 +sg1 +(g2 +g3 +VBIOMD0000000400 +p391 +tp392 +Rp393 +(dp394 +g8 +Nsg9 +I00 +sbS'Cooling2007_IP3transients_CardiacMyocyte' +p395 +sg1 +(g2 +g3 +VBIOMD0000000174 +p396 +tp397 +Rp398 +(dp399 +g8 +Nsg9 +I00 +sbS'Del_Conte_Zerial2008_Rab5_Rab7_cut_out_switch' +p400 +sg1 +(g2 +g3 +VBIOMD0000000408 +p401 +tp402 +Rp403 +(dp404 +g8 +Nsg9 +I00 +sbS'Hettling2011_CreatineKinase' +p405 +sg1 +(g2 +g3 +VBIOMD0000000409 +p406 +tp407 +Rp408 +(dp409 +g8 +Nsg9 +I00 +sbS'Queralt2006_MitoticExit_Cdc55DownregulationBySeparase' +p410 +sg1 +(g2 +g3 +VBIOMD0000000354 +p411 +tp412 +Rp413 +(dp414 +g8 +Nsg9 +I00 +sbS'Abell2011_CalciumSignaling_WithoutAdaptation' +p415 +sg1 +(g2 +g3 +VBIOMD0000000476 +p416 +tp417 +Rp418 +(dp419 +g8 +Nsg9 +I00 +sbS'Adams2012 - Locke2006 Circadian Rhythm model refined with Input Signal Light Function' +p420 +sg1 +(g2 +g3 +VBIOMD0000000015 +p421 +tp422 +Rp423 +(dp424 +g8 +Nsg9 +I00 +sbS'Curto1998_purineMetabol' +p425 +sg1 +(g2 +g3 +VBIOMD0000000213 +p426 +tp427 +Rp428 +(dp429 +g8 +Nsg9 +I00 +sbS'Nijhout2004_Folate_Cycle' +p430 +sg1 +(g2 +g3 +VBIOMD0000000017 +p431 +tp432 +Rp433 +(dp434 +g8 +Nsg9 +I00 +sbS'Hoefnagel2002_PyruvateBranches' +p435 +sg1 +(g2 +g3 +VBIOMD0000000016 +p436 +tp437 +Rp438 +(dp439 +g8 +Nsg9 +I00 +sbS'Goldbeter1995_CircClock' +p440 +sg1 +(g2 +g3 +VBIOMD0000000013 +p441 +tp442 +Rp443 +(dp444 +g8 +Nsg9 +I00 +sbS'Poolman2004_CalvinCycle' +p445 +sg1 +(g2 +g3 +VBIOMD0000000065 +p446 +tp447 +Rp448 +(dp449 +g8 +Nsg9 +I00 +sbS'Yildirim2003_Lac_Operon' +p450 +sg1 +(g2 +g3 +VBIOMD0000000275 +p451 +tp452 +Rp453 +(dp454 +g8 +Nsg9 +I00 +sbS'Goldbeter2007_Somitogenesis_Switch' +p455 +sg1 +(g2 +g3 +VBIOMD0000000019 +p456 +tp457 +Rp458 +(dp459 +g8 +Nsg9 +I00 +sbS'Schoeberl2002_EGF_MAPK' +p460 +sg1 +(g2 +g3 +VBIOMD0000000211 +p461 +tp462 +Rp463 +(dp464 +g8 +Nsg9 +I00 +sbS'Albert2005_Glycolysis' +p465 +sg1 +(g2 +g3 +VBIOMD0000000144 +p466 +tp467 +Rp468 +(dp469 +g8 +Nsg9 +I00 +sbS'Calzone2007_CellCycle' +p470 +sg1 +(g2 +g3 +VBIOMD0000000099 +p471 +tp472 +Rp473 +(dp474 +g8 +Nsg9 +I00 +sbS'Laub1998_SpontaneousOscillations' +p475 +sg1 +(g2 +g3 +VBIOMD0000000098 +p476 +tp477 +Rp478 +(dp479 +g8 +Nsg9 +I00 +sbS'Goldbeter1990_CalciumSpike_CICR' +p480 +sg1 +(g2 +g3 +VBIOMD0000000152 +p481 +tp482 +Rp483 +(dp484 +g8 +Nsg9 +I00 +sbS'Fernandez2006_ModelA' +p485 +sg1 +(g2 +g3 +VBIOMD0000000153 +p486 +tp487 +Rp488 +(dp489 +g8 +Nsg9 +I00 +sbS'Fernandez2006_ModelB' +p490 +sg1 +(g2 +g3 +VBIOMD0000000095 +p491 +tp492 +Rp493 +(dp494 +g8 +Nsg9 +I00 +sbS'Zeilinger2006_PRR7-PRR9-Y' +p495 +sg1 +(g2 +g3 +VBIOMD0000000094 +p496 +tp497 +Rp498 +(dp499 +g8 +Nsg9 +I00 +sbS'Yamada2003_JAK_STAT_SOCS1_knockout' +p500 +sg1 +(g2 +g3 +VBIOMD0000000097 +p501 +tp502 +Rp503 +(dp504 +g8 +Nsg9 +I00 +sbS'Zeilinger2006_PRR7-PRR9light-Yprime' +p505 +sg1 +(g2 +g3 +VBIOMD0000000096 +p506 +tp507 +Rp508 +(dp509 +g8 +Nsg9 +I00 +sbS'Zeilinger2006_PRR7-PRR9light-Y' +p510 +sg1 +(g2 +g3 +VBIOMD0000000091 +p511 +tp512 +Rp513 +(dp514 +g8 +Nsg9 +I00 +sbS'Proctor2005 - Actions of chaperones and their role in ageing' +p515 +sg1 +(g2 +g3 +VBIOMD0000000090 +p516 +tp517 +Rp518 +(dp519 +g8 +Nsg9 +I00 +sbS'Wolf2001_Respiratory_Oscillations' +p520 +sg1 +(g2 +g3 +VBIOMD0000000093 +p521 +tp522 +Rp523 +(dp524 +g8 +Nsg9 +I00 +sbS'Yamada2003_JAK_STAT_pathway' +p525 +sg1 +(g2 +g3 +VBIOMD0000000061 +p526 +tp527 +Rp528 +(dp529 +g8 +Nsg9 +I00 +sbS'Hynne2001_Glycolysis' +p530 +sg1 +(g2 +g3 +VBIOMD0000000473 +p531 +tp532 +Rp533 +(dp534 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Yeast metabolic model with modular rate law, merged with Pritchard 2002' +p535 +sg1 +(g2 +g3 +VBIOMD0000000472 +p536 +tp537 +Rp538 +(dp539 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Yeast metabolic model with modular rate law' +p540 +sg1 +(g2 +g3 +VBIOMD0000000471 +p541 +tp542 +Rp543 +(dp544 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Yeast metabolic model with linlog rate law' +p545 +sg1 +(g2 +g3 +VBIOMD0000000470 +p546 +tp547 +Rp548 +(dp549 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - E.coli metabolic model with modular rate law' +p550 +sg1 +(g2 +g3 +VBIOMD0000000215 +p551 +tp552 +Rp553 +(dp554 +g8 +Nsg9 +I00 +sbS'Schulz2009_Th1_differentiation' +p555 +sg1 +(g2 +g3 +VBIOMD0000000172 +p556 +tp557 +Rp558 +(dp559 +g8 +Nsg9 +I00 +sbS'Pritchard2002_glycolysis' +p560 +sg1 +(g2 +g3 +VBIOMD0000000214 +p561 +tp562 +Rp563 +(dp564 +g8 +Nsg9 +I00 +sbS'Akman2008_Circadian_Clock_Model2' +p565 +sg1 +(g2 +g3 +VBIOMD0000000383 +p566 +tp567 +Rp568 +(dp569 +g8 +Nsg9 +I00 +sbS'Arnold2011_Farquhar1980_RuBisCO-CalvinCycle' +p570 +sg1 +(g2 +g3 +VBIOMD0000000393 +p571 +tp572 +Rp573 +(dp574 +g8 +Nsg9 +I00 +sbS'Arnold2011_Zhu2007_CalvinCycle_Starch_Sucrose_Photorespiration' +p575 +sg1 +(g2 +g3 +VBIOMD0000000326 +p576 +tp577 +Rp578 +(dp579 +g8 +Nsg9 +I00 +sbS'DellOrco2009_phototransduction' +p580 +sg1 +(g2 +g3 +VBIOMD0000000038 +p581 +tp582 +Rp583 +(dp584 +g8 +Nsg9 +I00 +sbS'Rohwer2000_Phosphotransferase_System' +p585 +sg1 +(g2 +g3 +VBIOMD0000000458 +p586 +tp587 +Rp588 +(dp589 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - Serine biosynthesis' +p590 +sg1 +(g2 +g3 +VBIOMD0000000384 +p591 +tp592 +Rp593 +(dp594 +g8 +Nsg9 +I00 +sbS'Arnold2011_Medlyn2002_RuBisCO-CalvinCycle' +p595 +sg1 +(g2 +g3 +VBIOMD0000000002 +p596 +tp597 +Rp598 +(dp599 +g8 +Nsg9 +I00 +sbS'Edelstein1996 - EPSP ACh species' +p600 +sg1 +(g2 +g3 +VBIOMD0000000218 +p601 +tp602 +Rp603 +(dp604 +g8 +Nsg9 +I00 +sbS'Singh2006_TCA_mtu_model2' +p605 +sg1 +(g2 +g3 +VBIOMD0000000488 +p606 +tp607 +Rp608 +(dp609 +g8 +Nsg9 +I00 +sbS"Proctor2013 - Effect of A\xce\xb2 immunisation in Alzheimer's disease" +p610 +sg1 +(g2 +g3 +VBIOMD0000000122 +p611 +tp612 +Rp613 +(dp614 +g8 +Nsg9 +I00 +sbS'Fisher2006_Ca_Oscillation_dpdnt_NFAT_dynamics' +p615 +sg1 +(g2 +g3 +VBIOMD0000000386 +p616 +tp617 +Rp618 +(dp619 +g8 +Nsg9 +I00 +sbS'Arnold2011_Sharkey2007_RuBisCO-CalvinCycle' +p620 +sg1 +(g2 +g3 +VBIOMD0000000482 +p621 +tp622 +Rp623 +(dp624 +g8 +Nsg9 +I00 +sbS'Noguchi2013 - Insulin dependent glucose metabolism' +p625 +sg1 +(g2 +g3 +VBIOMD0000000161 +p626 +tp627 +Rp628 +(dp629 +g8 +Nsg9 +I00 +sbS'Eungdamrong2007_Ras_Activation' +p630 +sg1 +(g2 +g3 +VBIOMD0000000389 +p631 +tp632 +Rp633 +(dp634 +g8 +Nsg9 +I00 +sbS'Arnold2011_Hahn1986_CalvinCycle_Starch_Sucrose' +p635 +sg1 +(g2 +g3 +VBIOMD0000000088 +p636 +tp637 +Rp638 +(dp639 +g8 +Nsg9 +I00 +sbS'Maeda2006_MyosinPhosphorylation' +p640 +sg1 +(g2 +g3 +VBIOMD0000000089 +p641 +tp642 +Rp643 +(dp644 +g8 +Nsg9 +I00 +sbS'Locke2006_CircClock_LL' +p645 +sg1 +(g2 +g3 +VBIOMD0000000165 +p646 +tp647 +Rp648 +(dp649 +g8 +Nsg9 +I00 +sbS'Saucerman2006_PKA' +p650 +sg1 +(g2 +g3 +VBIOMD0000000164 +p651 +tp652 +Rp653 +(dp654 +g8 +Nsg9 +I00 +sbS'SmithAE2002_RanTransport' +p655 +sg1 +(g2 +g3 +VBIOMD0000000376 +p656 +tp657 +Rp658 +(dp659 +g8 +Nsg9 +I00 +sbS'Bertram2007_IsletCell_Oscillations' +p660 +sg1 +(g2 +g3 +VBIOMD0000000166 +p661 +tp662 +Rp663 +(dp664 +g8 +Nsg9 +I00 +sbS'Zhu2007_TF_modulated_by_Calcium' +p665 +sg1 +(g2 +g3 +VBIOMD0000000082 +p666 +tp667 +Rp668 +(dp669 +g8 +Nsg9 +I00 +sbS'Thomsen1988_AdenylateCyclase_Inhibition' +p670 +sg1 +(g2 +g3 +VBIOMD0000000083 +p671 +tp672 +Rp673 +(dp674 +g8 +Nsg9 +I00 +sbS'Leloup2003_CircClock_LD_REV-ERBalpha' +p675 +sg1 +(g2 +g3 +VBIOMD0000000080 +p676 +tp677 +Rp678 +(dp679 +g8 +Nsg9 +I00 +sbS'Thomsen1989_AdenylateCyclase' +p680 +sg1 +(g2 +g3 +VBIOMD0000000081 +p681 +tp682 +Rp683 +(dp684 +g8 +Nsg9 +I00 +sbS'Suh2004_KCNQ_Regulation' +p685 +sg1 +(g2 +g3 +VBIOMD0000000086 +p686 +tp687 +Rp688 +(dp689 +g8 +Nsg9 +I00 +sbS'Bornheimer2004_GTPaseCycle' +p690 +sg1 +(g2 +g3 +VBIOMD0000000087 +p691 +tp692 +Rp693 +(dp694 +g8 +Nsg9 +I00 +sbS'Proctor2006_telomere' +p695 +sg1 +(g2 +g3 +VBIOMD0000000277 +p696 +tp697 +Rp698 +(dp699 +g8 +Nsg9 +I00 +sbS'Shrestha2010_HyperCalcemia_PTHresponse' +p700 +sg1 +(g2 +g3 +VBIOMD0000000085 +p701 +tp702 +Rp703 +(dp704 +g8 +Nsg9 +I00 +sbS'Maurya2005_GTPaseCycle_reducedOrder' +p705 +sg1 +(g2 +g3 +VBIOMD0000000460 +p706 +tp707 +Rp708 +(dp709 +g8 +Nsg9 +I00 +sbS'Liebal2012 - B.subtilis sigB proteolysis model' +p710 +sg1 +(g2 +g3 +VBIOMD0000000461 +p711 +tp712 +Rp713 +(dp714 +g8 +Nsg9 +I00 +sbS'Liebal2012 - B.subtilis transcription inhibition model' +p715 +sg1 +(g2 +g3 +VBIOMD0000000462 +p716 +tp717 +Rp718 +(dp719 +g8 +Nsg9 +I00 +sbS'Proctor2012 - Amyloid-beta aggregation' +p720 +sg1 +(g2 +g3 +VBIOMD0000000248 +p721 +tp722 +Rp723 +(dp724 +g8 +Nsg9 +I00 +sbS'Lai2007_O2_Transport_Metabolism' +p725 +sg1 +(g2 +g3 +VBIOMD0000000464 +p726 +tp727 +Rp728 +(dp729 +g8 +Nsg9 +I00 +sbS'Koo2013 - Shear stress induced calcium influx and eNOS activation - Model 1' +p730 +sg1 +(g2 +g3 +VBIOMD0000000465 +p731 +tp732 +Rp733 +(dp734 +g8 +Nsg9 +I00 +sbS'Koo2013 - Shear stress induced AKT and eNOS phosphorylation - Model 2' +p735 +sg1 +(g2 +g3 +VBIOMD0000000466 +p736 +tp737 +Rp738 +(dp739 +g8 +Nsg9 +I00 +sbS'Koo2013 - Shear stress induced eNOS expression - Model 3' +p740 +sg1 +(g2 +g3 +VBIOMD0000000467 +p741 +tp742 +Rp743 +(dp744 +g8 +Nsg9 +I00 +sbS'Koo2013 - Shear stress induced NO production - Model 4' +p745 +sg1 +(g2 +g3 +VBIOMD0000000468 +p746 +tp747 +Rp748 +(dp749 +g8 +Nsg9 +I00 +sbS'Koo2013 - Integrated shear stress induced NO production model' +p750 +sg1 +(g2 +g3 +VBIOMD0000000469 +p751 +tp752 +Rp753 +(dp754 +g8 +Nsg9 +I00 +sbS'Smallbone2013 - E.coli metabolic model with linlog rate law' +p755 +sg1 +(g2 +g3 +VBIOMD0000000189 +p756 +tp757 +Rp758 +(dp759 +g8 +Nsg9 +I00 +sbS'Proctor2008_p53_Mdm2_ARF' +p760 +sg1 +(g2 +g3 +VBIOMD0000000188 +p761 +tp762 +Rp763 +(dp764 +g8 +Nsg9 +I00 +sbS'Proctor2008_p53_Mdm2_ATM' +p765 +sg1 +(g2 +g3 +VBIOMD0000000035 +p766 +tp767 +Rp768 +(dp769 +g8 +Nsg9 +I00 +sbS'Vilar2002_Oscillator' +p770 +sg1 +(g2 +g3 +VBIOMD0000000077 +p771 +tp772 +Rp773 +(dp774 +g8 +Nsg9 +I00 +sbS'Blum2000_LHsecretion_1' +p775 +sg1 +(g2 +g3 +VBIOMD0000000349 +p776 +tp777 +Rp778 +(dp779 +g8 +Nsg9 +I00 +sbS'Fridlyand2010_GlucoseSensitivity_B' +p780 +sg1 +(g2 +g3 +VBIOMD0000000348 +p781 +tp782 +Rp783 +(dp784 +g8 +Nsg9 +I00 +sbS'Fridlyand2010_GlucoseSensitivity_A' +p785 +sg1 +(g2 +g3 +VBIOMD0000000179 +p786 +tp787 +Rp788 +(dp789 +g8 +Nsg9 +I00 +sbS'Kim2007_CellularMemory_AsymmetricModel' +p790 +sg1 +(g2 +g3 +VBIOMD0000000176 +p791 +tp792 +Rp793 +(dp794 +g8 +Nsg9 +I00 +sbS'Conant2007_WGD_glycolysis_2A3AB' +p795 +sg1 +(g2 +g3 +VBIOMD0000000344 +p796 +tp797 +Rp798 +(dp799 +g8 +Nsg9 +I00 +sbS'Proctor2011_ProteinHomeostasis_NormalCondition' +p800 +sg1 +(g2 +g3 +VBIOMD0000000347 +p801 +tp802 +Rp803 +(dp804 +g8 +Nsg9 +I00 +sbS'Bachmann2011_JAK2-STAT5_FeedbackControl' +p805 +sg1 +(g2 +g3 +VBIOMD0000000175 +p806 +tp807 +Rp808 +(dp809 +g8 +Nsg9 +I00 +sbS'Birtwistle2007_ErbB_Signalling' +p810 +sg1 +(g2 +g3 +VBIOMD0000000341 +p811 +tp812 +Rp813 +(dp814 +g8 +Nsg9 +I00 +sbS'Topp2000_BetaCellMass_Diabetes' +p815 +sg1 +(g2 +g3 +VBIOMD0000000340 +p816 +tp817 +Rp818 +(dp819 +g8 +Nsg9 +I00 +sbS'Wajima2009_BloodCoagulation_warfarin_heparin' +p820 +sg1 +(g2 +g3 +VBIOMD0000000343 +p821 +tp822 +Rp823 +(dp824 +g8 +Nsg9 +I00 +sbS'Brannmark2010_InsulinSignalling_Mifamodel' +p825 +sg1 +(g2 +g3 +VBIOMD0000000171 +p826 +tp827 +Rp828 +(dp829 +g8 +Nsg9 +I00 +sbS'Leloup1998_CircClock_LD' +p830 +sg1 +(g2 +g3 +VBIOMD0000000266 +p831 +tp832 +Rp833 +(dp834 +g8 +Nsg9 +I00 +sbS'Voit2003_Trehalose_Cycle' +p835 +sg1 +(g2 +g3 +VBIOMD0000000076 +p836 +tp837 +Rp838 +(dp839 +g8 +Nsg9 +I00 +sbS'Cronwright2002_Glycerol_Synthesis' +p840 +sg1 +(g2 +g3 +VBIOMD0000000264 +p841 +tp842 +Rp843 +(dp844 +g8 +Nsg9 +I00 +sbS'Fujita2010_Akt_Signalling_EGFRinhib' +p845 +sg1 +(g2 +g3 +VBIOMD0000000074 +p846 +tp847 +Rp848 +(dp849 +g8 +Nsg9 +I00 +sbS'Leloup2003_CircClock_DD_REV-ERBalpha' +p850 +sg1 +(g2 +g3 +VBIOMD0000000073 +p851 +tp852 +Rp853 +(dp854 +g8 +Nsg9 +I00 +sbS'Leloup2003_CircClock_DD' +p855 +sg1 +(g2 +g3 +VBIOMD0000000072 +p856 +tp857 +Rp858 +(dp859 +g8 +Nsg9 +I00 +sbS'Yi2003_GproteinCycle' +p860 +sg1 +(g2 +g3 +VBIOMD0000000071 +p861 +tp862 +Rp863 +(dp864 +g8 +Nsg9 +I00 +sbS'Bakker2001_Glycolysis' +p865 +sg1 +(g2 +g3 +VBIOMD0000000070 +p866 +tp867 +Rp868 +(dp869 +g8 +Nsg9 +I00 +sbS'Holzhutter2004_Erythrocyte_Metabolism' +p870 +sg1 +(g2 +g3 +VBIOMD0000000182 +p871 +tp872 +Rp873 +(dp874 +g8 +Nsg9 +I00 +sbS'Neves2008 - Role of cell shape and size in controlling intracellular signalling' +p875 +sg1 +(g2 +g3 +VBIOMD0000000268 +p876 +tp877 +Rp878 +(dp879 +g8 +Nsg9 +I00 +sbS'Reed2008_Glutathione_Metabolism' +p880 +sg1 +(g2 +g3 +VBIOMD0000000078 +p881 +tp882 +Rp883 +(dp884 +g8 +Nsg9 +I00 +sbS'Leloup2003_CircClock_LD' +p885 +sg1 +(g2 +g3 +VBIOMD0000000190 +p886 +tp887 +Rp888 +(dp889 +g8 +Nsg9 +I00 +sbS'Rodriguez-Caso2006_Polyamine_Metabolism' +p890 +sg1 +(g2 +g3 +VBIOMD0000000191 +p891 +tp892 +Rp893 +(dp894 +g8 +Nsg9 +I00 +sbS'Monta\xc3\xb1ez2008_Arginine_catabolism' +p895 +sg1 +(g2 +g3 +VBIOMD0000000192 +p896 +tp897 +Rp898 +(dp899 +g8 +Nsg9 +I00 +sbS'G\xc3\xb6rlich2003_RanGTP_gradient' +p900 +sg1 +(g2 +g3 +VBIOMD0000000260 +p901 +tp902 +Rp903 +(dp904 +g8 +Nsg9 +I00 +sbS'Tiago2010_FeMetabolism_FeAdequate' +p905 +sg1 +(g2 +g3 +VBIOMD0000000198 +p906 +tp907 +Rp908 +(dp909 +g8 +Nsg9 +I00 +sbS'Stone1996_NOsGC' +p910 +sg1 +(g2 +g3 +VBIOMD0000000199 +p911 +tp912 +Rp913 +(dp914 +g8 +Nsg9 +I00 +sbS'Santolini2001_nNOS_Mechanism_Regulation' +p915 +sg1 +(g2 +g3 +VBIOMD0000000261 +p916 +tp917 +Rp918 +(dp919 +g8 +Nsg9 +I00 +sbS'Tiago2010_FeMetabolism_FeLoaded' +p920 +sg1 +(g2 +g3 +VBIOMD0000000143 +p921 +tp922 +Rp923 +(dp924 +g8 +Nsg9 +I00 +sbS'Olsen2003_neutrophil_oscillatory_metabolism' +p925 +sg1 +(g2 +g3 +VBIOMD0000000299 +p926 +tp927 +Rp928 +(dp929 +g8 +Nsg9 +I00 +sbS'Leloup1999_CircadianRhythms_Neurospora' +p930 +sg1 +(g2 +g3 +VBIOMD0000000298 +p931 +tp932 +Rp933 +(dp934 +g8 +Nsg9 +I00 +sbS'Leloup1999_CircadianRhythms_Drosophila' +p935 +sg1 +(g2 +g3 +VBIOMD0000000293 +p936 +tp937 +Rp938 +(dp939 +g8 +Nsg9 +I00 +sbS'Proctor2010_UCHL1_ProteinAggregation' +p940 +sg1 +(g2 +g3 +VBIOMD0000000292 +p941 +tp942 +Rp943 +(dp944 +g8 +Nsg9 +I00 +sbS'Rovers1995_Photsynthetic_Oscillations' +p945 +sg1 +(g2 +g3 +VBIOMD0000000291 +p946 +tp947 +Rp948 +(dp949 +g8 +Nsg9 +I00 +sbS'Nikolaev2005_AlbuminBilirubinAdsorption' +p950 +sg1 +(g2 +g3 +VBIOMD0000000055 +p951 +tp952 +Rp953 +(dp954 +g8 +Nsg9 +I00 +sbS'Locke2005 - Circadian Clock' +p955 +sg1 +(g2 +g3 +VBIOMD0000000170 +p956 +tp957 +Rp958 +(dp959 +g8 +Nsg9 +I00 +sbS'Weimann2004_CircadianOscillator' +p960 +sg1 +(g2 +g3 +VBIOMD0000000244 +p961 +tp962 +Rp963 +(dp964 +g8 +Nsg9 +I00 +sbS'Kotte2010_Ecoli_Metabolic_Adaption' +p965 +sg1 +(g2 +g3 +VBIOMD0000000108 +p966 +tp967 +Rp968 +(dp969 +g8 +Nsg9 +I00 +sbS'Kowald2006_SOD' +p970 +sg1 +(g2 +g3 +VBIOMD0000000453 +p971 +tp972 +Rp973 +(dp974 +g8 +Nsg9 +I00 +sbS'Bidkhori2012 - EGFR signalling in NSCLC' +p975 +sg1 +(g2 +g3 +VBIOMD0000000352 +p976 +tp977 +Rp978 +(dp979 +g8 +Nsg9 +I00 +sbS'Vernoux2011_AuxinSignaling_AuxinFluctuating' +p980 +sg1 +(g2 +g3 +VBIOMD0000000353 +p981 +tp982 +Rp983 +(dp984 +g8 +Nsg9 +I00 +sbS'Nag2011_ChloroplasticStarchDegradation' +p985 +sg1 +(g2 +g3 +VBIOMD0000000350 +p986 +tp987 +Rp988 +(dp989 +g8 +Nsg9 +I00 +sbS'Troein2011_ClockCircuit_OstreococcusTauri' +p990 +sg1 +(g2 +g3 +VBIOMD0000000100 +p991 +tp992 +Rp993 +(dp994 +g8 +Nsg9 +I00 +sbS'Rozi2003_GlycogenPhosphorylase_Activation' +p995 +sg1 +(g2 +g3 +VBIOMD0000000356 +p996 +tp997 +Rp998 +(dp999 +g8 +Nsg9 +I00 +sbS'Nyman2011_M3Hierarachical_InsulinGlucosedynamics' +p1000 +sg1 +(g2 +g3 +VBIOMD0000000106 +p1001 +tp1002 +Rp1003 +(dp1004 +g8 +Nsg9 +I00 +sbS'Yang2007_ArachidonicAcid' +p1005 +sg1 +(g2 +g3 +VBIOMD0000000105 +p1006 +tp1007 +Rp1008 +(dp1009 +g8 +Nsg9 +I00 +sbS'Proctor2007_ubiquitine' +p1010 +sg1 +(g2 +g3 +VBIOMD0000000355 +p1011 +tp1012 +Rp1013 +(dp1014 +g8 +Nsg9 +I00 +sbS'Abell2011_CalciumSignaling_WithAdaptation' +p1015 +sg1 +(g2 +g3 +VBIOMD0000000064 +p1016 +tp1017 +Rp1018 +(dp1019 +g8 +Nsg9 +I00 +sbS'Teusink2000_Glycolysis' +p1020 +sg1 +(g2 +g3 +VBIOMD0000000212 +p1021 +tp1022 +Rp1023 +(dp1024 +g8 +Nsg9 +I00 +sbS'Curien2009_Aspartate_Metabolism' +p1025 +sg1 +(g2 +g3 +VBIOMD0000000066 +p1026 +tp1027 +Rp1028 +(dp1029 +g8 +Nsg9 +I00 +sbS'Chassagnole2001_Threonine Synthesis' +p1030 +sg1 +(g2 +g3 +VBIOMD0000000067 +p1031 +tp1032 +Rp1033 +(dp1034 +g8 +Nsg9 +I00 +sbS'Fung2005_Metabolic_Oscillator' +p1035 +sg1 +(g2 +g3 +VBIOMD0000000217 +p1036 +tp1037 +Rp1038 +(dp1039 +g8 +Nsg9 +I00 +sbS'Bruggeman2005_AmmoniumAssimilation' +p1040 +sg1 +(g2 +g3 +VBIOMD0000000216 +p1041 +tp1042 +Rp1043 +(dp1044 +g8 +Nsg9 +I00 +sbS'Hong2009_CircadianClock' +p1045 +sg1 +(g2 +g3 +VBIOMD0000000062 +p1046 +tp1047 +Rp1048 +(dp1049 +g8 +Nsg9 +I00 +sbS'Bhartiya2003_Tryptophan_operon' +p1050 +sg1 +(g2 +g3 +VBIOMD0000000063 +p1051 +tp1052 +Rp1053 +(dp1054 +g8 +Nsg9 +I00 +sbS'Galazzo1990_FermentationPathwayKinetics' +p1055 +sg1 +(g2 +g3 +VBIOMD0000000219 +p1056 +tp1057 +Rp1058 +(dp1059 +g8 +Nsg9 +I00 +sbS'Singh2006_TCA_mtu_model1' +p1060 +sg1 +(g2 +g3 +VBIOMD0000000306 +p1061 +tp1062 +Rp1063 +(dp1064 +g8 +Nsg9 +I00 +sbS'Tyson2003_Activator_Inhibitor' +p1065 +sg1 +(g2 +g3 +VBIOMD0000000068 +p1066 +tp1067 +Rp1068 +(dp1069 +g8 +Nsg9 +I00 +sbS'Curien2003_MetThr_synthesis' +p1070 +sg1 +(g2 +g3 +VBIOMD0000000045 +p1071 +tp1072 +Rp1073 +(dp1074 +g8 +Nsg9 +I00 +sbS'Borghans1997 - Calcium Oscillation - Model 3' +p1075 +sg1 +(g2 +g3 +VBIOMD0000000452 +p1076 +tp1077 +Rp1078 +(dp1079 +g8 +Nsg9 +I00 +sbS'Bidkhori2012 - normal EGFR signalling' +p1080 +sg1 +(g2 +g3 +VBIOMD0000000231 +p1081 +tp1082 +Rp1083 +(dp1084 +g8 +Nsg9 +I00 +sbS'Valero2006_Adenine_TernaryCycle' +p1085 +sg1 +(g2 +g3 +VBIOMD0000000128 +p1086 +tp1087 +Rp1088 +(dp1089 +g8 +Nsg9 +I00 +sbS'Bertram2006_Endothelin' +p1090 +sg1 +(g2 +g3 +VBIOMD0000000145 +p1091 +tp1092 +Rp1093 +(dp1094 +g8 +Nsg9 +I00 +sbS'Wang2007_ATP_induced_Ca_Oscillation' +p1095 +sg1 +(g2 +g3 +VBIOMD0000000296 +p1096 +tp1097 +Rp1098 +(dp1099 +g8 +Nsg9 +I00 +sbS'Balagadd\xc3\xa92008_E_coli_Predator_Prey' +p1100 +sg1 +(g2 +g3 +VBIOMD0000000281 +p1101 +tp1102 +Rp1103 +(dp1104 +g8 +Nsg9 +I00 +sbS'Chance1960_Glycolysis_Respiration' +p1105 +sg1 +(g2 +g3 +VBIOMD0000000245 +p1106 +tp1107 +Rp1108 +(dp1109 +g8 +Nsg9 +I00 +sbS'Lei2001_Yeast_Aerobic_Metabolism' +p1110 +sg1 +(g2 +g3 +VBIOMD0000000282 +p1111 +tp1112 +Rp1113 +(dp1114 +g8 +Nsg9 +I00 +sbS'Chance1952_Catalase_Mechanism' +p1115 +sg1 +(g2 +g3 +VBIOMD0000000232 +p1116 +tp1117 +Rp1118 +(dp1119 +g8 +Nsg9 +I00 +sbS'Nazaret2009_TCA_RC_ATP' +p1120 +sg1 +(g2 +g3 +VBIOMD0000000286 +p1121 +tp1122 +Rp1123 +(dp1124 +g8 +Nsg9 +I00 +sbS'Proctor2010_GSK3_p53_AlzheimerDisease' +p1125 +sg1 +(g2 +g3 +VBIOMD0000000287 +p1126 +tp1127 +Rp1128 +(dp1129 +g8 +Nsg9 +I00 +sbS'Passos2010_DNAdamage_CellularSenescence' +p1130 +sg1 +(g2 +g3 +VBIOMD0000000119 +p1131 +tp1132 +Rp1133 +(dp1134 +g8 +Nsg9 +I00 +sbS'Golomb2006_SomaticBursting_nonzero[Ca]' +p1135 +sg1 +(g2 +g3 +VBIOMD0000000283 +p1136 +tp1137 +Rp1138 +(dp1139 +g8 +Nsg9 +I00 +sbS'Chance1943_Peroxidase_ES_Kinetics' +p1140 +sg1 +(g2 +g3 +VBIOMD0000000112 +p1141 +tp1142 +Rp1143 +(dp1144 +g8 +Nsg9 +I00 +sbS'Clarke2006_Smad_signalling' +p1145 +sg1 +(g2 +g3 +VBIOMD0000000113 +p1146 +tp1147 +Rp1148 +(dp1149 +g8 +Nsg9 +I00 +sbS'Dupont1992_Ca_dpt_protein_phospho' +p1150 +sg1 +(g2 +g3 +VBIOMD0000000114 +p1151 +tp1152 +Rp1153 +(dp1154 +g8 +Nsg9 +I00 +sbS'Somogyi1990_CaOscillations' +p1155 +sg1 +(g2 +g3 +VBIOMD0000000115 +p1156 +tp1157 +Rp1158 +(dp1159 +g8 +Nsg9 +I00 +sbS'Somogyi1990_CaOscillations_SingleCaSpike' +p1160 +sg1 +(g2 +g3 +VBIOMD0000000117 +p1161 +tp1162 +Rp1163 +(dp1164 +g8 +Nsg9 +I00 +sbS'Dupont1991_CaOscillation' +p1165 +sg1 +(g2 +g3 +VBIOMD0000000051 +p1166 +tp1167 +Rp1168 +(dp1169 +g8 +Nsg9 +I00 +sbS'Chassagnole2002_Carbon_Metabolism' +p1170 +sg1 +(g2 +g3 +VBIOMD0000000050 +p1171 +tp1172 +Rp1173 +(dp1174 +g8 +Nsg9 +I00 +sbS'Martins2003_AmadoriDegradation' +p1175 +sg1 +(g2 +g3 +VBIOMD0000000202 +p1176 +tp1177 +Rp1178 +(dp1179 +g8 +Nsg9 +I00 +sbS'ChenXF2008_CICR' +p1180 +sg1 +(g2 +g3 +VBIOMD0000000052 +p1181 +tp1182 +Rp1183 +(dp1184 +g8 +Nsg9 +I00 +sbS'Brands2002 - Monosaccharide-casein systems' +p1185 +sg1 +(g2 +g3 +VBIOMD0000000459 +p1186 +tp1187 +Rp1188 +(dp1189 +g8 +Nsg9 +I00 +sbS'Liebal2012 - B.subtilis post-transcriptional instability model' +p1190 +sg1 +(g2 +g3 +VBIOMD0000000205 +p1191 +tp1192 +Rp1193 +(dp1194 +g8 +Nsg9 +I00 +sbS'Ung2008_EGFR_Endocytosis' +p1195 +sg1 +(g2 +g3 +VBIOMD0000000206 +p1196 +tp1197 +Rp1198 +(dp1199 +g8 +Nsg9 +I00 +sbS'Wolf2000_Glycolytic_Oscillations' +p1200 +sg1 +(g2 +g3 +VBIOMD0000000328 +p1201 +tp1202 +Rp1203 +(dp1204 +g8 +Nsg9 +I00 +sbS'Bucher2011_Atorvastatin_Metabolism' +p1205 +sg1 +(g2 +g3 +VBIOMD0000000059 +p1206 +tp1207 +Rp1208 +(dp1209 +g8 +Nsg9 +I00 +sbS'Fridlyand2003_Calcium_flux' +p1210 +sg1 +(g2 +g3 +VBIOMD0000000058 +p1211 +tp1212 +Rp1213 +(dp1214 +g8 +Nsg9 +I00 +sbS'Bindschadler2001_coupled_Ca_oscillators' +p1215 +sg1 +(g2 +g3 +VBIOMD0000000325 +p1216 +tp1217 +Rp1218 +(dp1219 +g8 +Nsg9 +I00 +sbS'Palini2011_Minimal_2_Feedback_Model' +p1220 +sg1 +(g2 +g3 +VBIOMD0000000323 +p1221 +tp1222 +Rp1223 +(dp1224 +g8 +Nsg9 +I00 +sbS'Kim2011_Oscillator_SimpleIII' +p1225 +sg1 +(g2 +g3 +VBIOMD0000000322 +p1226 +tp1227 +Rp1228 +(dp1229 +g8 +Nsg9 +I00 +sbS'Kim2011_Oscillator_SimpleI' +p1230 +sg1 +(g2 +g3 +VBIOMD0000000321 +p1231 +tp1232 +Rp1233 +(dp1234 +g8 +Nsg9 +I00 +sbS'Grange2001 - L Dopa PK model' +p1235 +sg1 +(g2 +g3 +VBIOMD0000000320 +p1236 +tp1237 +Rp1238 +(dp1239 +g8 +Nsg9 +I00 +sbS'Grange2001 - PK interaction of L-dopa and benserazide' +p1240 +sg1 +(g2 +g3 +VBIOMD0000000438 +p1241 +tp1242 +Rp1243 +(dp1244 +g8 +Nsg9 +I00 +sbS'Saeidi2012 - Quorum sensing device that produces GFP' +p1245 +sg1 +(g2 +g3 +VBIOMD0000000437 +p1246 +tp1247 +Rp1248 +(dp1249 +g8 +Nsg9 +I00 +sbS'Tseng2012 - Circadian clock of N.crassa' +p1250 +sg1 +(g2 +g3 +VBIOMD0000000436 +p1251 +tp1252 +Rp1253 +(dp1254 +g8 +Nsg9 +I00 +sbS'Gupta2009 - Eicosanoid Metabolism' +p1255 +sg1 +(g2 +g3 +VBIOMD0000000434 +p1256 +tp1257 +Rp1258 +(dp1259 +g8 +Nsg9 +I00 +sbS'McAuley2012 - Whole-body Cholesterol Metabolism' +p1260 +sg1 +(g2 +g3 +VBIOMD0000000236 +p1261 +tp1262 +Rp1263 +(dp1264 +g8 +Nsg9 +I00 +sbS'Westermark2003_Pancreatic_GlycOsc_extended' +p1265 +sg1 +(g2 +g3 +VBIOMD0000000259 +p1266 +tp1267 +Rp1268 +(dp1269 +g8 +Nsg9 +I00 +sbS'Tiago2010_FeMetabolism_FeDeficient' +p1270 +sg1 +(g2 +g3 +VBIOMD0000000378 +p1271 +tp1272 +Rp1273 +(dp1274 +g8 +Nsg9 +I00 +sbS'Chay1997_CalciumConcentration' +p1275 +sg1 +(g2 +g3 +VBIOMD0000000185 +p1276 +tp1277 +Rp1278 +(dp1279 +g8 +Nsg9 +I00 +sbS'Locke2008_Circadian_Clock' +p1280 +sg1 +(g2 +g3 +VBIOMD0000000246 +p1281 +tp1282 +Rp1283 +(dp1284 +g8 +Nsg9 +I00 +sbS'Vasalou2010_Pacemaker_Neuron_SCN' +p1285 +sg1 +(g2 +g3 +VBIOMD0000000379 +p1286 +tp1287 +Rp1288 +(dp1289 +g8 +Nsg9 +I00 +sbS'DallaMan2007_MealModel_GlucoseInsulinSystem' +p1290 +sg1 +(g2 +g3 +VBIOMD0000000372 +p1291 +tp1292 +Rp1293 +(dp1294 +g8 +Nsg9 +I00 +sbS'Tolic2000_InsulinGlucoseFeedback' +p1295 +sg1 +(g2 +g3 +VBIOMD0000000273 +p1296 +tp1297 +Rp1298 +(dp1299 +g8 +Nsg9 +I00 +sbS'Pokhilko2010_CircClock' +p1300 +sg1 +(g2 +g3 +VBIOMD0000000124 +p1301 +tp1302 +Rp1303 +(dp1304 +g8 +Nsg9 +I00 +sbS'Wu2006_K+Channel' +p1305 +sg1 +(g2 +g3 +VBIOMD0000000239 +p1306 +tp1307 +Rp1308 +(dp1309 +g8 +Nsg9 +I00 +sbS'Jiang2007 - GSIS system, Pancreatic Beta Cells' +p1310 +sg1 +(g2 +g3 +VBIOMD0000000123 +p1311 +tp1312 +Rp1313 +(dp1314 +g8 +Nsg9 +I00 +sbS'Fisher2006_NFAT_Activation' +p1315 +sg1 +(g2 +g3 +VBIOMD0000000049 +p1316 +tp1317 +Rp1318 +(dp1319 +g8 +Nsg9 +I00 +sbS'Sasagawa2005_MAPK' +p1320 +sg1 +(g2 +g3 +VBIOMD0000000046 +p1321 +tp1322 +Rp1323 +(dp1324 +g8 +Nsg9 +I00 +sbS'Olsen2003_peroxidase' +p1325 +sg1 +(g2 +g3 +VBIOMD0000000047 +p1326 +tp1327 +Rp1328 +(dp1329 +g8 +Nsg9 +I00 +sbS'Oxhamre2005_Ca_oscillation' +p1330 +sg1 +(g2 +g3 +VBIOMD0000000044 +p1331 +tp1332 +Rp1333 +(dp1334 +g8 +Nsg9 +I00 +sbS'Borghans1997 - Calcium Oscillation - Model 2' +p1335 +sg1 +(g2 +g3 +VBIOMD0000000012 +p1336 +tp1337 +Rp1338 +(dp1339 +g8 +Nsg9 +I00 +sbS'Elowitz2000 - Repressilator' +p1340 +sg1 +(g2 +g3 +VBIOMD0000000042 +p1341 +tp1342 +Rp1343 +(dp1344 +g8 +Nsg9 +I00 +sbS'Nielsen1998_Glycolysis' +p1345 +sg1 +(g2 +g3 +VBIOMD0000000043 +p1346 +tp1347 +Rp1348 +(dp1349 +g8 +Nsg9 +I00 +sbS'Borghans1997 - Calcium Oscillation - Model 1' +p1350 +sg1 +(g2 +g3 +VBIOMD0000000040 +p1351 +tp1352 +Rp1353 +(dp1354 +g8 +Nsg9 +I00 +sbS'Field1974_Oregonator' +p1355 +sg1 +(g2 +g3 +VBIOMD0000000041 +p1356 +tp1357 +Rp1358 +(dp1359 +g8 +Nsg9 +I00 +sbS'Kongas2007 - Creatine Kinase in energy metabolic signaling in muscle' +p1360 +sg1 +(g2 +g3 +VBIOMD0000000184 +p1361 +tp1362 +Rp1363 +(dp1364 +g8 +Nsg9 +I00 +sbS'Lavrentovich2008_Ca_Oscillations' +p1365 +sg1 +(g2 +g3 +VBIOMD0000000382 +p1366 +tp1367 +Rp1368 +(dp1369 +g8 +Nsg9 +I00 +sbS'Sturis1991_InsulinGlucoseModel_UltradianOscillation' +p1370 +sg1 +(g2 +g3 +VBIOMD0000000448 +p1371 +tp1372 +Rp1373 +(dp1374 +g8 +Nsg9 +I00 +sbS'Br\xc3\xa4nnmark2013 - Insulin signalling in human adipocytes (normal condition)' +p1375 +sg1 +(g2 +g3 +VBIOMD0000000449 +p1376 +tp1377 +Rp1378 +(dp1379 +g8 +Nsg9 +I00 +sbS'Br\xc3\xa4nnmark2013 - Insulin signalling in human adipocytes (diabetic condition)' +p1380 +sg1 +(g2 +g3 +VBIOMD0000000338 +p1381 +tp1382 +Rp1383 +(dp1384 +g8 +Nsg9 +I00 +sbS'Wajima2009_BloodCoagulation_aPTTtest' +p1385 +sg1 +(g2 +g3 +VBIOMD0000000339 +p1386 +tp1387 +Rp1388 +(dp1389 +g8 +Nsg9 +I00 +sbS'Wajima2009_BloodCoagulation_PTtest' +p1390 +sg1 +(g2 +g3 +VBIOMD0000000373 +p1391 +tp1392 +Rp1393 +(dp1394 +g8 +Nsg9 +I00 +sbS'Bertram2004_PancreaticBetaCell_modelB' +p1395 +sg1 +(g2 +g3 +VBIOMD0000000276 +p1396 +tp1397 +Rp1398 +(dp1399 +g8 +Nsg9 +I00 +sbS'Shrestha2010_HypoCalcemia_PTHresponse' +p1400 +sg1 +(g2 +g3 +VBIOMD0000000330 +p1401 +tp1402 +Rp1403 +(dp1404 +g8 +Nsg9 +I00 +sbS'Larsen2004_CalciumSpiking' +p1405 +sg1 +(g2 +g3 +VBIOMD0000000445 +p1406 +tp1407 +Rp1408 +(dp1409 +g8 +Nsg9 +I00 +sbS'Pokhilko2013 - TOC1 signalling in Arabidopsis circadian clock' +p1410 +s. \ No newline at end of file diff --git a/moose-gui/biomodelsclient.py b/moose-gui/biomodelsclient.py new file mode 100644 index 0000000000000000000000000000000000000000..403da12681ff4d440c81af6474d521033aff19fa --- /dev/null +++ b/moose-gui/biomodelsclient.py @@ -0,0 +1,293 @@ +# biomodelsclient.py --- +# +# Filename: biomodelsclient.py +# Description: +# Author: Subhasis Ray +# Maintainer: +# Created: Tue Mar 2 07:57:39 2010 (+0530) +# Version: +# Last-Updated: Wed Dec 11 15:47:32 2010 (+0530) +# By: +# Update #: +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# This is a client for Biomodels database SOAP service. +# It imitates the SOAP client written in JAVA +# availabele at biomodels website. + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: + + +from suds.client import Client +from suds.transport.http import HttpTransport as SudsHttpTransport +import os +import config +import pickle +import moose + +BIOMODELS_WSDL_URI = 'http://www.ebi.ac.uk/biomodels-main/services/BioModelsWebServices?wsdl' +proxyOpts = dict() + +for k,v in {'http':'http_proxy','https':'https_proxy'}.items(): + if os.environ.has_key(v): + httpProxy = os.environ[v].replace('http://', '') + proxyOpts[k] = httpProxy[0:httpProxy.rfind('/',0,len(httpProxy))] + elif os.environ.has_key(v.upper()): + HttpProxy = os.environ[v.upper()].replace('http://', '') + proxyOpts[k] = HttpProxy[0:HttpProxy.rfind('/',0,len(HttpProxy))] + +''' +class HttpTransport(SudsHttpTransport): + """HttpTransport which properly obeys the ``*_proxy`` environment variables.""" + def u2handlers(self): + return [] +''' +class BioModelsClient(Client): + def __init__(self, WSDL_URI=BIOMODELS_WSDL_URI): + """Initialize the client with the available queries listed in + the WSDL file. All the queries can be executed using the following syntax: + + client.service.queryToBeExecuted() + """ + try: + Client.__init__(self, WSDL_URI,proxy=proxyOpts) + #Client.__init__(self, WSDL_URI,transport=HttpTransport()) + except Exception, e: + print e + +from PyQt4.Qt import Qt +from PyQt4 import QtCore, QtGui + +class BioModelsClientWidget(QtGui.QDialog): + """This is a widget with a Biomodels Client. It provides simple + access to the biomodel queries and gives the user a view of the + results""" + COMBO_ITEM_QUERY_MAP = [('All Curated Model Ids', 'getAllCuratedModelsId'), + ('All Model Ids', 'getAllModelsId'), + ('All Non-curated Model Ids', 'getAllNonCuratedModelsId'), + ('Model Name By Id', 'getModelNameById'), + ('Model Ids by ChEBI', 'getModelsIdByChEBI'), + ('Model Ids by ChEBI Id', 'getModelsIdByChEBIId'), + ('Model Ids by Gene Ontology Term', 'getModelsIdByGO'), + ('Model Ids by Gene Ontology Id', 'getModelsIdByGOId'), + ('Model Ids by Name', 'getModelsIdByName'), + ('Model Ids by Author/Modeler', 'getModelsIdByPerson'), + ('Model Ids by Publication', 'getModelsIdByPublication'), + ('Model Ids by Taxonomy', 'getModelsIdByTaxonomy'),] + def __init__(self, parent=None): + QtGui.QWidget.__init__(self, parent) + self.setWindowTitle('Connect to BioModels') + self.client = BioModelsClient() + self.queryPanel = QtGui.QWidget(self) + self.queryModelLabel = QtGui.QLabel('Get ', self.queryPanel) + self.queryModelCombo = QtGui.QComboBox(self.queryPanel) + self.queryLineEdit = QtGui.QLineEdit(self.queryPanel) + self.goButton = QtGui.QPushButton('Go', self.queryPanel) + self.filePath = '' + layout = QtGui.QHBoxLayout(self.queryPanel) + layout.addWidget(self.queryModelLabel) + layout.addWidget(self.queryModelCombo) + layout.addWidget(self.queryLineEdit) + layout.addWidget(self.goButton) + self.queryPanel.setLayout(layout) + + for entry in BioModelsClientWidget.COMBO_ITEM_QUERY_MAP: + self.queryModelCombo.addItem(self.tr(entry[0]), QtCore.QVariant(entry[1])) + self.resultsPanel = QtGui.QTableWidget(self) + layout = QtGui.QVBoxLayout(self) + layout.addWidget(self.queryPanel) + layout.addWidget(self.resultsPanel) + + self.queryPanel1 = QtGui.QWidget(self) + self.importButton = QtGui.QPushButton('Import',self.queryPanel1) + self.importButton.setEnabled(False) + self.closeButton = QtGui.QPushButton('Close',self.queryPanel1) + hbox = QtGui.QHBoxLayout(self.queryPanel1) + hbox.addStretch(1) + hbox.addWidget(self.importButton) + hbox.addWidget(self.closeButton) + layout.addWidget(self.queryPanel1) + + self.setLayout(layout) + self.setupActions() + self.client.set_options(proxy=proxyOpts) + + # TODO: + # proxy = [ can be set using set_option(proxy={'http':'proxyhost:port', ...}) function + + def setupActions(self): + self.connect(self.queryLineEdit, QtCore.SIGNAL('returnPressed()'), self.runQuery) + self.connect(self.goButton, QtCore.SIGNAL('clicked()'), self.runQuery) + self.connect(self.closeButton, QtCore.SIGNAL('clicked()'),self.close) + self.connect(self.importButton,QtCore.SIGNAL('clicked()'),self.downloadModel) + self.connect(self.resultsPanel, QtCore.SIGNAL('cellClicked(int,int)'),self.enableimportButton) + def closeWidget(self): + self.close() + + def downloadModel(self): + """Download the selected model""" + """ If user select multi row, only data from currentRow is downloaded and loaded into moose """ + selectedRow = self.resultsPanel.currentRow() + modelId = self.resultsPanel.item(selectedRow, 0).text() + modelSBML = unicode(self.client.service.getModelSBMLById(modelId)).encode("utf-8") + self.filePath = os.path.join(config.settings[config.KEY_LOCAL_DEMOS_DIR], str(modelId)+'.xml') + f = open(str(self.filePath), 'w') + f.write(modelSBML) + self.close() + + type_sbml = 'SBML' + filters = {'SBML(*.xml)': type_sbml} + filepath,filter_ = QtGui.QFileDialog.getSaveFileNameAndFilter(None,'Save File',modelId,';;'.join(filters)) + if filepath: + if str(filepath).rfind('.') != -1: + filepath = filepath[:str(filepath).rfind('.')] + if str(filter_).rfind('.') != -1: + extension = filter_[str(filter_).rfind('.'):len(filter_)-1] + self.filePath = str(filepath+extension) + + if filters[str(filter_)] == 'SBML': + f = open(str(self.filePath), 'w') + f.write(modelSBML) + f.close() + + def getTargetPath(self): + return str(self.filePath) + + def runQuery(self): + print 'Running query .....' + #self.resultsPanel.cellClicked.connect(self.enableDownload) + progressDialog = QtGui.QProgressDialog() + progressDialog.setLabelText('Retrieving data from BioModels Database') + progressDialog.setModal(True) + progressDialog.setVisible(True) + progressDialog.setWindowTitle("BioModels Database") + index = self.queryModelCombo.currentIndex() + query = self.queryModelCombo.itemData(index).toString() + argument = self.queryLineEdit.text().trimmed() + function = eval('self.client.service.' + str(query)) + if index > 2: + result = function(str(argument)) + else: + result = function() + + self.resultsPanel.clear() + + row = 0 + column = 0 + self.resultsPanel.setColumnCount(2) + self.resultsPanel.setHorizontalHeaderItem(column, QtGui.QTableWidgetItem('Id')) + self.resultsPanel.setHorizontalHeaderItem(column + 1, QtGui.QTableWidgetItem('Name')) + self.resultsPanel.setRowCount(0) + display = True + totalRows = 0 + if type(result) is type(''): + self.resultsPanel.insertRow(row) + item = QtGui.QTableWidgetItem(argument) + item.setFlags(item.flags() & ~Qt.ItemIsEditable) + self.resultsPanel.setItem(row, column, item) + item = QtGui.QTableWidgetItem(result) + item.setFlags(item.flags() & ~Qt.ItemIsEditable) + self.resultsPanel.setItem(row, column + 1, item) + elif type(result) is type([]): + totalRows = len(result) + updatepickleFile = False + filename = str(query) + filePath = os.path.join(config.settings[config.KEY_BIOMODEL_DIR], filename+'.pkl') + #print filePath + pickleResult = {} + if os.path.isfile(filePath): + pickleFile = open(filePath,'rb') + pickleResult = pickle.load(pickleFile) + + #If there is update from BioModels,then pickle file is updated. + r = 0 + if progressDialog: + progressDialog.setMaximum(totalRows) + + for item in result: + if item not in pickleResult: + if progressDialog: + progressDialog.setValue(r) + if progressDialog.wasCanceled(): + return 0 + name = unicode(self.client.service.getModelNameById(item)).encode("utf-8") + r = r+1 + pickleResult.update({item:name}) + updatepickleFile = True + if updatepickleFile: + output = open(os.path.join(config.settings[config.KEY_BIOMODEL_DIR], filename+'.pkl'),'wb') + pickle.dump(pickleResult,output) + output.close() + + + if not argument.isEmpty(): + try: + name = pickleResult[str(argument)] + pickleResult = {} + pickleResult[argument] = name; + + except KeyError, e: + print 'A KeyError - "%s"' % str(e) ,' not found in ',filename + QtGui.QMessageBox.critical(None, "BioModels Database"," The Id "+ str(e) +" not found in "+ filename,QtGui.QMessageBox.Ok | QtGui.QMessageBox.Default,QtGui.QMessageBox.NoButton) + display = False + if display: + for value,name in pickleResult.items(): + self.resultsPanel.insertRow(row) + item = QtGui.QTableWidgetItem(self.tr(value)) + item.setFlags(item.flags() & ~Qt.ItemIsEditable) + #item.setData(Qt.DisplayRole, QtCore.QVariant(value)) + self.resultsPanel.setItem(row, column, item) + #name = self.client.service.getModelNameById(value) + item = QtGui.QTableWidgetItem(name) + item.setFlags(item.flags() & ~Qt.ItemIsEditable) + self.resultsPanel.setItem(row, column + 1, item) + row = row + 1 + + if progressDialog: + progressDialog.close() + #self.importButton.setEnabled(True) + print 'Finished running query' + + def enableimportButton(self): + self.importButton.setEnabled(True) + +if __name__ == '__main__': + client = BioModelsClient() + #print dir(client) + #print client.helloBioModels() + + app = QtGui.QApplication([]) + clientWidget = BioModelsClientWidget() + #clientWidget.exec_() + app.exec_() + +# +# biomodelsclient.py ends here diff --git a/moose-gui/checkcombobox.py b/moose-gui/checkcombobox.py new file mode 100644 index 0000000000000000000000000000000000000000..70d3c07f3c0a74acae4b48f4949deb2a3d662d68 --- /dev/null +++ b/moose-gui/checkcombobox.py @@ -0,0 +1,169 @@ +# checkcombobox.py --- +# +# Filename: checkcombobox.py +# Description: +# Author: +# Maintainer: +# Created: Wed Jun 5 15:06:21 2013 (+0530) +# Version: +# Last-Updated: Wed Jun 5 18:42:50 2013 (+0530) +# By: subha +# Update #: 188 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# ComboBox with checkable items. Inspired by the same in libqxt. +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: + +import sys + +from PyQt4 import QtCore, QtGui +from PyQt4.Qt import Qt +from collections import defaultdict + +class CheckComboBoxModel(QtGui.QStandardItemModel): + """This is inspired by Qxt library.""" + checkStateChange = QtCore.pyqtSignal(name='checkStateChanged') + def __init__(self, *args): + QtGui.QStandardItemModel.__init__(self, *args) + self.checked_dict = defaultdict(int) + + def flags(self, index): + return Qt.ItemIsUserCheckable | Qt.ItemIsSelectable | Qt.ItemIsEnabled + + def data(self, index, role): + if index.isValid() and role == Qt.CheckStateRole: + return QtCore.QVariant(self.checked_dict[index]) + else: + return QtGui.QStandardItemModel.data(self, index, role) + + def setData(self, index, value, role=Qt.EditRole): + if not index.isValid(): + return False + ok = QtGui.QStandardItemModel.setData(self, index, value, role) + if ok and role == Qt.CheckStateRole: + self.checked_dict[index] = value.toInt()[0] + self.dataChanged.emit(index, index) + self.checkStateChange.emit() + return ok + +class ComboEventFilter(QtCore.QObject): + """Event filter for CheckComboBox - inspired by Qxt library""" + def __init__(self, parent): + QtCore.QObject.__init__(self, parent) + + def eventFilter(self, obj, event): + etype = event.type() + if etype == event.KeyPress or etype == event.KeyRelease: + if obj == self and \ + (event.key() == Qt.Key_UP or + event.key() == Qt.Key_Down): + self.parent().showPopup() + return True + elif event.key() == Qt.Key_Enter or \ + event.key() == Qt.Key_Return or \ + event.key() == Qt.Key_Escape: + QtGui.QComboBox.hidePopup(self.parent()) + if event.key() != Qt.Key_Escape: + return True + elif etype == event.MouseButtonPress: + self.parent()._containerMousePress = (obj == self.parent().view().window()) + elif etype == event.MouseButtonRelease: + self.parent()._containerMousePress = False + return False + +class CheckComboBox(QtGui.QComboBox): + """Specialization of QComboBox to allow checkable items. This is + inspired by the same class in Qxt""" + def __init__(self, *args): + QtGui.QComboBox.__init__(self, *args) + self._containerMousePress = False + self.setModel(CheckComboBoxModel()) + self.activated.connect(self.toggleCheckState) + self.ef = ComboEventFilter(self) + self.view().installEventFilter(self.ef) + self.view().window().installEventFilter(self.ef) + self.view().viewport().installEventFilter(self.ef) + self.installEventFilter(self.ef) + + def hidePopup(self): + """This is to disable hiding of the popup when an item is clicked.""" + if self._containerMousePress: + QtGui.QComboBox.hidePopup(self) + + def itemCheckState(self, index): + return self.itemData(index, Qt.CheckStateRole).toInt()[0] + + def setItemCheckState(self, index, state): + self.setItemData(index, QtCore.QVariant(state), QtCore.Qt.CheckStateRole) + + def checkedItems(self): + index = self.model().index(0,0) + checked = self.model().match(index, Qt.CheckStateRole, Qt.Checked, -1, Qt.MatchExactly) + return [index.data().toString() for index in checked] + + def setCheckedItems(self, textItemList): + for text in textItemList: + index = self.findText(text) + if index.isValid(): + self.setItemCheckState(index, Qt.Checked) + else: + self.setItemCheckState(index, Qt.Unchecked) + + def toggleCheckState(self, index): + value = self.itemData(index, Qt.CheckStateRole) + if value.isValid(): + state = value.toInt()[0] + if state == Qt.Checked: + self.setItemData(index, Qt.Unchecked, Qt.CheckStateRole) + else: + self.setItemData(index, Qt.Checked, Qt.CheckStateRole) + +def main(): + """Test main: load a model and display the tree for it""" + app = QtGui.QApplication([]) + mainwin = QtGui.QMainWindow() + mainwin.setWindowTitle('CheckComboBox test') + box = CheckComboBox() + for ii in range(5): + box.addItem('myitem_%d' % (ii)) + mainwin.setCentralWidget(box) + mainwin.show() + sys.exit(app.exec_()) + +if __name__ == '__main__': + main() + + +# +# checkcombobox.py ends here diff --git a/moose-gui/colormaps/fire b/moose-gui/colormaps/fire new file mode 100644 index 0000000000000000000000000000000000000000..52498d78ab3e4ec773c75768af05ce82a873b526 --- /dev/null +++ b/moose-gui/colormaps/fire @@ -0,0 +1,3754 @@ +(lp0 +(lp1 +cdecimal +Decimal +p2 +(S'0' +p3 +tp4 +Rp5 +ag2 +(g3 +tp6 +Rp7 +ag2 +(g3 +tp8 +Rp9 +aa(lp10 +g2 +(g3 +tp11 +Rp12 +ag2 +(g3 +tp13 +Rp14 +ag2 +(S'0.0157' +p15 +tp16 +Rp17 +aa(lp18 +g2 +(g3 +tp19 +Rp20 +ag2 +(g3 +tp21 +Rp22 +ag2 +(S'0.0314' +p23 +tp24 +Rp25 +aa(lp26 +g2 +(g3 +tp27 +Rp28 +ag2 +(g3 +tp29 +Rp30 +ag2 +(S'0.0471' +p31 +tp32 +Rp33 +aa(lp34 +g2 +(g3 +tp35 +Rp36 +ag2 +(g3 +tp37 +Rp38 +ag2 +(S'0.0627' +p39 +tp40 +Rp41 +aa(lp42 +g2 +(g3 +tp43 +Rp44 +ag2 +(g3 +tp45 +Rp46 +ag2 +(S'0.0784' +p47 +tp48 +Rp49 +aa(lp50 +g2 +(g3 +tp51 +Rp52 +ag2 +(g3 +tp53 +Rp54 +ag2 +(S'0.0941' +p55 +tp56 +Rp57 +aa(lp58 +g2 +(g3 +tp59 +Rp60 +ag2 +(g3 +tp61 +Rp62 +ag2 +(S'0.110' +p63 +tp64 +Rp65 +aa(lp66 +g2 +(g3 +tp67 +Rp68 +ag2 +(g3 +tp69 +Rp70 +ag2 +(S'0.125' +p71 +tp72 +Rp73 +aa(lp74 +g2 +(g3 +tp75 +Rp76 +ag2 +(g3 +tp77 +Rp78 +ag2 +(S'0.141' +p79 +tp80 +Rp81 +aa(lp82 +g2 +(g3 +tp83 +Rp84 +ag2 +(g3 +tp85 +Rp86 +ag2 +(S'0.161' +p87 +tp88 +Rp89 +aa(lp90 +g2 +(g3 +tp91 +Rp92 +ag2 +(g3 +tp93 +Rp94 +ag2 +(S'0.176' +p95 +tp96 +Rp97 +aa(lp98 +g2 +(g3 +tp99 +Rp100 +ag2 +(g3 +tp101 +Rp102 +ag2 +(S'0.192' +p103 +tp104 +Rp105 +aa(lp106 +g2 +(g3 +tp107 +Rp108 +ag2 +(g3 +tp109 +Rp110 +ag2 +(S'0.208' +p111 +tp112 +Rp113 +aa(lp114 +g2 +(g3 +tp115 +Rp116 +ag2 +(g3 +tp117 +Rp118 +ag2 +(S'0.224' +p119 +tp120 +Rp121 +aa(lp122 +g2 +(g3 +tp123 +Rp124 +ag2 +(g3 +tp125 +Rp126 +ag2 +(S'0.239' +p127 +tp128 +Rp129 +aa(lp130 +g2 +(g3 +tp131 +Rp132 +ag2 +(g3 +tp133 +Rp134 +ag2 +(S'0.255' +p135 +tp136 +Rp137 +aa(lp138 +g2 +(S'0.00784' +p139 +tp140 +Rp141 +ag2 +(g3 +tp142 +Rp143 +ag2 +(S'0.271' +p144 +tp145 +Rp146 +aa(lp147 +g2 +(S'0.0157' +p148 +tp149 +Rp150 +ag2 +(g3 +tp151 +Rp152 +ag2 +(S'0.286' +p153 +tp154 +Rp155 +aa(lp156 +g2 +(S'0.0235' +p157 +tp158 +Rp159 +ag2 +(g3 +tp160 +Rp161 +ag2 +(S'0.302' +p162 +tp163 +Rp164 +aa(lp165 +g2 +(S'0.0314' +p166 +tp167 +Rp168 +ag2 +(g3 +tp169 +Rp170 +ag2 +(S'0.318' +p171 +tp172 +Rp173 +aa(lp174 +g2 +(S'0.0392' +p175 +tp176 +Rp177 +ag2 +(g3 +tp178 +Rp179 +ag2 +(S'0.333' +p180 +tp181 +Rp182 +aa(lp183 +g2 +(S'0.0471' +p184 +tp185 +Rp186 +ag2 +(g3 +tp187 +Rp188 +ag2 +(S'0.349' +p189 +tp190 +Rp191 +aa(lp192 +g2 +(S'0.0549' +p193 +tp194 +Rp195 +ag2 +(g3 +tp196 +Rp197 +ag2 +(S'0.365' +p198 +tp199 +Rp200 +aa(lp201 +g2 +(S'0.0627' +p202 +tp203 +Rp204 +ag2 +(g3 +tp205 +Rp206 +ag2 +(S'0.380' +p207 +tp208 +Rp209 +aa(lp210 +g2 +(S'0.0706' +p211 +tp212 +Rp213 +ag2 +(g3 +tp214 +Rp215 +ag2 +(S'0.396' +p216 +tp217 +Rp218 +aa(lp219 +g2 +(S'0.0784' +p220 +tp221 +Rp222 +ag2 +(g3 +tp223 +Rp224 +ag2 +(S'0.412' +p225 +tp226 +Rp227 +aa(lp228 +g2 +(S'0.0863' +p229 +tp230 +Rp231 +ag2 +(g3 +tp232 +Rp233 +ag2 +(S'0.427' +p234 +tp235 +Rp236 +aa(lp237 +g2 +(S'0.0941' +p238 +tp239 +Rp240 +ag2 +(g3 +tp241 +Rp242 +ag2 +(S'0.447' +p243 +tp244 +Rp245 +aa(lp246 +g2 +(S'0.102' +p247 +tp248 +Rp249 +ag2 +(g3 +tp250 +Rp251 +ag2 +(S'0.463' +p252 +tp253 +Rp254 +aa(lp255 +g2 +(S'0.110' +p256 +tp257 +Rp258 +ag2 +(g3 +tp259 +Rp260 +ag2 +(S'0.478' +p261 +tp262 +Rp263 +aa(lp264 +g2 +(S'0.118' +p265 +tp266 +Rp267 +ag2 +(g3 +tp268 +Rp269 +ag2 +(S'0.494' +p270 +tp271 +Rp272 +aa(lp273 +g2 +(S'0.125' +p274 +tp275 +Rp276 +ag2 +(g3 +tp277 +Rp278 +ag2 +(S'0.510' +p279 +tp280 +Rp281 +aa(lp282 +g2 +(S'0.133' +p283 +tp284 +Rp285 +ag2 +(g3 +tp286 +Rp287 +ag2 +(S'0.525' +p288 +tp289 +Rp290 +aa(lp291 +g2 +(S'0.141' +p292 +tp293 +Rp294 +ag2 +(g3 +tp295 +Rp296 +ag2 +(S'0.541' +p297 +tp298 +Rp299 +aa(lp300 +g2 +(S'0.149' +p301 +tp302 +Rp303 +ag2 +(g3 +tp304 +Rp305 +ag2 +(S'0.557' +p306 +tp307 +Rp308 +aa(lp309 +g2 +(S'0.157' +p310 +tp311 +Rp312 +ag2 +(g3 +tp313 +Rp314 +ag2 +(S'0.573' +p315 +tp316 +Rp317 +aa(lp318 +g2 +(S'0.165' +p319 +tp320 +Rp321 +ag2 +(g3 +tp322 +Rp323 +ag2 +(S'0.588' +p324 +tp325 +Rp326 +aa(lp327 +g2 +(S'0.173' +p328 +tp329 +Rp330 +ag2 +(g3 +tp331 +Rp332 +ag2 +(S'0.604' +p333 +tp334 +Rp335 +aa(lp336 +g2 +(S'0.180' +p337 +tp338 +Rp339 +ag2 +(g3 +tp340 +Rp341 +ag2 +(S'0.620' +p342 +tp343 +Rp344 +aa(lp345 +g2 +(S'0.188' +p346 +tp347 +Rp348 +ag2 +(g3 +tp349 +Rp350 +ag2 +(S'0.635' +p351 +tp352 +Rp353 +aa(lp354 +g2 +(S'0.196' +p355 +tp356 +Rp357 +ag2 +(g3 +tp358 +Rp359 +ag2 +(S'0.651' +p360 +tp361 +Rp362 +aa(lp363 +g2 +(S'0.204' +p364 +tp365 +Rp366 +ag2 +(g3 +tp367 +Rp368 +ag2 +(S'0.667' +p369 +tp370 +Rp371 +aa(lp372 +g2 +(S'0.212' +p373 +tp374 +Rp375 +ag2 +(g3 +tp376 +Rp377 +ag2 +(S'0.682' +p378 +tp379 +Rp380 +aa(lp381 +g2 +(S'0.220' +p382 +tp383 +Rp384 +ag2 +(g3 +tp385 +Rp386 +ag2 +(S'0.698' +p387 +tp388 +Rp389 +aa(lp390 +g2 +(S'0.227' +p391 +tp392 +Rp393 +ag2 +(g3 +tp394 +Rp395 +ag2 +(S'0.714' +p396 +tp397 +Rp398 +aa(lp399 +g2 +(S'0.235' +p400 +tp401 +Rp402 +ag2 +(g3 +tp403 +Rp404 +ag2 +(S'0.729' +p405 +tp406 +Rp407 +aa(lp408 +g2 +(S'0.243' +p409 +tp410 +Rp411 +ag2 +(g3 +tp412 +Rp413 +ag2 +(S'0.749' +p414 +tp415 +Rp416 +aa(lp417 +g2 +(S'0.251' +p418 +tp419 +Rp420 +ag2 +(g3 +tp421 +Rp422 +ag2 +(S'0.765' +p423 +tp424 +Rp425 +aa(lp426 +g2 +(S'0.259' +p427 +tp428 +Rp429 +ag2 +(g3 +tp430 +Rp431 +ag2 +(S'0.780' +p432 +tp433 +Rp434 +aa(lp435 +g2 +(S'0.267' +p436 +tp437 +Rp438 +ag2 +(g3 +tp439 +Rp440 +ag2 +(S'0.796' +p441 +tp442 +Rp443 +aa(lp444 +g2 +(S'0.275' +p445 +tp446 +Rp447 +ag2 +(g3 +tp448 +Rp449 +ag2 +(S'0.812' +p450 +tp451 +Rp452 +aa(lp453 +g2 +(S'0.282' +p454 +tp455 +Rp456 +ag2 +(g3 +tp457 +Rp458 +ag2 +(S'0.827' +p459 +tp460 +Rp461 +aa(lp462 +g2 +(S'0.290' +p463 +tp464 +Rp465 +ag2 +(g3 +tp466 +Rp467 +ag2 +(S'0.843' +p468 +tp469 +Rp470 +aa(lp471 +g2 +(S'0.298' +p472 +tp473 +Rp474 +ag2 +(g3 +tp475 +Rp476 +ag2 +(S'0.859' +p477 +tp478 +Rp479 +aa(lp480 +g2 +(S'0.306' +p481 +tp482 +Rp483 +ag2 +(g3 +tp484 +Rp485 +ag2 +(S'0.875' +p486 +tp487 +Rp488 +aa(lp489 +g2 +(S'0.314' +p490 +tp491 +Rp492 +ag2 +(g3 +tp493 +Rp494 +ag2 +(S'0.890' +p495 +tp496 +Rp497 +aa(lp498 +g2 +(S'0.322' +p499 +tp500 +Rp501 +ag2 +(g3 +tp502 +Rp503 +ag2 +(S'0.878' +p504 +tp505 +Rp506 +aa(lp507 +g2 +(S'0.329' +p508 +tp509 +Rp510 +ag2 +(g3 +tp511 +Rp512 +ag2 +(S'0.867' +p513 +tp514 +Rp515 +aa(lp516 +g2 +(S'0.337' +p517 +tp518 +Rp519 +ag2 +(g3 +tp520 +Rp521 +ag2 +(S'0.855' +p522 +tp523 +Rp524 +aa(lp525 +g2 +(S'0.345' +p526 +tp527 +Rp528 +ag2 +(g3 +tp529 +Rp530 +ag2 +(S'0.839' +p531 +tp532 +Rp533 +aa(lp534 +g2 +(S'0.353' +p535 +tp536 +Rp537 +ag2 +(g3 +tp538 +Rp539 +ag2 +(S'0.827' +p540 +tp541 +Rp542 +aa(lp543 +g2 +(S'0.361' +p544 +tp545 +Rp546 +ag2 +(g3 +tp547 +Rp548 +ag2 +(S'0.816' +p549 +tp550 +Rp551 +aa(lp552 +g2 +(S'0.369' +p553 +tp554 +Rp555 +ag2 +(g3 +tp556 +Rp557 +ag2 +(S'0.804' +p558 +tp559 +Rp560 +aa(lp561 +g2 +(S'0.376' +p562 +tp563 +Rp564 +ag2 +(g3 +tp565 +Rp566 +ag2 +(S'0.792' +p567 +tp568 +Rp569 +aa(lp570 +g2 +(S'0.384' +p571 +tp572 +Rp573 +ag2 +(g3 +tp574 +Rp575 +ag2 +(S'0.780' +p576 +tp577 +Rp578 +aa(lp579 +g2 +(S'0.392' +p580 +tp581 +Rp582 +ag2 +(g3 +tp583 +Rp584 +ag2 +(S'0.765' +p585 +tp586 +Rp587 +aa(lp588 +g2 +(S'0.4' +p589 +tp590 +Rp591 +ag2 +(g3 +tp592 +Rp593 +ag2 +(S'0.753' +p594 +tp595 +Rp596 +aa(lp597 +g2 +(S'0.408' +p598 +tp599 +Rp600 +ag2 +(g3 +tp601 +Rp602 +ag2 +(S'0.741' +p603 +tp604 +Rp605 +aa(lp606 +g2 +(S'0.416' +p607 +tp608 +Rp609 +ag2 +(g3 +tp610 +Rp611 +ag2 +(S'0.729' +p612 +tp613 +Rp614 +aa(lp615 +g2 +(S'0.424' +p616 +tp617 +Rp618 +ag2 +(g3 +tp619 +Rp620 +ag2 +(S'0.718' +p621 +tp622 +Rp623 +aa(lp624 +g2 +(S'0.431' +p625 +tp626 +Rp627 +ag2 +(g3 +tp628 +Rp629 +ag2 +(S'0.706' +p630 +tp631 +Rp632 +aa(lp633 +g2 +(S'0.439' +p634 +tp635 +Rp636 +ag2 +(g3 +tp637 +Rp638 +ag2 +(S'0.694' +p639 +tp640 +Rp641 +aa(lp642 +g2 +(S'0.447' +p643 +tp644 +Rp645 +ag2 +(g3 +tp646 +Rp647 +ag2 +(S'0.678' +p648 +tp649 +Rp650 +aa(lp651 +g2 +(S'0.455' +p652 +tp653 +Rp654 +ag2 +(g3 +tp655 +Rp656 +ag2 +(S'0.667' +p657 +tp658 +Rp659 +aa(lp660 +g2 +(S'0.463' +p661 +tp662 +Rp663 +ag2 +(g3 +tp664 +Rp665 +ag2 +(S'0.655' +p666 +tp667 +Rp668 +aa(lp669 +g2 +(S'0.471' +p670 +tp671 +Rp672 +ag2 +(g3 +tp673 +Rp674 +ag2 +(S'0.643' +p675 +tp676 +Rp677 +aa(lp678 +g2 +(S'0.478' +p679 +tp680 +Rp681 +ag2 +(g3 +tp682 +Rp683 +ag2 +(S'0.631' +p684 +tp685 +Rp686 +aa(lp687 +g2 +(S'0.486' +p688 +tp689 +Rp690 +ag2 +(g3 +tp691 +Rp692 +ag2 +(S'0.620' +p693 +tp694 +Rp695 +aa(lp696 +g2 +(S'0.494' +p697 +tp698 +Rp699 +ag2 +(g3 +tp700 +Rp701 +ag2 +(S'0.604' +p702 +tp703 +Rp704 +aa(lp705 +g2 +(S'0.502' +p706 +tp707 +Rp708 +ag2 +(g3 +tp709 +Rp710 +ag2 +(S'0.592' +p711 +tp712 +Rp713 +aa(lp714 +g2 +(S'0.510' +p715 +tp716 +Rp717 +ag2 +(g3 +tp718 +Rp719 +ag2 +(S'0.580' +p720 +tp721 +Rp722 +aa(lp723 +g2 +(S'0.518' +p724 +tp725 +Rp726 +ag2 +(g3 +tp727 +Rp728 +ag2 +(S'0.569' +p729 +tp730 +Rp731 +aa(lp732 +g2 +(S'0.525' +p733 +tp734 +Rp735 +ag2 +(g3 +tp736 +Rp737 +ag2 +(S'0.557' +p738 +tp739 +Rp740 +aa(lp741 +g2 +(S'0.533' +p742 +tp743 +Rp744 +ag2 +(g3 +tp745 +Rp746 +ag2 +(S'0.545' +p747 +tp748 +Rp749 +aa(lp750 +g2 +(S'0.541' +p751 +tp752 +Rp753 +ag2 +(g3 +tp754 +Rp755 +ag2 +(S'0.533' +p756 +tp757 +Rp758 +aa(lp759 +g2 +(S'0.549' +p760 +tp761 +Rp762 +ag2 +(g3 +tp763 +Rp764 +ag2 +(S'0.518' +p765 +tp766 +Rp767 +aa(lp768 +g2 +(S'0.557' +p769 +tp770 +Rp771 +ag2 +(g3 +tp772 +Rp773 +ag2 +(S'0.506' +p774 +tp775 +Rp776 +aa(lp777 +g2 +(S'0.565' +p778 +tp779 +Rp780 +ag2 +(g3 +tp781 +Rp782 +ag2 +(S'0.494' +p783 +tp784 +Rp785 +aa(lp786 +g2 +(S'0.573' +p787 +tp788 +Rp789 +ag2 +(g3 +tp790 +Rp791 +ag2 +(S'0.482' +p792 +tp793 +Rp794 +aa(lp795 +g2 +(S'0.580' +p796 +tp797 +Rp798 +ag2 +(g3 +tp799 +Rp800 +ag2 +(S'0.471' +p801 +tp802 +Rp803 +aa(lp804 +g2 +(S'0.588' +p805 +tp806 +Rp807 +ag2 +(g3 +tp808 +Rp809 +ag2 +(S'0.459' +p810 +tp811 +Rp812 +aa(lp813 +g2 +(S'0.596' +p814 +tp815 +Rp816 +ag2 +(g3 +tp817 +Rp818 +ag2 +(S'0.447' +p819 +tp820 +Rp821 +aa(lp822 +g2 +(S'0.604' +p823 +tp824 +Rp825 +ag2 +(g3 +tp826 +Rp827 +ag2 +(S'0.431' +p828 +tp829 +Rp830 +aa(lp831 +g2 +(S'0.612' +p832 +tp833 +Rp834 +ag2 +(g3 +tp835 +Rp836 +ag2 +(S'0.420' +p837 +tp838 +Rp839 +aa(lp840 +g2 +(S'0.620' +p841 +tp842 +Rp843 +ag2 +(g3 +tp844 +Rp845 +ag2 +(S'0.408' +p846 +tp847 +Rp848 +aa(lp849 +g2 +(S'0.627' +p850 +tp851 +Rp852 +ag2 +(g3 +tp853 +Rp854 +ag2 +(S'0.396' +p855 +tp856 +Rp857 +aa(lp858 +g2 +(S'0.635' +p859 +tp860 +Rp861 +ag2 +(S'0.00784' +p862 +tp863 +Rp864 +ag2 +(S'0.384' +p865 +tp866 +Rp867 +aa(lp868 +g2 +(S'0.643' +p869 +tp870 +Rp871 +ag2 +(S'0.0157' +p872 +tp873 +Rp874 +ag2 +(S'0.373' +p875 +tp876 +Rp877 +aa(lp878 +g2 +(S'0.651' +p879 +tp880 +Rp881 +ag2 +(S'0.0235' +p882 +tp883 +Rp884 +ag2 +(S'0.357' +p885 +tp886 +Rp887 +aa(lp888 +g2 +(S'0.659' +p889 +tp890 +Rp891 +ag2 +(S'0.0314' +p892 +tp893 +Rp894 +ag2 +(S'0.345' +p895 +tp896 +Rp897 +aa(lp898 +g2 +(S'0.667' +p899 +tp900 +Rp901 +ag2 +(S'0.0392' +p902 +tp903 +Rp904 +ag2 +(S'0.333' +p905 +tp906 +Rp907 +aa(lp908 +g2 +(S'0.675' +p909 +tp910 +Rp911 +ag2 +(S'0.0471' +p912 +tp913 +Rp914 +ag2 +(S'0.322' +p915 +tp916 +Rp917 +aa(lp918 +g2 +(S'0.682' +p919 +tp920 +Rp921 +ag2 +(S'0.0549' +p922 +tp923 +Rp924 +ag2 +(S'0.310' +p925 +tp926 +Rp927 +aa(lp928 +g2 +(S'0.690' +p929 +tp930 +Rp931 +ag2 +(S'0.0627' +p932 +tp933 +Rp934 +ag2 +(S'0.298' +p935 +tp936 +Rp937 +aa(lp938 +g2 +(S'0.698' +p939 +tp940 +Rp941 +ag2 +(S'0.0706' +p942 +tp943 +Rp944 +ag2 +(S'0.286' +p945 +tp946 +Rp947 +aa(lp948 +g2 +(S'0.706' +p949 +tp950 +Rp951 +ag2 +(S'0.0784' +p952 +tp953 +Rp954 +ag2 +(S'0.271' +p955 +tp956 +Rp957 +aa(lp958 +g2 +(S'0.714' +p959 +tp960 +Rp961 +ag2 +(S'0.0863' +p962 +tp963 +Rp964 +ag2 +(S'0.259' +p965 +tp966 +Rp967 +aa(lp968 +g2 +(S'0.722' +p969 +tp970 +Rp971 +ag2 +(S'0.0941' +p972 +tp973 +Rp974 +ag2 +(S'0.247' +p975 +tp976 +Rp977 +aa(lp978 +g2 +(S'0.729' +p979 +tp980 +Rp981 +ag2 +(S'0.102' +p982 +tp983 +Rp984 +ag2 +(S'0.235' +p985 +tp986 +Rp987 +aa(lp988 +g2 +(S'0.737' +p989 +tp990 +Rp991 +ag2 +(S'0.110' +p992 +tp993 +Rp994 +ag2 +(S'0.224' +p995 +tp996 +Rp997 +aa(lp998 +g2 +(S'0.745' +p999 +tp1000 +Rp1001 +ag2 +(S'0.118' +p1002 +tp1003 +Rp1004 +ag2 +(S'0.212' +p1005 +tp1006 +Rp1007 +aa(lp1008 +g2 +(S'0.753' +p1009 +tp1010 +Rp1011 +ag2 +(S'0.125' +p1012 +tp1013 +Rp1014 +ag2 +(S'0.196' +p1015 +tp1016 +Rp1017 +aa(lp1018 +g2 +(S'0.761' +p1019 +tp1020 +Rp1021 +ag2 +(S'0.133' +p1022 +tp1023 +Rp1024 +ag2 +(S'0.184' +p1025 +tp1026 +Rp1027 +aa(lp1028 +g2 +(S'0.769' +p1029 +tp1030 +Rp1031 +ag2 +(S'0.141' +p1032 +tp1033 +Rp1034 +ag2 +(S'0.173' +p1035 +tp1036 +Rp1037 +aa(lp1038 +g2 +(S'0.776' +p1039 +tp1040 +Rp1041 +ag2 +(S'0.149' +p1042 +tp1043 +Rp1044 +ag2 +(S'0.161' +p1045 +tp1046 +Rp1047 +aa(lp1048 +g2 +(S'0.784' +p1049 +tp1050 +Rp1051 +ag2 +(S'0.157' +p1052 +tp1053 +Rp1054 +ag2 +(S'0.149' +p1055 +tp1056 +Rp1057 +aa(lp1058 +g2 +(S'0.792' +p1059 +tp1060 +Rp1061 +ag2 +(S'0.165' +p1062 +tp1063 +Rp1064 +ag2 +(S'0.137' +p1065 +tp1066 +Rp1067 +aa(lp1068 +g2 +(S'0.8' +p1069 +tp1070 +Rp1071 +ag2 +(S'0.173' +p1072 +tp1073 +Rp1074 +ag2 +(S'0.125' +p1075 +tp1076 +Rp1077 +aa(lp1078 +g2 +(S'0.808' +p1079 +tp1080 +Rp1081 +ag2 +(S'0.180' +p1082 +tp1083 +Rp1084 +ag2 +(S'0.110' +p1085 +tp1086 +Rp1087 +aa(lp1088 +g2 +(S'0.816' +p1089 +tp1090 +Rp1091 +ag2 +(S'0.188' +p1092 +tp1093 +Rp1094 +ag2 +(S'0.0980' +p1095 +tp1096 +Rp1097 +aa(lp1098 +g2 +(S'0.824' +p1099 +tp1100 +Rp1101 +ag2 +(S'0.196' +p1102 +tp1103 +Rp1104 +ag2 +(S'0.0863' +p1105 +tp1106 +Rp1107 +aa(lp1108 +g2 +(S'0.831' +p1109 +tp1110 +Rp1111 +ag2 +(S'0.204' +p1112 +tp1113 +Rp1114 +ag2 +(S'0.0745' +p1115 +tp1116 +Rp1117 +aa(lp1118 +g2 +(S'0.839' +p1119 +tp1120 +Rp1121 +ag2 +(S'0.212' +p1122 +tp1123 +Rp1124 +ag2 +(S'0.0627' +p1125 +tp1126 +Rp1127 +aa(lp1128 +g2 +(S'0.847' +p1129 +tp1130 +Rp1131 +ag2 +(S'0.220' +p1132 +tp1133 +Rp1134 +ag2 +(S'0.0510' +p1135 +tp1136 +Rp1137 +aa(lp1138 +g2 +(S'0.855' +p1139 +tp1140 +Rp1141 +ag2 +(S'0.227' +p1142 +tp1143 +Rp1144 +ag2 +(S'0.0353' +p1145 +tp1146 +Rp1147 +aa(lp1148 +g2 +(S'0.863' +p1149 +tp1150 +Rp1151 +ag2 +(S'0.235' +p1152 +tp1153 +Rp1154 +ag2 +(S'0.0235' +p1155 +tp1156 +Rp1157 +aa(lp1158 +g2 +(S'0.871' +p1159 +tp1160 +Rp1161 +ag2 +(S'0.243' +p1162 +tp1163 +Rp1164 +ag2 +(S'0.0118' +p1165 +tp1166 +Rp1167 +aa(lp1168 +g2 +(S'0.878' +p1169 +tp1170 +Rp1171 +ag2 +(S'0.251' +p1172 +tp1173 +Rp1174 +ag2 +(g3 +tp1175 +Rp1176 +aa(lp1177 +g2 +(S'0.886' +p1178 +tp1179 +Rp1180 +ag2 +(S'0.259' +p1181 +tp1182 +Rp1183 +ag2 +(g3 +tp1184 +Rp1185 +aa(lp1186 +g2 +(S'0.894' +p1187 +tp1188 +Rp1189 +ag2 +(S'0.267' +p1190 +tp1191 +Rp1192 +ag2 +(g3 +tp1193 +Rp1194 +aa(lp1195 +g2 +(S'0.902' +p1196 +tp1197 +Rp1198 +ag2 +(S'0.275' +p1199 +tp1200 +Rp1201 +ag2 +(g3 +tp1202 +Rp1203 +aa(lp1204 +g2 +(S'0.910' +p1205 +tp1206 +Rp1207 +ag2 +(S'0.282' +p1208 +tp1209 +Rp1210 +ag2 +(g3 +tp1211 +Rp1212 +aa(lp1213 +g2 +(S'0.918' +p1214 +tp1215 +Rp1216 +ag2 +(S'0.290' +p1217 +tp1218 +Rp1219 +ag2 +(g3 +tp1220 +Rp1221 +aa(lp1222 +g2 +(S'0.925' +p1223 +tp1224 +Rp1225 +ag2 +(S'0.298' +p1226 +tp1227 +Rp1228 +ag2 +(g3 +tp1229 +Rp1230 +aa(lp1231 +g2 +(S'0.933' +p1232 +tp1233 +Rp1234 +ag2 +(S'0.306' +p1235 +tp1236 +Rp1237 +ag2 +(g3 +tp1238 +Rp1239 +aa(lp1240 +g2 +(S'0.941' +p1241 +tp1242 +Rp1243 +ag2 +(S'0.314' +p1244 +tp1245 +Rp1246 +ag2 +(g3 +tp1247 +Rp1248 +aa(lp1249 +g2 +(S'0.949' +p1250 +tp1251 +Rp1252 +ag2 +(S'0.322' +p1253 +tp1254 +Rp1255 +ag2 +(g3 +tp1256 +Rp1257 +aa(lp1258 +g2 +(S'0.957' +p1259 +tp1260 +Rp1261 +ag2 +(S'0.329' +p1262 +tp1263 +Rp1264 +ag2 +(g3 +tp1265 +Rp1266 +aa(lp1267 +g2 +(S'0.965' +p1268 +tp1269 +Rp1270 +ag2 +(S'0.337' +p1271 +tp1272 +Rp1273 +ag2 +(g3 +tp1274 +Rp1275 +aa(lp1276 +g2 +(S'0.973' +p1277 +tp1278 +Rp1279 +ag2 +(S'0.345' +p1280 +tp1281 +Rp1282 +ag2 +(g3 +tp1283 +Rp1284 +aa(lp1285 +g2 +(S'0.980' +p1286 +tp1287 +Rp1288 +ag2 +(S'0.353' +p1289 +tp1290 +Rp1291 +ag2 +(g3 +tp1292 +Rp1293 +aa(lp1294 +g2 +(S'0.988' +p1295 +tp1296 +Rp1297 +ag2 +(S'0.361' +p1298 +tp1299 +Rp1300 +ag2 +(g3 +tp1301 +Rp1302 +aa(lp1303 +g2 +(S'0.996' +p1304 +tp1305 +Rp1306 +ag2 +(S'0.369' +p1307 +tp1308 +Rp1309 +ag2 +(g3 +tp1310 +Rp1311 +aa(lp1312 +g2 +(S'1' +p1313 +tp1314 +Rp1315 +ag2 +(S'0.376' +p1316 +tp1317 +Rp1318 +ag2 +(g3 +tp1319 +Rp1320 +aa(lp1321 +g2 +(g1313 +tp1322 +Rp1323 +ag2 +(S'0.384' +p1324 +tp1325 +Rp1326 +ag2 +(g3 +tp1327 +Rp1328 +aa(lp1329 +g2 +(g1313 +tp1330 +Rp1331 +ag2 +(S'0.392' +p1332 +tp1333 +Rp1334 +ag2 +(g3 +tp1335 +Rp1336 +aa(lp1337 +g2 +(g1313 +tp1338 +Rp1339 +ag2 +(S'0.4' +p1340 +tp1341 +Rp1342 +ag2 +(g3 +tp1343 +Rp1344 +aa(lp1345 +g2 +(g1313 +tp1346 +Rp1347 +ag2 +(S'0.408' +p1348 +tp1349 +Rp1350 +ag2 +(g3 +tp1351 +Rp1352 +aa(lp1353 +g2 +(g1313 +tp1354 +Rp1355 +ag2 +(S'0.416' +p1356 +tp1357 +Rp1358 +ag2 +(g3 +tp1359 +Rp1360 +aa(lp1361 +g2 +(g1313 +tp1362 +Rp1363 +ag2 +(S'0.424' +p1364 +tp1365 +Rp1366 +ag2 +(g3 +tp1367 +Rp1368 +aa(lp1369 +g2 +(g1313 +tp1370 +Rp1371 +ag2 +(S'0.431' +p1372 +tp1373 +Rp1374 +ag2 +(g3 +tp1375 +Rp1376 +aa(lp1377 +g2 +(g1313 +tp1378 +Rp1379 +ag2 +(S'0.439' +p1380 +tp1381 +Rp1382 +ag2 +(g3 +tp1383 +Rp1384 +aa(lp1385 +g2 +(g1313 +tp1386 +Rp1387 +ag2 +(S'0.447' +p1388 +tp1389 +Rp1390 +ag2 +(g3 +tp1391 +Rp1392 +aa(lp1393 +g2 +(g1313 +tp1394 +Rp1395 +ag2 +(S'0.455' +p1396 +tp1397 +Rp1398 +ag2 +(g3 +tp1399 +Rp1400 +aa(lp1401 +g2 +(g1313 +tp1402 +Rp1403 +ag2 +(S'0.463' +p1404 +tp1405 +Rp1406 +ag2 +(g3 +tp1407 +Rp1408 +aa(lp1409 +g2 +(g1313 +tp1410 +Rp1411 +ag2 +(S'0.471' +p1412 +tp1413 +Rp1414 +ag2 +(g3 +tp1415 +Rp1416 +aa(lp1417 +g2 +(g1313 +tp1418 +Rp1419 +ag2 +(S'0.478' +p1420 +tp1421 +Rp1422 +ag2 +(g3 +tp1423 +Rp1424 +aa(lp1425 +g2 +(g1313 +tp1426 +Rp1427 +ag2 +(S'0.486' +p1428 +tp1429 +Rp1430 +ag2 +(g3 +tp1431 +Rp1432 +aa(lp1433 +g2 +(g1313 +tp1434 +Rp1435 +ag2 +(S'0.494' +p1436 +tp1437 +Rp1438 +ag2 +(g3 +tp1439 +Rp1440 +aa(lp1441 +g2 +(g1313 +tp1442 +Rp1443 +ag2 +(S'0.502' +p1444 +tp1445 +Rp1446 +ag2 +(g3 +tp1447 +Rp1448 +aa(lp1449 +g2 +(g1313 +tp1450 +Rp1451 +ag2 +(S'0.510' +p1452 +tp1453 +Rp1454 +ag2 +(g3 +tp1455 +Rp1456 +aa(lp1457 +g2 +(g1313 +tp1458 +Rp1459 +ag2 +(S'0.518' +p1460 +tp1461 +Rp1462 +ag2 +(g3 +tp1463 +Rp1464 +aa(lp1465 +g2 +(g1313 +tp1466 +Rp1467 +ag2 +(S'0.525' +p1468 +tp1469 +Rp1470 +ag2 +(g3 +tp1471 +Rp1472 +aa(lp1473 +g2 +(g1313 +tp1474 +Rp1475 +ag2 +(S'0.533' +p1476 +tp1477 +Rp1478 +ag2 +(g3 +tp1479 +Rp1480 +aa(lp1481 +g2 +(g1313 +tp1482 +Rp1483 +ag2 +(S'0.541' +p1484 +tp1485 +Rp1486 +ag2 +(g3 +tp1487 +Rp1488 +aa(lp1489 +g2 +(g1313 +tp1490 +Rp1491 +ag2 +(S'0.549' +p1492 +tp1493 +Rp1494 +ag2 +(g3 +tp1495 +Rp1496 +aa(lp1497 +g2 +(g1313 +tp1498 +Rp1499 +ag2 +(S'0.557' +p1500 +tp1501 +Rp1502 +ag2 +(g3 +tp1503 +Rp1504 +aa(lp1505 +g2 +(g1313 +tp1506 +Rp1507 +ag2 +(S'0.565' +p1508 +tp1509 +Rp1510 +ag2 +(g3 +tp1511 +Rp1512 +aa(lp1513 +g2 +(g1313 +tp1514 +Rp1515 +ag2 +(S'0.573' +p1516 +tp1517 +Rp1518 +ag2 +(g3 +tp1519 +Rp1520 +aa(lp1521 +g2 +(g1313 +tp1522 +Rp1523 +ag2 +(S'0.580' +p1524 +tp1525 +Rp1526 +ag2 +(g3 +tp1527 +Rp1528 +aa(lp1529 +g2 +(g1313 +tp1530 +Rp1531 +ag2 +(S'0.588' +p1532 +tp1533 +Rp1534 +ag2 +(g3 +tp1535 +Rp1536 +aa(lp1537 +g2 +(g1313 +tp1538 +Rp1539 +ag2 +(S'0.596' +p1540 +tp1541 +Rp1542 +ag2 +(g3 +tp1543 +Rp1544 +aa(lp1545 +g2 +(g1313 +tp1546 +Rp1547 +ag2 +(S'0.604' +p1548 +tp1549 +Rp1550 +ag2 +(g3 +tp1551 +Rp1552 +aa(lp1553 +g2 +(g1313 +tp1554 +Rp1555 +ag2 +(S'0.612' +p1556 +tp1557 +Rp1558 +ag2 +(g3 +tp1559 +Rp1560 +aa(lp1561 +g2 +(g1313 +tp1562 +Rp1563 +ag2 +(S'0.620' +p1564 +tp1565 +Rp1566 +ag2 +(g3 +tp1567 +Rp1568 +aa(lp1569 +g2 +(g1313 +tp1570 +Rp1571 +ag2 +(S'0.627' +p1572 +tp1573 +Rp1574 +ag2 +(g3 +tp1575 +Rp1576 +aa(lp1577 +g2 +(g1313 +tp1578 +Rp1579 +ag2 +(S'0.635' +p1580 +tp1581 +Rp1582 +ag2 +(g3 +tp1583 +Rp1584 +aa(lp1585 +g2 +(g1313 +tp1586 +Rp1587 +ag2 +(S'0.643' +p1588 +tp1589 +Rp1590 +ag2 +(g3 +tp1591 +Rp1592 +aa(lp1593 +g2 +(g1313 +tp1594 +Rp1595 +ag2 +(S'0.651' +p1596 +tp1597 +Rp1598 +ag2 +(g3 +tp1599 +Rp1600 +aa(lp1601 +g2 +(g1313 +tp1602 +Rp1603 +ag2 +(S'0.659' +p1604 +tp1605 +Rp1606 +ag2 +(g3 +tp1607 +Rp1608 +aa(lp1609 +g2 +(g1313 +tp1610 +Rp1611 +ag2 +(S'0.667' +p1612 +tp1613 +Rp1614 +ag2 +(g3 +tp1615 +Rp1616 +aa(lp1617 +g2 +(g1313 +tp1618 +Rp1619 +ag2 +(S'0.675' +p1620 +tp1621 +Rp1622 +ag2 +(g3 +tp1623 +Rp1624 +aa(lp1625 +g2 +(g1313 +tp1626 +Rp1627 +ag2 +(S'0.682' +p1628 +tp1629 +Rp1630 +ag2 +(g3 +tp1631 +Rp1632 +aa(lp1633 +g2 +(g1313 +tp1634 +Rp1635 +ag2 +(S'0.690' +p1636 +tp1637 +Rp1638 +ag2 +(g3 +tp1639 +Rp1640 +aa(lp1641 +g2 +(g1313 +tp1642 +Rp1643 +ag2 +(S'0.698' +p1644 +tp1645 +Rp1646 +ag2 +(g3 +tp1647 +Rp1648 +aa(lp1649 +g2 +(g1313 +tp1650 +Rp1651 +ag2 +(S'0.706' +p1652 +tp1653 +Rp1654 +ag2 +(g3 +tp1655 +Rp1656 +aa(lp1657 +g2 +(g1313 +tp1658 +Rp1659 +ag2 +(S'0.714' +p1660 +tp1661 +Rp1662 +ag2 +(g3 +tp1663 +Rp1664 +aa(lp1665 +g2 +(g1313 +tp1666 +Rp1667 +ag2 +(S'0.722' +p1668 +tp1669 +Rp1670 +ag2 +(g3 +tp1671 +Rp1672 +aa(lp1673 +g2 +(g1313 +tp1674 +Rp1675 +ag2 +(S'0.729' +p1676 +tp1677 +Rp1678 +ag2 +(g3 +tp1679 +Rp1680 +aa(lp1681 +g2 +(g1313 +tp1682 +Rp1683 +ag2 +(S'0.737' +p1684 +tp1685 +Rp1686 +ag2 +(g3 +tp1687 +Rp1688 +aa(lp1689 +g2 +(g1313 +tp1690 +Rp1691 +ag2 +(S'0.745' +p1692 +tp1693 +Rp1694 +ag2 +(g3 +tp1695 +Rp1696 +aa(lp1697 +g2 +(g1313 +tp1698 +Rp1699 +ag2 +(S'0.753' +p1700 +tp1701 +Rp1702 +ag2 +(g3 +tp1703 +Rp1704 +aa(lp1705 +g2 +(g1313 +tp1706 +Rp1707 +ag2 +(S'0.761' +p1708 +tp1709 +Rp1710 +ag2 +(g3 +tp1711 +Rp1712 +aa(lp1713 +g2 +(g1313 +tp1714 +Rp1715 +ag2 +(S'0.769' +p1716 +tp1717 +Rp1718 +ag2 +(g3 +tp1719 +Rp1720 +aa(lp1721 +g2 +(g1313 +tp1722 +Rp1723 +ag2 +(S'0.776' +p1724 +tp1725 +Rp1726 +ag2 +(g3 +tp1727 +Rp1728 +aa(lp1729 +g2 +(g1313 +tp1730 +Rp1731 +ag2 +(S'0.784' +p1732 +tp1733 +Rp1734 +ag2 +(g3 +tp1735 +Rp1736 +aa(lp1737 +g2 +(g1313 +tp1738 +Rp1739 +ag2 +(S'0.792' +p1740 +tp1741 +Rp1742 +ag2 +(g3 +tp1743 +Rp1744 +aa(lp1745 +g2 +(g1313 +tp1746 +Rp1747 +ag2 +(S'0.8' +p1748 +tp1749 +Rp1750 +ag2 +(g3 +tp1751 +Rp1752 +aa(lp1753 +g2 +(g1313 +tp1754 +Rp1755 +ag2 +(S'0.808' +p1756 +tp1757 +Rp1758 +ag2 +(g3 +tp1759 +Rp1760 +aa(lp1761 +g2 +(g1313 +tp1762 +Rp1763 +ag2 +(S'0.816' +p1764 +tp1765 +Rp1766 +ag2 +(g3 +tp1767 +Rp1768 +aa(lp1769 +g2 +(g1313 +tp1770 +Rp1771 +ag2 +(S'0.824' +p1772 +tp1773 +Rp1774 +ag2 +(g3 +tp1775 +Rp1776 +aa(lp1777 +g2 +(g1313 +tp1778 +Rp1779 +ag2 +(S'0.831' +p1780 +tp1781 +Rp1782 +ag2 +(g3 +tp1783 +Rp1784 +aa(lp1785 +g2 +(g1313 +tp1786 +Rp1787 +ag2 +(S'0.839' +p1788 +tp1789 +Rp1790 +ag2 +(g3 +tp1791 +Rp1792 +aa(lp1793 +g2 +(g1313 +tp1794 +Rp1795 +ag2 +(S'0.847' +p1796 +tp1797 +Rp1798 +ag2 +(g3 +tp1799 +Rp1800 +aa(lp1801 +g2 +(g1313 +tp1802 +Rp1803 +ag2 +(S'0.855' +p1804 +tp1805 +Rp1806 +ag2 +(g3 +tp1807 +Rp1808 +aa(lp1809 +g2 +(g1313 +tp1810 +Rp1811 +ag2 +(S'0.863' +p1812 +tp1813 +Rp1814 +ag2 +(g3 +tp1815 +Rp1816 +aa(lp1817 +g2 +(g1313 +tp1818 +Rp1819 +ag2 +(S'0.871' +p1820 +tp1821 +Rp1822 +ag2 +(g3 +tp1823 +Rp1824 +aa(lp1825 +g2 +(g1313 +tp1826 +Rp1827 +ag2 +(S'0.878' +p1828 +tp1829 +Rp1830 +ag2 +(g3 +tp1831 +Rp1832 +aa(lp1833 +g2 +(g1313 +tp1834 +Rp1835 +ag2 +(S'0.886' +p1836 +tp1837 +Rp1838 +ag2 +(S'0.0235' +p1839 +tp1840 +Rp1841 +aa(lp1842 +g2 +(g1313 +tp1843 +Rp1844 +ag2 +(S'0.894' +p1845 +tp1846 +Rp1847 +ag2 +(S'0.0510' +p1848 +tp1849 +Rp1850 +aa(lp1851 +g2 +(g1313 +tp1852 +Rp1853 +ag2 +(S'0.902' +p1854 +tp1855 +Rp1856 +ag2 +(S'0.0745' +p1857 +tp1858 +Rp1859 +aa(lp1860 +g2 +(g1313 +tp1861 +Rp1862 +ag2 +(S'0.910' +p1863 +tp1864 +Rp1865 +ag2 +(S'0.102' +p1866 +tp1867 +Rp1868 +aa(lp1869 +g2 +(g1313 +tp1870 +Rp1871 +ag2 +(S'0.918' +p1872 +tp1873 +Rp1874 +ag2 +(S'0.125' +p1875 +tp1876 +Rp1877 +aa(lp1878 +g2 +(g1313 +tp1879 +Rp1880 +ag2 +(S'0.925' +p1881 +tp1882 +Rp1883 +ag2 +(S'0.149' +p1884 +tp1885 +Rp1886 +aa(lp1887 +g2 +(g1313 +tp1888 +Rp1889 +ag2 +(S'0.933' +p1890 +tp1891 +Rp1892 +ag2 +(S'0.176' +p1893 +tp1894 +Rp1895 +aa(lp1896 +g2 +(g1313 +tp1897 +Rp1898 +ag2 +(S'0.941' +p1899 +tp1900 +Rp1901 +ag2 +(S'0.2' +p1902 +tp1903 +Rp1904 +aa(lp1905 +g2 +(g1313 +tp1906 +Rp1907 +ag2 +(S'0.949' +p1908 +tp1909 +Rp1910 +ag2 +(S'0.224' +p1911 +tp1912 +Rp1913 +aa(lp1914 +g2 +(g1313 +tp1915 +Rp1916 +ag2 +(S'0.957' +p1917 +tp1918 +Rp1919 +ag2 +(S'0.251' +p1920 +tp1921 +Rp1922 +aa(lp1923 +g2 +(g1313 +tp1924 +Rp1925 +ag2 +(S'0.965' +p1926 +tp1927 +Rp1928 +ag2 +(S'0.275' +p1929 +tp1930 +Rp1931 +aa(lp1932 +g2 +(g1313 +tp1933 +Rp1934 +ag2 +(S'0.973' +p1935 +tp1936 +Rp1937 +ag2 +(S'0.298' +p1938 +tp1939 +Rp1940 +aa(lp1941 +g2 +(g1313 +tp1942 +Rp1943 +ag2 +(S'0.980' +p1944 +tp1945 +Rp1946 +ag2 +(S'0.325' +p1947 +tp1948 +Rp1949 +aa(lp1950 +g2 +(g1313 +tp1951 +Rp1952 +ag2 +(S'0.988' +p1953 +tp1954 +Rp1955 +ag2 +(S'0.349' +p1956 +tp1957 +Rp1958 +aa(lp1959 +g2 +(g1313 +tp1960 +Rp1961 +ag2 +(S'0.996' +p1962 +tp1963 +Rp1964 +ag2 +(S'0.376' +p1965 +tp1966 +Rp1967 +aa(lp1968 +g2 +(g1313 +tp1969 +Rp1970 +ag2 +(g1313 +tp1971 +Rp1972 +ag2 +(S'0.4' +p1973 +tp1974 +Rp1975 +aa(lp1976 +g2 +(g1313 +tp1977 +Rp1978 +ag2 +(g1313 +tp1979 +Rp1980 +ag2 +(S'0.424' +p1981 +tp1982 +Rp1983 +aa(lp1984 +g2 +(g1313 +tp1985 +Rp1986 +ag2 +(g1313 +tp1987 +Rp1988 +ag2 +(S'0.451' +p1989 +tp1990 +Rp1991 +aa(lp1992 +g2 +(g1313 +tp1993 +Rp1994 +ag2 +(g1313 +tp1995 +Rp1996 +ag2 +(S'0.475' +p1997 +tp1998 +Rp1999 +aa(lp2000 +g2 +(g1313 +tp2001 +Rp2002 +ag2 +(g1313 +tp2003 +Rp2004 +ag2 +(S'0.502' +p2005 +tp2006 +Rp2007 +aa(lp2008 +g2 +(g1313 +tp2009 +Rp2010 +ag2 +(g1313 +tp2011 +Rp2012 +ag2 +(S'0.525' +p2013 +tp2014 +Rp2015 +aa(lp2016 +g2 +(g1313 +tp2017 +Rp2018 +ag2 +(g1313 +tp2019 +Rp2020 +ag2 +(S'0.549' +p2021 +tp2022 +Rp2023 +aa(lp2024 +g2 +(g1313 +tp2025 +Rp2026 +ag2 +(g1313 +tp2027 +Rp2028 +ag2 +(S'0.576' +p2029 +tp2030 +Rp2031 +aa(lp2032 +g2 +(g1313 +tp2033 +Rp2034 +ag2 +(g1313 +tp2035 +Rp2036 +ag2 +(S'0.6' +p2037 +tp2038 +Rp2039 +aa(lp2040 +g2 +(g1313 +tp2041 +Rp2042 +ag2 +(g1313 +tp2043 +Rp2044 +ag2 +(S'0.624' +p2045 +tp2046 +Rp2047 +aa(lp2048 +g2 +(g1313 +tp2049 +Rp2050 +ag2 +(g1313 +tp2051 +Rp2052 +ag2 +(S'0.651' +p2053 +tp2054 +Rp2055 +aa(lp2056 +g2 +(g1313 +tp2057 +Rp2058 +ag2 +(g1313 +tp2059 +Rp2060 +ag2 +(S'0.675' +p2061 +tp2062 +Rp2063 +aa(lp2064 +g2 +(g1313 +tp2065 +Rp2066 +ag2 +(g1313 +tp2067 +Rp2068 +ag2 +(S'0.698' +p2069 +tp2070 +Rp2071 +aa(lp2072 +g2 +(g1313 +tp2073 +Rp2074 +ag2 +(g1313 +tp2075 +Rp2076 +ag2 +(S'0.725' +p2077 +tp2078 +Rp2079 +aa(lp2080 +g2 +(g1313 +tp2081 +Rp2082 +ag2 +(g1313 +tp2083 +Rp2084 +ag2 +(S'0.749' +p2085 +tp2086 +Rp2087 +aa(lp2088 +g2 +(g1313 +tp2089 +Rp2090 +ag2 +(g1313 +tp2091 +Rp2092 +ag2 +(S'0.776' +p2093 +tp2094 +Rp2095 +aa(lp2096 +g2 +(g1313 +tp2097 +Rp2098 +ag2 +(g1313 +tp2099 +Rp2100 +ag2 +(S'0.8' +p2101 +tp2102 +Rp2103 +aa(lp2104 +g2 +(g1313 +tp2105 +Rp2106 +ag2 +(g1313 +tp2107 +Rp2108 +ag2 +(S'0.824' +p2109 +tp2110 +Rp2111 +aa(lp2112 +g2 +(g1313 +tp2113 +Rp2114 +ag2 +(g1313 +tp2115 +Rp2116 +ag2 +(S'0.851' +p2117 +tp2118 +Rp2119 +aa(lp2120 +g2 +(g1313 +tp2121 +Rp2122 +ag2 +(g1313 +tp2123 +Rp2124 +ag2 +(S'0.875' +p2125 +tp2126 +Rp2127 +aa(lp2128 +g2 +(g1313 +tp2129 +Rp2130 +ag2 +(g1313 +tp2131 +Rp2132 +ag2 +(S'0.902' +p2133 +tp2134 +Rp2135 +aa(lp2136 +g2 +(g1313 +tp2137 +Rp2138 +ag2 +(g1313 +tp2139 +Rp2140 +ag2 +(S'0.925' +p2141 +tp2142 +Rp2143 +aa(lp2144 +g2 +(g1313 +tp2145 +Rp2146 +ag2 +(g1313 +tp2147 +Rp2148 +ag2 +(S'0.949' +p2149 +tp2150 +Rp2151 +aa(lp2152 +g2 +(g1313 +tp2153 +Rp2154 +ag2 +(g1313 +tp2155 +Rp2156 +ag2 +(S'0.976' +p2157 +tp2158 +Rp2159 +aa(lp2160 +g2 +(g1313 +tp2161 +Rp2162 +ag2 +(g1313 +tp2163 +Rp2164 +ag2 +(g1313 +tp2165 +Rp2166 +aa(lp2167 +g2 +(g1313 +tp2168 +Rp2169 +ag2 +(g1313 +tp2170 +Rp2171 +ag2 +(g1313 +tp2172 +Rp2173 +aa(lp2174 +g2 +(g1313 +tp2175 +Rp2176 +ag2 +(g1313 +tp2177 +Rp2178 +ag2 +(g1313 +tp2179 +Rp2180 +aa(lp2181 +g2 +(g1313 +tp2182 +Rp2183 +ag2 +(g1313 +tp2184 +Rp2185 +ag2 +(g1313 +tp2186 +Rp2187 +aa(lp2188 +g2 +(g1313 +tp2189 +Rp2190 +ag2 +(g1313 +tp2191 +Rp2192 +ag2 +(g1313 +tp2193 +Rp2194 +aa(lp2195 +g2 +(g1313 +tp2196 +Rp2197 +ag2 +(g1313 +tp2198 +Rp2199 +ag2 +(g1313 +tp2200 +Rp2201 +aa(lp2202 +g2 +(g1313 +tp2203 +Rp2204 +ag2 +(g1313 +tp2205 +Rp2206 +ag2 +(g1313 +tp2207 +Rp2208 +aa(lp2209 +g2 +(g1313 +tp2210 +Rp2211 +ag2 +(g1313 +tp2212 +Rp2213 +ag2 +(g1313 +tp2214 +Rp2215 +aa. \ No newline at end of file diff --git a/moose-gui/colormaps/greenfire b/moose-gui/colormaps/greenfire new file mode 100644 index 0000000000000000000000000000000000000000..2975e889b453056d5d8834292428d22c0cda6ca5 --- /dev/null +++ b/moose-gui/colormaps/greenfire @@ -0,0 +1,3714 @@ +(lp0 +(lp1 +cdecimal +Decimal +p2 +(S'0' +p3 +tp4 +Rp5 +ag2 +(g3 +tp6 +Rp7 +ag2 +(g3 +tp8 +Rp9 +aa(lp10 +g2 +(g3 +tp11 +Rp12 +ag2 +(S'0.00784' +p13 +tp14 +Rp15 +ag2 +(S'0.0118' +p16 +tp17 +Rp18 +aa(lp19 +g2 +(g3 +tp20 +Rp21 +ag2 +(S'0.0157' +p22 +tp23 +Rp24 +ag2 +(S'0.0196' +p25 +tp26 +Rp27 +aa(lp28 +g2 +(g3 +tp29 +Rp30 +ag2 +(S'0.0235' +p31 +tp32 +Rp33 +ag2 +(S'0.0314' +p34 +tp35 +Rp36 +aa(lp37 +g2 +(g3 +tp38 +Rp39 +ag2 +(S'0.0314' +p40 +tp41 +Rp42 +ag2 +(S'0.0431' +p43 +tp44 +Rp45 +aa(lp46 +g2 +(g3 +tp47 +Rp48 +ag2 +(S'0.0392' +p49 +tp50 +Rp51 +ag2 +(S'0.0510' +p52 +tp53 +Rp54 +aa(lp55 +g2 +(g3 +tp56 +Rp57 +ag2 +(S'0.0471' +p58 +tp59 +Rp60 +ag2 +(S'0.0627' +p61 +tp62 +Rp63 +aa(lp64 +g2 +(g3 +tp65 +Rp66 +ag2 +(S'0.0549' +p67 +tp68 +Rp69 +ag2 +(S'0.0745' +p70 +tp71 +Rp72 +aa(lp73 +g2 +(g3 +tp74 +Rp75 +ag2 +(S'0.0627' +p76 +tp77 +Rp78 +ag2 +(S'0.0824' +p79 +tp80 +Rp81 +aa(lp82 +g2 +(g3 +tp83 +Rp84 +ag2 +(S'0.0706' +p85 +tp86 +Rp87 +ag2 +(S'0.0941' +p88 +tp89 +Rp90 +aa(lp91 +g2 +(g3 +tp92 +Rp93 +ag2 +(S'0.0784' +p94 +tp95 +Rp96 +ag2 +(S'0.106' +p97 +tp98 +Rp99 +aa(lp100 +g2 +(g3 +tp101 +Rp102 +ag2 +(S'0.0863' +p103 +tp104 +Rp105 +ag2 +(S'0.114' +p106 +tp107 +Rp108 +aa(lp109 +g2 +(g3 +tp110 +Rp111 +ag2 +(S'0.0941' +p112 +tp113 +Rp114 +ag2 +(S'0.125' +p115 +tp116 +Rp117 +aa(lp118 +g2 +(g3 +tp119 +Rp120 +ag2 +(S'0.102' +p121 +tp122 +Rp123 +ag2 +(S'0.137' +p124 +tp125 +Rp126 +aa(lp127 +g2 +(g3 +tp128 +Rp129 +ag2 +(S'0.110' +p130 +tp131 +Rp132 +ag2 +(S'0.145' +p133 +tp134 +Rp135 +aa(lp136 +g2 +(g3 +tp137 +Rp138 +ag2 +(S'0.118' +p139 +tp140 +Rp141 +ag2 +(S'0.157' +p142 +tp143 +Rp144 +aa(lp145 +g2 +(g3 +tp146 +Rp147 +ag2 +(S'0.125' +p148 +tp149 +Rp150 +ag2 +(S'0.165' +p151 +tp152 +Rp153 +aa(lp154 +g2 +(g3 +tp155 +Rp156 +ag2 +(S'0.133' +p157 +tp158 +Rp159 +ag2 +(S'0.176' +p160 +tp161 +Rp162 +aa(lp163 +g2 +(g3 +tp164 +Rp165 +ag2 +(S'0.141' +p166 +tp167 +Rp168 +ag2 +(S'0.188' +p169 +tp170 +Rp171 +aa(lp172 +g2 +(g3 +tp173 +Rp174 +ag2 +(S'0.149' +p175 +tp176 +Rp177 +ag2 +(S'0.196' +p178 +tp179 +Rp180 +aa(lp181 +g2 +(g3 +tp182 +Rp183 +ag2 +(S'0.157' +p184 +tp185 +Rp186 +ag2 +(S'0.208' +p187 +tp188 +Rp189 +aa(lp190 +g2 +(g3 +tp191 +Rp192 +ag2 +(S'0.165' +p193 +tp194 +Rp195 +ag2 +(S'0.220' +p196 +tp197 +Rp198 +aa(lp199 +g2 +(g3 +tp200 +Rp201 +ag2 +(S'0.173' +p202 +tp203 +Rp204 +ag2 +(S'0.227' +p205 +tp206 +Rp207 +aa(lp208 +g2 +(g3 +tp209 +Rp210 +ag2 +(S'0.180' +p211 +tp212 +Rp213 +ag2 +(S'0.239' +p214 +tp215 +Rp216 +aa(lp217 +g2 +(g3 +tp218 +Rp219 +ag2 +(S'0.188' +p220 +tp221 +Rp222 +ag2 +(S'0.251' +p223 +tp224 +Rp225 +aa(lp226 +g2 +(g3 +tp227 +Rp228 +ag2 +(S'0.196' +p229 +tp230 +Rp231 +ag2 +(S'0.259' +p232 +tp233 +Rp234 +aa(lp235 +g2 +(g3 +tp236 +Rp237 +ag2 +(S'0.204' +p238 +tp239 +Rp240 +ag2 +(S'0.271' +p241 +tp242 +Rp243 +aa(lp244 +g2 +(g3 +tp245 +Rp246 +ag2 +(S'0.212' +p247 +tp248 +Rp249 +ag2 +(S'0.282' +p250 +tp251 +Rp252 +aa(lp253 +g2 +(g3 +tp254 +Rp255 +ag2 +(S'0.220' +p256 +tp257 +Rp258 +ag2 +(S'0.290' +p259 +tp260 +Rp261 +aa(lp262 +g2 +(g3 +tp263 +Rp264 +ag2 +(S'0.227' +p265 +tp266 +Rp267 +ag2 +(S'0.302' +p268 +tp269 +Rp270 +aa(lp271 +g2 +(g3 +tp272 +Rp273 +ag2 +(S'0.235' +p274 +tp275 +Rp276 +ag2 +(S'0.314' +p277 +tp278 +Rp279 +aa(lp280 +g2 +(g3 +tp281 +Rp282 +ag2 +(S'0.243' +p283 +tp284 +Rp285 +ag2 +(S'0.322' +p286 +tp287 +Rp288 +aa(lp289 +g2 +(g3 +tp290 +Rp291 +ag2 +(S'0.251' +p292 +tp293 +Rp294 +ag2 +(S'0.333' +p295 +tp296 +Rp297 +aa(lp298 +g2 +(g3 +tp299 +Rp300 +ag2 +(S'0.259' +p301 +tp302 +Rp303 +ag2 +(S'0.345' +p304 +tp305 +Rp306 +aa(lp307 +g2 +(g3 +tp308 +Rp309 +ag2 +(S'0.267' +p310 +tp311 +Rp312 +ag2 +(S'0.353' +p313 +tp314 +Rp315 +aa(lp316 +g2 +(g3 +tp317 +Rp318 +ag2 +(S'0.275' +p319 +tp320 +Rp321 +ag2 +(S'0.365' +p322 +tp323 +Rp324 +aa(lp325 +g2 +(g3 +tp326 +Rp327 +ag2 +(S'0.282' +p328 +tp329 +Rp330 +ag2 +(S'0.376' +p331 +tp332 +Rp333 +aa(lp334 +g2 +(g3 +tp335 +Rp336 +ag2 +(S'0.290' +p337 +tp338 +Rp339 +ag2 +(S'0.384' +p340 +tp341 +Rp342 +aa(lp343 +g2 +(g3 +tp344 +Rp345 +ag2 +(S'0.298' +p346 +tp347 +Rp348 +ag2 +(S'0.396' +p349 +tp350 +Rp351 +aa(lp352 +g2 +(g3 +tp353 +Rp354 +ag2 +(S'0.306' +p355 +tp356 +Rp357 +ag2 +(S'0.408' +p358 +tp359 +Rp360 +aa(lp361 +g2 +(g3 +tp362 +Rp363 +ag2 +(S'0.314' +p364 +tp365 +Rp366 +ag2 +(S'0.416' +p367 +tp368 +Rp369 +aa(lp370 +g2 +(g3 +tp371 +Rp372 +ag2 +(S'0.322' +p373 +tp374 +Rp375 +ag2 +(S'0.427' +p376 +tp377 +Rp378 +aa(lp379 +g2 +(g3 +tp380 +Rp381 +ag2 +(S'0.329' +p382 +tp383 +Rp384 +ag2 +(S'0.439' +p385 +tp386 +Rp387 +aa(lp388 +g2 +(g3 +tp389 +Rp390 +ag2 +(S'0.337' +p391 +tp392 +Rp393 +ag2 +(S'0.447' +p394 +tp395 +Rp396 +aa(lp397 +g2 +(g3 +tp398 +Rp399 +ag2 +(S'0.345' +p400 +tp401 +Rp402 +ag2 +(S'0.459' +p403 +tp404 +Rp405 +aa(lp406 +g2 +(g3 +tp407 +Rp408 +ag2 +(S'0.353' +p409 +tp410 +Rp411 +ag2 +(S'0.471' +p412 +tp413 +Rp414 +aa(lp415 +g2 +(g3 +tp416 +Rp417 +ag2 +(S'0.361' +p418 +tp419 +Rp420 +ag2 +(S'0.478' +p421 +tp422 +Rp423 +aa(lp424 +g2 +(g3 +tp425 +Rp426 +ag2 +(S'0.369' +p427 +tp428 +Rp429 +ag2 +(S'0.490' +p430 +tp431 +Rp432 +aa(lp433 +g2 +(g3 +tp434 +Rp435 +ag2 +(S'0.376' +p436 +tp437 +Rp438 +ag2 +(S'0.502' +p439 +tp440 +Rp441 +aa(lp442 +g2 +(g3 +tp443 +Rp444 +ag2 +(S'0.384' +p445 +tp446 +Rp447 +ag2 +(S'0.510' +p448 +tp449 +Rp450 +aa(lp451 +g2 +(g3 +tp452 +Rp453 +ag2 +(S'0.392' +p454 +tp455 +Rp456 +ag2 +(S'0.522' +p457 +tp458 +Rp459 +aa(lp460 +g2 +(g3 +tp461 +Rp462 +ag2 +(S'0.4' +p463 +tp464 +Rp465 +ag2 +(S'0.529' +p466 +tp467 +Rp468 +aa(lp469 +g2 +(g3 +tp470 +Rp471 +ag2 +(S'0.408' +p472 +tp473 +Rp474 +ag2 +(S'0.541' +p475 +tp476 +Rp477 +aa(lp478 +g2 +(g3 +tp479 +Rp480 +ag2 +(S'0.416' +p481 +tp482 +Rp483 +ag2 +(S'0.553' +p484 +tp485 +Rp486 +aa(lp487 +g2 +(g3 +tp488 +Rp489 +ag2 +(S'0.424' +p490 +tp491 +Rp492 +ag2 +(S'0.561' +p493 +tp494 +Rp495 +aa(lp496 +g2 +(g3 +tp497 +Rp498 +ag2 +(S'0.431' +p499 +tp500 +Rp501 +ag2 +(S'0.573' +p502 +tp503 +Rp504 +aa(lp505 +g2 +(g3 +tp506 +Rp507 +ag2 +(S'0.439' +p508 +tp509 +Rp510 +ag2 +(S'0.584' +p511 +tp512 +Rp513 +aa(lp514 +g2 +(g3 +tp515 +Rp516 +ag2 +(S'0.447' +p517 +tp518 +Rp519 +ag2 +(S'0.592' +p520 +tp521 +Rp522 +aa(lp523 +g2 +(g3 +tp524 +Rp525 +ag2 +(S'0.455' +p526 +tp527 +Rp528 +ag2 +(S'0.604' +p529 +tp530 +Rp531 +aa(lp532 +g2 +(g3 +tp533 +Rp534 +ag2 +(S'0.463' +p535 +tp536 +Rp537 +ag2 +(S'0.616' +p538 +tp539 +Rp540 +aa(lp541 +g2 +(g3 +tp542 +Rp543 +ag2 +(S'0.471' +p544 +tp545 +Rp546 +ag2 +(S'0.624' +p547 +tp548 +Rp549 +aa(lp550 +g2 +(g3 +tp551 +Rp552 +ag2 +(S'0.478' +p553 +tp554 +Rp555 +ag2 +(S'0.635' +p556 +tp557 +Rp558 +aa(lp559 +g2 +(g3 +tp560 +Rp561 +ag2 +(S'0.486' +p562 +tp563 +Rp564 +ag2 +(S'0.647' +p565 +tp566 +Rp567 +aa(lp568 +g2 +(g3 +tp569 +Rp570 +ag2 +(S'0.494' +p571 +tp572 +Rp573 +ag2 +(S'0.655' +p574 +tp575 +Rp576 +aa(lp577 +g2 +(g3 +tp578 +Rp579 +ag2 +(S'0.502' +p580 +tp581 +Rp582 +ag2 +(S'0.667' +p583 +tp584 +Rp585 +aa(lp586 +g2 +(g3 +tp587 +Rp588 +ag2 +(S'0.510' +p589 +tp590 +Rp591 +ag2 +(S'0.655' +p592 +tp593 +Rp594 +aa(lp595 +g2 +(g3 +tp596 +Rp597 +ag2 +(S'0.518' +p598 +tp599 +Rp600 +ag2 +(S'0.647' +p601 +tp602 +Rp603 +aa(lp604 +g2 +(g3 +tp605 +Rp606 +ag2 +(S'0.525' +p607 +tp608 +Rp609 +ag2 +(S'0.635' +p610 +tp611 +Rp612 +aa(lp613 +g2 +(g3 +tp614 +Rp615 +ag2 +(S'0.533' +p616 +tp617 +Rp618 +ag2 +(S'0.624' +p619 +tp620 +Rp621 +aa(lp622 +g2 +(g3 +tp623 +Rp624 +ag2 +(S'0.541' +p625 +tp626 +Rp627 +ag2 +(S'0.616' +p628 +tp629 +Rp630 +aa(lp631 +g2 +(g3 +tp632 +Rp633 +ag2 +(S'0.549' +p634 +tp635 +Rp636 +ag2 +(S'0.604' +p637 +tp638 +Rp639 +aa(lp640 +g2 +(g3 +tp641 +Rp642 +ag2 +(S'0.557' +p643 +tp644 +Rp645 +ag2 +(S'0.592' +p646 +tp647 +Rp648 +aa(lp649 +g2 +(g3 +tp650 +Rp651 +ag2 +(S'0.565' +p652 +tp653 +Rp654 +ag2 +(S'0.584' +p655 +tp656 +Rp657 +aa(lp658 +g2 +(g3 +tp659 +Rp660 +ag2 +(S'0.573' +p661 +tp662 +Rp663 +ag2 +(S'0.573' +p664 +tp665 +Rp666 +aa(lp667 +g2 +(g3 +tp668 +Rp669 +ag2 +(S'0.580' +p670 +tp671 +Rp672 +ag2 +(S'0.561' +p673 +tp674 +Rp675 +aa(lp676 +g2 +(g3 +tp677 +Rp678 +ag2 +(S'0.588' +p679 +tp680 +Rp681 +ag2 +(S'0.553' +p682 +tp683 +Rp684 +aa(lp685 +g2 +(g3 +tp686 +Rp687 +ag2 +(S'0.596' +p688 +tp689 +Rp690 +ag2 +(S'0.541' +p691 +tp692 +Rp693 +aa(lp694 +g2 +(g3 +tp695 +Rp696 +ag2 +(S'0.604' +p697 +tp698 +Rp699 +ag2 +(S'0.529' +p700 +tp701 +Rp702 +aa(lp703 +g2 +(g3 +tp704 +Rp705 +ag2 +(S'0.612' +p706 +tp707 +Rp708 +ag2 +(S'0.522' +p709 +tp710 +Rp711 +aa(lp712 +g2 +(g3 +tp713 +Rp714 +ag2 +(S'0.620' +p715 +tp716 +Rp717 +ag2 +(S'0.510' +p718 +tp719 +Rp720 +aa(lp721 +g2 +(g3 +tp722 +Rp723 +ag2 +(S'0.627' +p724 +tp725 +Rp726 +ag2 +(S'0.502' +p727 +tp728 +Rp729 +aa(lp730 +g2 +(g3 +tp731 +Rp732 +ag2 +(S'0.635' +p733 +tp734 +Rp735 +ag2 +(S'0.490' +p736 +tp737 +Rp738 +aa(lp739 +g2 +(g3 +tp740 +Rp741 +ag2 +(S'0.643' +p742 +tp743 +Rp744 +ag2 +(S'0.478' +p745 +tp746 +Rp747 +aa(lp748 +g2 +(g3 +tp749 +Rp750 +ag2 +(S'0.651' +p751 +tp752 +Rp753 +ag2 +(S'0.471' +p754 +tp755 +Rp756 +aa(lp757 +g2 +(g3 +tp758 +Rp759 +ag2 +(S'0.659' +p760 +tp761 +Rp762 +ag2 +(S'0.459' +p763 +tp764 +Rp765 +aa(lp766 +g2 +(g3 +tp767 +Rp768 +ag2 +(S'0.667' +p769 +tp770 +Rp771 +ag2 +(S'0.447' +p772 +tp773 +Rp774 +aa(lp775 +g2 +(g3 +tp776 +Rp777 +ag2 +(S'0.675' +p778 +tp779 +Rp780 +ag2 +(S'0.439' +p781 +tp782 +Rp783 +aa(lp784 +g2 +(g3 +tp785 +Rp786 +ag2 +(S'0.682' +p787 +tp788 +Rp789 +ag2 +(S'0.427' +p790 +tp791 +Rp792 +aa(lp793 +g2 +(g3 +tp794 +Rp795 +ag2 +(S'0.690' +p796 +tp797 +Rp798 +ag2 +(S'0.416' +p799 +tp800 +Rp801 +aa(lp802 +g2 +(g3 +tp803 +Rp804 +ag2 +(S'0.698' +p805 +tp806 +Rp807 +ag2 +(S'0.408' +p808 +tp809 +Rp810 +aa(lp811 +g2 +(g3 +tp812 +Rp813 +ag2 +(S'0.706' +p814 +tp815 +Rp816 +ag2 +(S'0.396' +p817 +tp818 +Rp819 +aa(lp820 +g2 +(g3 +tp821 +Rp822 +ag2 +(S'0.714' +p823 +tp824 +Rp825 +ag2 +(S'0.384' +p826 +tp827 +Rp828 +aa(lp829 +g2 +(g3 +tp830 +Rp831 +ag2 +(S'0.722' +p832 +tp833 +Rp834 +ag2 +(S'0.376' +p835 +tp836 +Rp837 +aa(lp838 +g2 +(g3 +tp839 +Rp840 +ag2 +(S'0.729' +p841 +tp842 +Rp843 +ag2 +(S'0.365' +p844 +tp845 +Rp846 +aa(lp847 +g2 +(g3 +tp848 +Rp849 +ag2 +(S'0.737' +p850 +tp851 +Rp852 +ag2 +(S'0.353' +p853 +tp854 +Rp855 +aa(lp856 +g2 +(g3 +tp857 +Rp858 +ag2 +(S'0.745' +p859 +tp860 +Rp861 +ag2 +(S'0.345' +p862 +tp863 +Rp864 +aa(lp865 +g2 +(g3 +tp866 +Rp867 +ag2 +(S'0.753' +p868 +tp869 +Rp870 +ag2 +(S'0.333' +p871 +tp872 +Rp873 +aa(lp874 +g2 +(g3 +tp875 +Rp876 +ag2 +(S'0.761' +p877 +tp878 +Rp879 +ag2 +(S'0.322' +p880 +tp881 +Rp882 +aa(lp883 +g2 +(g3 +tp884 +Rp885 +ag2 +(S'0.769' +p886 +tp887 +Rp888 +ag2 +(S'0.314' +p889 +tp890 +Rp891 +aa(lp892 +g2 +(g3 +tp893 +Rp894 +ag2 +(S'0.776' +p895 +tp896 +Rp897 +ag2 +(S'0.302' +p898 +tp899 +Rp900 +aa(lp901 +g2 +(g3 +tp902 +Rp903 +ag2 +(S'0.784' +p904 +tp905 +Rp906 +ag2 +(S'0.290' +p907 +tp908 +Rp909 +aa(lp910 +g2 +(g3 +tp911 +Rp912 +ag2 +(S'0.792' +p913 +tp914 +Rp915 +ag2 +(S'0.282' +p916 +tp917 +Rp918 +aa(lp919 +g2 +(g3 +tp920 +Rp921 +ag2 +(S'0.8' +p922 +tp923 +Rp924 +ag2 +(S'0.271' +p925 +tp926 +Rp927 +aa(lp928 +g2 +(g3 +tp929 +Rp930 +ag2 +(S'0.808' +p931 +tp932 +Rp933 +ag2 +(S'0.259' +p934 +tp935 +Rp936 +aa(lp937 +g2 +(g3 +tp938 +Rp939 +ag2 +(S'0.816' +p940 +tp941 +Rp942 +ag2 +(S'0.251' +p943 +tp944 +Rp945 +aa(lp946 +g2 +(g3 +tp947 +Rp948 +ag2 +(S'0.824' +p949 +tp950 +Rp951 +ag2 +(S'0.239' +p952 +tp953 +Rp954 +aa(lp955 +g2 +(g3 +tp956 +Rp957 +ag2 +(S'0.831' +p958 +tp959 +Rp960 +ag2 +(S'0.227' +p961 +tp962 +Rp963 +aa(lp964 +g2 +(g3 +tp965 +Rp966 +ag2 +(S'0.839' +p967 +tp968 +Rp969 +ag2 +(S'0.220' +p970 +tp971 +Rp972 +aa(lp973 +g2 +(g3 +tp974 +Rp975 +ag2 +(S'0.847' +p976 +tp977 +Rp978 +ag2 +(S'0.208' +p979 +tp980 +Rp981 +aa(lp982 +g2 +(g3 +tp983 +Rp984 +ag2 +(S'0.855' +p985 +tp986 +Rp987 +ag2 +(S'0.196' +p988 +tp989 +Rp990 +aa(lp991 +g2 +(g3 +tp992 +Rp993 +ag2 +(S'0.863' +p994 +tp995 +Rp996 +ag2 +(S'0.188' +p997 +tp998 +Rp999 +aa(lp1000 +g2 +(g3 +tp1001 +Rp1002 +ag2 +(S'0.871' +p1003 +tp1004 +Rp1005 +ag2 +(S'0.176' +p1006 +tp1007 +Rp1008 +aa(lp1009 +g2 +(g3 +tp1010 +Rp1011 +ag2 +(S'0.878' +p1012 +tp1013 +Rp1014 +ag2 +(S'0.165' +p1015 +tp1016 +Rp1017 +aa(lp1018 +g2 +(g3 +tp1019 +Rp1020 +ag2 +(S'0.886' +p1021 +tp1022 +Rp1023 +ag2 +(S'0.157' +p1024 +tp1025 +Rp1026 +aa(lp1027 +g2 +(g3 +tp1028 +Rp1029 +ag2 +(S'0.894' +p1030 +tp1031 +Rp1032 +ag2 +(S'0.145' +p1033 +tp1034 +Rp1035 +aa(lp1036 +g2 +(g3 +tp1037 +Rp1038 +ag2 +(S'0.902' +p1039 +tp1040 +Rp1041 +ag2 +(S'0.137' +p1042 +tp1043 +Rp1044 +aa(lp1045 +g2 +(g3 +tp1046 +Rp1047 +ag2 +(S'0.910' +p1048 +tp1049 +Rp1050 +ag2 +(S'0.125' +p1051 +tp1052 +Rp1053 +aa(lp1054 +g2 +(g3 +tp1055 +Rp1056 +ag2 +(S'0.918' +p1057 +tp1058 +Rp1059 +ag2 +(S'0.114' +p1060 +tp1061 +Rp1062 +aa(lp1063 +g2 +(g3 +tp1064 +Rp1065 +ag2 +(S'0.925' +p1066 +tp1067 +Rp1068 +ag2 +(S'0.106' +p1069 +tp1070 +Rp1071 +aa(lp1072 +g2 +(g3 +tp1073 +Rp1074 +ag2 +(S'0.933' +p1075 +tp1076 +Rp1077 +ag2 +(S'0.0941' +p1078 +tp1079 +Rp1080 +aa(lp1081 +g2 +(g3 +tp1082 +Rp1083 +ag2 +(S'0.941' +p1084 +tp1085 +Rp1086 +ag2 +(S'0.0824' +p1087 +tp1088 +Rp1089 +aa(lp1090 +g2 +(g3 +tp1091 +Rp1092 +ag2 +(S'0.949' +p1093 +tp1094 +Rp1095 +ag2 +(S'0.0745' +p1096 +tp1097 +Rp1098 +aa(lp1099 +g2 +(g3 +tp1100 +Rp1101 +ag2 +(S'0.957' +p1102 +tp1103 +Rp1104 +ag2 +(S'0.0627' +p1105 +tp1106 +Rp1107 +aa(lp1108 +g2 +(g3 +tp1109 +Rp1110 +ag2 +(S'0.965' +p1111 +tp1112 +Rp1113 +ag2 +(S'0.0510' +p1114 +tp1115 +Rp1116 +aa(lp1117 +g2 +(g3 +tp1118 +Rp1119 +ag2 +(S'0.973' +p1120 +tp1121 +Rp1122 +ag2 +(S'0.0431' +p1123 +tp1124 +Rp1125 +aa(lp1126 +g2 +(g3 +tp1127 +Rp1128 +ag2 +(S'0.980' +p1129 +tp1130 +Rp1131 +ag2 +(S'0.0314' +p1132 +tp1133 +Rp1134 +aa(lp1135 +g2 +(g3 +tp1136 +Rp1137 +ag2 +(S'0.988' +p1138 +tp1139 +Rp1140 +ag2 +(S'0.0196' +p1141 +tp1142 +Rp1143 +aa(lp1144 +g2 +(g3 +tp1145 +Rp1146 +ag2 +(S'0.996' +p1147 +tp1148 +Rp1149 +ag2 +(S'0.0118' +p1150 +tp1151 +Rp1152 +aa(lp1153 +g2 +(g3 +tp1154 +Rp1155 +ag2 +(S'1' +p1156 +tp1157 +Rp1158 +ag2 +(g3 +tp1159 +Rp1160 +aa(lp1161 +g2 +(S'0.0157' +p1162 +tp1163 +Rp1164 +ag2 +(g1156 +tp1165 +Rp1166 +ag2 +(g3 +tp1167 +Rp1168 +aa(lp1169 +g2 +(S'0.0314' +p1170 +tp1171 +Rp1172 +ag2 +(g1156 +tp1173 +Rp1174 +ag2 +(g3 +tp1175 +Rp1176 +aa(lp1177 +g2 +(S'0.0471' +p1178 +tp1179 +Rp1180 +ag2 +(g1156 +tp1181 +Rp1182 +ag2 +(g3 +tp1183 +Rp1184 +aa(lp1185 +g2 +(S'0.0627' +p1186 +tp1187 +Rp1188 +ag2 +(g1156 +tp1189 +Rp1190 +ag2 +(g3 +tp1191 +Rp1192 +aa(lp1193 +g2 +(S'0.0784' +p1194 +tp1195 +Rp1196 +ag2 +(g1156 +tp1197 +Rp1198 +ag2 +(g3 +tp1199 +Rp1200 +aa(lp1201 +g2 +(S'0.0941' +p1202 +tp1203 +Rp1204 +ag2 +(g1156 +tp1205 +Rp1206 +ag2 +(g3 +tp1207 +Rp1208 +aa(lp1209 +g2 +(S'0.110' +p1210 +tp1211 +Rp1212 +ag2 +(g1156 +tp1213 +Rp1214 +ag2 +(g3 +tp1215 +Rp1216 +aa(lp1217 +g2 +(S'0.125' +p1218 +tp1219 +Rp1220 +ag2 +(g1156 +tp1221 +Rp1222 +ag2 +(g3 +tp1223 +Rp1224 +aa(lp1225 +g2 +(S'0.141' +p1226 +tp1227 +Rp1228 +ag2 +(g1156 +tp1229 +Rp1230 +ag2 +(g3 +tp1231 +Rp1232 +aa(lp1233 +g2 +(S'0.157' +p1234 +tp1235 +Rp1236 +ag2 +(g1156 +tp1237 +Rp1238 +ag2 +(g3 +tp1239 +Rp1240 +aa(lp1241 +g2 +(S'0.173' +p1242 +tp1243 +Rp1244 +ag2 +(g1156 +tp1245 +Rp1246 +ag2 +(g3 +tp1247 +Rp1248 +aa(lp1249 +g2 +(S'0.188' +p1250 +tp1251 +Rp1252 +ag2 +(g1156 +tp1253 +Rp1254 +ag2 +(g3 +tp1255 +Rp1256 +aa(lp1257 +g2 +(S'0.204' +p1258 +tp1259 +Rp1260 +ag2 +(g1156 +tp1261 +Rp1262 +ag2 +(g3 +tp1263 +Rp1264 +aa(lp1265 +g2 +(S'0.220' +p1266 +tp1267 +Rp1268 +ag2 +(g1156 +tp1269 +Rp1270 +ag2 +(g3 +tp1271 +Rp1272 +aa(lp1273 +g2 +(S'0.235' +p1274 +tp1275 +Rp1276 +ag2 +(g1156 +tp1277 +Rp1278 +ag2 +(g3 +tp1279 +Rp1280 +aa(lp1281 +g2 +(S'0.251' +p1282 +tp1283 +Rp1284 +ag2 +(g1156 +tp1285 +Rp1286 +ag2 +(g3 +tp1287 +Rp1288 +aa(lp1289 +g2 +(S'0.267' +p1290 +tp1291 +Rp1292 +ag2 +(g1156 +tp1293 +Rp1294 +ag2 +(g3 +tp1295 +Rp1296 +aa(lp1297 +g2 +(S'0.282' +p1298 +tp1299 +Rp1300 +ag2 +(g1156 +tp1301 +Rp1302 +ag2 +(g3 +tp1303 +Rp1304 +aa(lp1305 +g2 +(S'0.298' +p1306 +tp1307 +Rp1308 +ag2 +(g1156 +tp1309 +Rp1310 +ag2 +(g3 +tp1311 +Rp1312 +aa(lp1313 +g2 +(S'0.314' +p1314 +tp1315 +Rp1316 +ag2 +(g1156 +tp1317 +Rp1318 +ag2 +(g3 +tp1319 +Rp1320 +aa(lp1321 +g2 +(S'0.329' +p1322 +tp1323 +Rp1324 +ag2 +(g1156 +tp1325 +Rp1326 +ag2 +(g3 +tp1327 +Rp1328 +aa(lp1329 +g2 +(S'0.345' +p1330 +tp1331 +Rp1332 +ag2 +(g1156 +tp1333 +Rp1334 +ag2 +(g3 +tp1335 +Rp1336 +aa(lp1337 +g2 +(S'0.361' +p1338 +tp1339 +Rp1340 +ag2 +(g1156 +tp1341 +Rp1342 +ag2 +(g3 +tp1343 +Rp1344 +aa(lp1345 +g2 +(S'0.376' +p1346 +tp1347 +Rp1348 +ag2 +(g1156 +tp1349 +Rp1350 +ag2 +(g3 +tp1351 +Rp1352 +aa(lp1353 +g2 +(S'0.392' +p1354 +tp1355 +Rp1356 +ag2 +(g1156 +tp1357 +Rp1358 +ag2 +(g3 +tp1359 +Rp1360 +aa(lp1361 +g2 +(S'0.408' +p1362 +tp1363 +Rp1364 +ag2 +(g1156 +tp1365 +Rp1366 +ag2 +(g3 +tp1367 +Rp1368 +aa(lp1369 +g2 +(S'0.424' +p1370 +tp1371 +Rp1372 +ag2 +(g1156 +tp1373 +Rp1374 +ag2 +(g3 +tp1375 +Rp1376 +aa(lp1377 +g2 +(S'0.439' +p1378 +tp1379 +Rp1380 +ag2 +(g1156 +tp1381 +Rp1382 +ag2 +(g3 +tp1383 +Rp1384 +aa(lp1385 +g2 +(S'0.455' +p1386 +tp1387 +Rp1388 +ag2 +(g1156 +tp1389 +Rp1390 +ag2 +(g3 +tp1391 +Rp1392 +aa(lp1393 +g2 +(S'0.471' +p1394 +tp1395 +Rp1396 +ag2 +(g1156 +tp1397 +Rp1398 +ag2 +(g3 +tp1399 +Rp1400 +aa(lp1401 +g2 +(S'0.486' +p1402 +tp1403 +Rp1404 +ag2 +(g1156 +tp1405 +Rp1406 +ag2 +(g3 +tp1407 +Rp1408 +aa(lp1409 +g2 +(S'0.502' +p1410 +tp1411 +Rp1412 +ag2 +(g1156 +tp1413 +Rp1414 +ag2 +(g3 +tp1415 +Rp1416 +aa(lp1417 +g2 +(S'0.518' +p1418 +tp1419 +Rp1420 +ag2 +(g1156 +tp1421 +Rp1422 +ag2 +(g3 +tp1423 +Rp1424 +aa(lp1425 +g2 +(S'0.533' +p1426 +tp1427 +Rp1428 +ag2 +(g1156 +tp1429 +Rp1430 +ag2 +(g3 +tp1431 +Rp1432 +aa(lp1433 +g2 +(S'0.549' +p1434 +tp1435 +Rp1436 +ag2 +(g1156 +tp1437 +Rp1438 +ag2 +(g3 +tp1439 +Rp1440 +aa(lp1441 +g2 +(S'0.565' +p1442 +tp1443 +Rp1444 +ag2 +(g1156 +tp1445 +Rp1446 +ag2 +(g3 +tp1447 +Rp1448 +aa(lp1449 +g2 +(S'0.580' +p1450 +tp1451 +Rp1452 +ag2 +(g1156 +tp1453 +Rp1454 +ag2 +(g3 +tp1455 +Rp1456 +aa(lp1457 +g2 +(S'0.596' +p1458 +tp1459 +Rp1460 +ag2 +(g1156 +tp1461 +Rp1462 +ag2 +(g3 +tp1463 +Rp1464 +aa(lp1465 +g2 +(S'0.612' +p1466 +tp1467 +Rp1468 +ag2 +(g1156 +tp1469 +Rp1470 +ag2 +(g3 +tp1471 +Rp1472 +aa(lp1473 +g2 +(S'0.627' +p1474 +tp1475 +Rp1476 +ag2 +(g1156 +tp1477 +Rp1478 +ag2 +(g3 +tp1479 +Rp1480 +aa(lp1481 +g2 +(S'0.643' +p1482 +tp1483 +Rp1484 +ag2 +(g1156 +tp1485 +Rp1486 +ag2 +(g3 +tp1487 +Rp1488 +aa(lp1489 +g2 +(S'0.659' +p1490 +tp1491 +Rp1492 +ag2 +(g1156 +tp1493 +Rp1494 +ag2 +(g3 +tp1495 +Rp1496 +aa(lp1497 +g2 +(S'0.675' +p1498 +tp1499 +Rp1500 +ag2 +(g1156 +tp1501 +Rp1502 +ag2 +(g3 +tp1503 +Rp1504 +aa(lp1505 +g2 +(S'0.690' +p1506 +tp1507 +Rp1508 +ag2 +(g1156 +tp1509 +Rp1510 +ag2 +(g3 +tp1511 +Rp1512 +aa(lp1513 +g2 +(S'0.706' +p1514 +tp1515 +Rp1516 +ag2 +(g1156 +tp1517 +Rp1518 +ag2 +(g3 +tp1519 +Rp1520 +aa(lp1521 +g2 +(S'0.722' +p1522 +tp1523 +Rp1524 +ag2 +(g1156 +tp1525 +Rp1526 +ag2 +(g3 +tp1527 +Rp1528 +aa(lp1529 +g2 +(S'0.737' +p1530 +tp1531 +Rp1532 +ag2 +(g1156 +tp1533 +Rp1534 +ag2 +(g3 +tp1535 +Rp1536 +aa(lp1537 +g2 +(S'0.753' +p1538 +tp1539 +Rp1540 +ag2 +(g1156 +tp1541 +Rp1542 +ag2 +(g3 +tp1543 +Rp1544 +aa(lp1545 +g2 +(S'0.769' +p1546 +tp1547 +Rp1548 +ag2 +(g1156 +tp1549 +Rp1550 +ag2 +(g3 +tp1551 +Rp1552 +aa(lp1553 +g2 +(S'0.784' +p1554 +tp1555 +Rp1556 +ag2 +(g1156 +tp1557 +Rp1558 +ag2 +(g3 +tp1559 +Rp1560 +aa(lp1561 +g2 +(S'0.8' +p1562 +tp1563 +Rp1564 +ag2 +(g1156 +tp1565 +Rp1566 +ag2 +(g3 +tp1567 +Rp1568 +aa(lp1569 +g2 +(S'0.816' +p1570 +tp1571 +Rp1572 +ag2 +(g1156 +tp1573 +Rp1574 +ag2 +(g3 +tp1575 +Rp1576 +aa(lp1577 +g2 +(S'0.831' +p1578 +tp1579 +Rp1580 +ag2 +(g1156 +tp1581 +Rp1582 +ag2 +(g3 +tp1583 +Rp1584 +aa(lp1585 +g2 +(S'0.847' +p1586 +tp1587 +Rp1588 +ag2 +(g1156 +tp1589 +Rp1590 +ag2 +(g3 +tp1591 +Rp1592 +aa(lp1593 +g2 +(S'0.863' +p1594 +tp1595 +Rp1596 +ag2 +(g1156 +tp1597 +Rp1598 +ag2 +(g3 +tp1599 +Rp1600 +aa(lp1601 +g2 +(S'0.878' +p1602 +tp1603 +Rp1604 +ag2 +(g1156 +tp1605 +Rp1606 +ag2 +(g3 +tp1607 +Rp1608 +aa(lp1609 +g2 +(S'0.894' +p1610 +tp1611 +Rp1612 +ag2 +(g1156 +tp1613 +Rp1614 +ag2 +(g3 +tp1615 +Rp1616 +aa(lp1617 +g2 +(S'0.910' +p1618 +tp1619 +Rp1620 +ag2 +(g1156 +tp1621 +Rp1622 +ag2 +(g3 +tp1623 +Rp1624 +aa(lp1625 +g2 +(S'0.925' +p1626 +tp1627 +Rp1628 +ag2 +(g1156 +tp1629 +Rp1630 +ag2 +(g3 +tp1631 +Rp1632 +aa(lp1633 +g2 +(S'0.941' +p1634 +tp1635 +Rp1636 +ag2 +(g1156 +tp1637 +Rp1638 +ag2 +(g3 +tp1639 +Rp1640 +aa(lp1641 +g2 +(S'0.957' +p1642 +tp1643 +Rp1644 +ag2 +(g1156 +tp1645 +Rp1646 +ag2 +(g3 +tp1647 +Rp1648 +aa(lp1649 +g2 +(S'0.973' +p1650 +tp1651 +Rp1652 +ag2 +(g1156 +tp1653 +Rp1654 +ag2 +(g3 +tp1655 +Rp1656 +aa(lp1657 +g2 +(S'0.988' +p1658 +tp1659 +Rp1660 +ag2 +(g1156 +tp1661 +Rp1662 +ag2 +(g3 +tp1663 +Rp1664 +aa(lp1665 +g2 +(g1156 +tp1666 +Rp1667 +ag2 +(g1156 +tp1668 +Rp1669 +ag2 +(g3 +tp1670 +Rp1671 +aa(lp1672 +g2 +(g1156 +tp1673 +Rp1674 +ag2 +(g1156 +tp1675 +Rp1676 +ag2 +(S'0.0157' +p1677 +tp1678 +Rp1679 +aa(lp1680 +g2 +(g1156 +tp1681 +Rp1682 +ag2 +(g1156 +tp1683 +Rp1684 +ag2 +(S'0.0314' +p1685 +tp1686 +Rp1687 +aa(lp1688 +g2 +(g1156 +tp1689 +Rp1690 +ag2 +(g1156 +tp1691 +Rp1692 +ag2 +(S'0.0471' +p1693 +tp1694 +Rp1695 +aa(lp1696 +g2 +(g1156 +tp1697 +Rp1698 +ag2 +(g1156 +tp1699 +Rp1700 +ag2 +(S'0.0627' +p1701 +tp1702 +Rp1703 +aa(lp1704 +g2 +(g1156 +tp1705 +Rp1706 +ag2 +(g1156 +tp1707 +Rp1708 +ag2 +(S'0.0784' +p1709 +tp1710 +Rp1711 +aa(lp1712 +g2 +(g1156 +tp1713 +Rp1714 +ag2 +(g1156 +tp1715 +Rp1716 +ag2 +(S'0.0941' +p1717 +tp1718 +Rp1719 +aa(lp1720 +g2 +(g1156 +tp1721 +Rp1722 +ag2 +(g1156 +tp1723 +Rp1724 +ag2 +(S'0.110' +p1725 +tp1726 +Rp1727 +aa(lp1728 +g2 +(g1156 +tp1729 +Rp1730 +ag2 +(g1156 +tp1731 +Rp1732 +ag2 +(S'0.125' +p1733 +tp1734 +Rp1735 +aa(lp1736 +g2 +(g1156 +tp1737 +Rp1738 +ag2 +(g1156 +tp1739 +Rp1740 +ag2 +(S'0.141' +p1741 +tp1742 +Rp1743 +aa(lp1744 +g2 +(g1156 +tp1745 +Rp1746 +ag2 +(g1156 +tp1747 +Rp1748 +ag2 +(S'0.157' +p1749 +tp1750 +Rp1751 +aa(lp1752 +g2 +(g1156 +tp1753 +Rp1754 +ag2 +(g1156 +tp1755 +Rp1756 +ag2 +(S'0.173' +p1757 +tp1758 +Rp1759 +aa(lp1760 +g2 +(g1156 +tp1761 +Rp1762 +ag2 +(g1156 +tp1763 +Rp1764 +ag2 +(S'0.188' +p1765 +tp1766 +Rp1767 +aa(lp1768 +g2 +(g1156 +tp1769 +Rp1770 +ag2 +(g1156 +tp1771 +Rp1772 +ag2 +(S'0.204' +p1773 +tp1774 +Rp1775 +aa(lp1776 +g2 +(g1156 +tp1777 +Rp1778 +ag2 +(g1156 +tp1779 +Rp1780 +ag2 +(S'0.220' +p1781 +tp1782 +Rp1783 +aa(lp1784 +g2 +(g1156 +tp1785 +Rp1786 +ag2 +(g1156 +tp1787 +Rp1788 +ag2 +(S'0.235' +p1789 +tp1790 +Rp1791 +aa(lp1792 +g2 +(g1156 +tp1793 +Rp1794 +ag2 +(g1156 +tp1795 +Rp1796 +ag2 +(S'0.251' +p1797 +tp1798 +Rp1799 +aa(lp1800 +g2 +(g1156 +tp1801 +Rp1802 +ag2 +(g1156 +tp1803 +Rp1804 +ag2 +(S'0.267' +p1805 +tp1806 +Rp1807 +aa(lp1808 +g2 +(g1156 +tp1809 +Rp1810 +ag2 +(g1156 +tp1811 +Rp1812 +ag2 +(S'0.282' +p1813 +tp1814 +Rp1815 +aa(lp1816 +g2 +(g1156 +tp1817 +Rp1818 +ag2 +(g1156 +tp1819 +Rp1820 +ag2 +(S'0.298' +p1821 +tp1822 +Rp1823 +aa(lp1824 +g2 +(g1156 +tp1825 +Rp1826 +ag2 +(g1156 +tp1827 +Rp1828 +ag2 +(S'0.314' +p1829 +tp1830 +Rp1831 +aa(lp1832 +g2 +(g1156 +tp1833 +Rp1834 +ag2 +(g1156 +tp1835 +Rp1836 +ag2 +(S'0.329' +p1837 +tp1838 +Rp1839 +aa(lp1840 +g2 +(g1156 +tp1841 +Rp1842 +ag2 +(g1156 +tp1843 +Rp1844 +ag2 +(S'0.345' +p1845 +tp1846 +Rp1847 +aa(lp1848 +g2 +(g1156 +tp1849 +Rp1850 +ag2 +(g1156 +tp1851 +Rp1852 +ag2 +(S'0.361' +p1853 +tp1854 +Rp1855 +aa(lp1856 +g2 +(g1156 +tp1857 +Rp1858 +ag2 +(g1156 +tp1859 +Rp1860 +ag2 +(S'0.376' +p1861 +tp1862 +Rp1863 +aa(lp1864 +g2 +(g1156 +tp1865 +Rp1866 +ag2 +(g1156 +tp1867 +Rp1868 +ag2 +(S'0.392' +p1869 +tp1870 +Rp1871 +aa(lp1872 +g2 +(g1156 +tp1873 +Rp1874 +ag2 +(g1156 +tp1875 +Rp1876 +ag2 +(S'0.408' +p1877 +tp1878 +Rp1879 +aa(lp1880 +g2 +(g1156 +tp1881 +Rp1882 +ag2 +(g1156 +tp1883 +Rp1884 +ag2 +(S'0.424' +p1885 +tp1886 +Rp1887 +aa(lp1888 +g2 +(g1156 +tp1889 +Rp1890 +ag2 +(g1156 +tp1891 +Rp1892 +ag2 +(S'0.439' +p1893 +tp1894 +Rp1895 +aa(lp1896 +g2 +(g1156 +tp1897 +Rp1898 +ag2 +(g1156 +tp1899 +Rp1900 +ag2 +(S'0.455' +p1901 +tp1902 +Rp1903 +aa(lp1904 +g2 +(g1156 +tp1905 +Rp1906 +ag2 +(g1156 +tp1907 +Rp1908 +ag2 +(S'0.471' +p1909 +tp1910 +Rp1911 +aa(lp1912 +g2 +(g1156 +tp1913 +Rp1914 +ag2 +(g1156 +tp1915 +Rp1916 +ag2 +(S'0.486' +p1917 +tp1918 +Rp1919 +aa(lp1920 +g2 +(g1156 +tp1921 +Rp1922 +ag2 +(g1156 +tp1923 +Rp1924 +ag2 +(S'0.502' +p1925 +tp1926 +Rp1927 +aa(lp1928 +g2 +(g1156 +tp1929 +Rp1930 +ag2 +(g1156 +tp1931 +Rp1932 +ag2 +(S'0.518' +p1933 +tp1934 +Rp1935 +aa(lp1936 +g2 +(g1156 +tp1937 +Rp1938 +ag2 +(g1156 +tp1939 +Rp1940 +ag2 +(S'0.533' +p1941 +tp1942 +Rp1943 +aa(lp1944 +g2 +(g1156 +tp1945 +Rp1946 +ag2 +(g1156 +tp1947 +Rp1948 +ag2 +(S'0.549' +p1949 +tp1950 +Rp1951 +aa(lp1952 +g2 +(g1156 +tp1953 +Rp1954 +ag2 +(g1156 +tp1955 +Rp1956 +ag2 +(S'0.565' +p1957 +tp1958 +Rp1959 +aa(lp1960 +g2 +(g1156 +tp1961 +Rp1962 +ag2 +(g1156 +tp1963 +Rp1964 +ag2 +(S'0.580' +p1965 +tp1966 +Rp1967 +aa(lp1968 +g2 +(g1156 +tp1969 +Rp1970 +ag2 +(g1156 +tp1971 +Rp1972 +ag2 +(S'0.596' +p1973 +tp1974 +Rp1975 +aa(lp1976 +g2 +(g1156 +tp1977 +Rp1978 +ag2 +(g1156 +tp1979 +Rp1980 +ag2 +(S'0.612' +p1981 +tp1982 +Rp1983 +aa(lp1984 +g2 +(g1156 +tp1985 +Rp1986 +ag2 +(g1156 +tp1987 +Rp1988 +ag2 +(S'0.627' +p1989 +tp1990 +Rp1991 +aa(lp1992 +g2 +(g1156 +tp1993 +Rp1994 +ag2 +(g1156 +tp1995 +Rp1996 +ag2 +(S'0.643' +p1997 +tp1998 +Rp1999 +aa(lp2000 +g2 +(g1156 +tp2001 +Rp2002 +ag2 +(g1156 +tp2003 +Rp2004 +ag2 +(S'0.659' +p2005 +tp2006 +Rp2007 +aa(lp2008 +g2 +(g1156 +tp2009 +Rp2010 +ag2 +(g1156 +tp2011 +Rp2012 +ag2 +(S'0.675' +p2013 +tp2014 +Rp2015 +aa(lp2016 +g2 +(g1156 +tp2017 +Rp2018 +ag2 +(g1156 +tp2019 +Rp2020 +ag2 +(S'0.690' +p2021 +tp2022 +Rp2023 +aa(lp2024 +g2 +(g1156 +tp2025 +Rp2026 +ag2 +(g1156 +tp2027 +Rp2028 +ag2 +(S'0.706' +p2029 +tp2030 +Rp2031 +aa(lp2032 +g2 +(g1156 +tp2033 +Rp2034 +ag2 +(g1156 +tp2035 +Rp2036 +ag2 +(S'0.722' +p2037 +tp2038 +Rp2039 +aa(lp2040 +g2 +(g1156 +tp2041 +Rp2042 +ag2 +(g1156 +tp2043 +Rp2044 +ag2 +(S'0.737' +p2045 +tp2046 +Rp2047 +aa(lp2048 +g2 +(g1156 +tp2049 +Rp2050 +ag2 +(g1156 +tp2051 +Rp2052 +ag2 +(S'0.753' +p2053 +tp2054 +Rp2055 +aa(lp2056 +g2 +(g1156 +tp2057 +Rp2058 +ag2 +(g1156 +tp2059 +Rp2060 +ag2 +(S'0.769' +p2061 +tp2062 +Rp2063 +aa(lp2064 +g2 +(g1156 +tp2065 +Rp2066 +ag2 +(g1156 +tp2067 +Rp2068 +ag2 +(S'0.784' +p2069 +tp2070 +Rp2071 +aa(lp2072 +g2 +(g1156 +tp2073 +Rp2074 +ag2 +(g1156 +tp2075 +Rp2076 +ag2 +(S'0.8' +p2077 +tp2078 +Rp2079 +aa(lp2080 +g2 +(g1156 +tp2081 +Rp2082 +ag2 +(g1156 +tp2083 +Rp2084 +ag2 +(S'0.816' +p2085 +tp2086 +Rp2087 +aa(lp2088 +g2 +(g1156 +tp2089 +Rp2090 +ag2 +(g1156 +tp2091 +Rp2092 +ag2 +(S'0.831' +p2093 +tp2094 +Rp2095 +aa(lp2096 +g2 +(g1156 +tp2097 +Rp2098 +ag2 +(g1156 +tp2099 +Rp2100 +ag2 +(S'0.847' +p2101 +tp2102 +Rp2103 +aa(lp2104 +g2 +(g1156 +tp2105 +Rp2106 +ag2 +(g1156 +tp2107 +Rp2108 +ag2 +(S'0.863' +p2109 +tp2110 +Rp2111 +aa(lp2112 +g2 +(g1156 +tp2113 +Rp2114 +ag2 +(g1156 +tp2115 +Rp2116 +ag2 +(S'0.878' +p2117 +tp2118 +Rp2119 +aa(lp2120 +g2 +(g1156 +tp2121 +Rp2122 +ag2 +(g1156 +tp2123 +Rp2124 +ag2 +(S'0.894' +p2125 +tp2126 +Rp2127 +aa(lp2128 +g2 +(g1156 +tp2129 +Rp2130 +ag2 +(g1156 +tp2131 +Rp2132 +ag2 +(S'0.910' +p2133 +tp2134 +Rp2135 +aa(lp2136 +g2 +(g1156 +tp2137 +Rp2138 +ag2 +(g1156 +tp2139 +Rp2140 +ag2 +(S'0.925' +p2141 +tp2142 +Rp2143 +aa(lp2144 +g2 +(g1156 +tp2145 +Rp2146 +ag2 +(g1156 +tp2147 +Rp2148 +ag2 +(S'0.941' +p2149 +tp2150 +Rp2151 +aa(lp2152 +g2 +(g1156 +tp2153 +Rp2154 +ag2 +(g1156 +tp2155 +Rp2156 +ag2 +(S'0.957' +p2157 +tp2158 +Rp2159 +aa(lp2160 +g2 +(g1156 +tp2161 +Rp2162 +ag2 +(g1156 +tp2163 +Rp2164 +ag2 +(S'0.973' +p2165 +tp2166 +Rp2167 +aa(lp2168 +g2 +(g1156 +tp2169 +Rp2170 +ag2 +(g1156 +tp2171 +Rp2172 +ag2 +(S'0.988' +p2173 +tp2174 +Rp2175 +aa. \ No newline at end of file diff --git a/moose-gui/colormaps/grey b/moose-gui/colormaps/grey new file mode 100644 index 0000000000000000000000000000000000000000..5a9785a87b282bd39b9424abd120be2526b7faeb --- /dev/null +++ b/moose-gui/colormaps/grey @@ -0,0 +1,2050 @@ +(lp0 +(lp1 +cdecimal +Decimal +p2 +(S'0.00781' +p3 +tp4 +Rp5 +ag2 +(S'0.00781' +p6 +tp7 +Rp8 +ag2 +(S'0.00781' +p9 +tp10 +Rp11 +aa(lp12 +g2 +(S'0.0156' +p13 +tp14 +Rp15 +ag2 +(S'0.0156' +p16 +tp17 +Rp18 +ag2 +(S'0.0156' +p19 +tp20 +Rp21 +aa(lp22 +g2 +(S'0.0234' +p23 +tp24 +Rp25 +ag2 +(S'0.0234' +p26 +tp27 +Rp28 +ag2 +(S'0.0234' +p29 +tp30 +Rp31 +aa(lp32 +g2 +(S'0.0313' +p33 +tp34 +Rp35 +ag2 +(S'0.0313' +p36 +tp37 +Rp38 +ag2 +(S'0.0313' +p39 +tp40 +Rp41 +aa(lp42 +g2 +(S'0.0391' +p43 +tp44 +Rp45 +ag2 +(S'0.0391' +p46 +tp47 +Rp48 +ag2 +(S'0.0391' +p49 +tp50 +Rp51 +aa(lp52 +g2 +(S'0.0469' +p53 +tp54 +Rp55 +ag2 +(S'0.0469' +p56 +tp57 +Rp58 +ag2 +(S'0.0469' +p59 +tp60 +Rp61 +aa(lp62 +g2 +(S'0.0547' +p63 +tp64 +Rp65 +ag2 +(S'0.0547' +p66 +tp67 +Rp68 +ag2 +(S'0.0547' +p69 +tp70 +Rp71 +aa(lp72 +g2 +(S'0.0625' +p73 +tp74 +Rp75 +ag2 +(S'0.0625' +p76 +tp77 +Rp78 +ag2 +(S'0.0625' +p79 +tp80 +Rp81 +aa(lp82 +g2 +(S'0.0703' +p83 +tp84 +Rp85 +ag2 +(S'0.0703' +p86 +tp87 +Rp88 +ag2 +(S'0.0703' +p89 +tp90 +Rp91 +aa(lp92 +g2 +(S'0.0781' +p93 +tp94 +Rp95 +ag2 +(S'0.0781' +p96 +tp97 +Rp98 +ag2 +(S'0.0781' +p99 +tp100 +Rp101 +aa(lp102 +g2 +(S'0.0859' +p103 +tp104 +Rp105 +ag2 +(S'0.0859' +p106 +tp107 +Rp108 +ag2 +(S'0.0859' +p109 +tp110 +Rp111 +aa(lp112 +g2 +(S'0.0938' +p113 +tp114 +Rp115 +ag2 +(S'0.0938' +p116 +tp117 +Rp118 +ag2 +(S'0.0938' +p119 +tp120 +Rp121 +aa(lp122 +g2 +(S'0.102' +p123 +tp124 +Rp125 +ag2 +(S'0.102' +p126 +tp127 +Rp128 +ag2 +(S'0.102' +p129 +tp130 +Rp131 +aa(lp132 +g2 +(S'0.109' +p133 +tp134 +Rp135 +ag2 +(S'0.109' +p136 +tp137 +Rp138 +ag2 +(S'0.109' +p139 +tp140 +Rp141 +aa(lp142 +g2 +(S'0.117' +p143 +tp144 +Rp145 +ag2 +(S'0.117' +p146 +tp147 +Rp148 +ag2 +(S'0.117' +p149 +tp150 +Rp151 +aa(lp152 +g2 +(S'0.125' +p153 +tp154 +Rp155 +ag2 +(S'0.125' +p156 +tp157 +Rp158 +ag2 +(S'0.125' +p159 +tp160 +Rp161 +aa(lp162 +g2 +(S'0.133' +p163 +tp164 +Rp165 +ag2 +(S'0.133' +p166 +tp167 +Rp168 +ag2 +(S'0.133' +p169 +tp170 +Rp171 +aa(lp172 +g2 +(S'0.141' +p173 +tp174 +Rp175 +ag2 +(S'0.141' +p176 +tp177 +Rp178 +ag2 +(S'0.141' +p179 +tp180 +Rp181 +aa(lp182 +g2 +(S'0.148' +p183 +tp184 +Rp185 +ag2 +(S'0.148' +p186 +tp187 +Rp188 +ag2 +(S'0.148' +p189 +tp190 +Rp191 +aa(lp192 +g2 +(S'0.156' +p193 +tp194 +Rp195 +ag2 +(S'0.156' +p196 +tp197 +Rp198 +ag2 +(S'0.156' +p199 +tp200 +Rp201 +aa(lp202 +g2 +(S'0.164' +p203 +tp204 +Rp205 +ag2 +(S'0.164' +p206 +tp207 +Rp208 +ag2 +(S'0.164' +p209 +tp210 +Rp211 +aa(lp212 +g2 +(S'0.172' +p213 +tp214 +Rp215 +ag2 +(S'0.172' +p216 +tp217 +Rp218 +ag2 +(S'0.172' +p219 +tp220 +Rp221 +aa(lp222 +g2 +(S'0.180' +p223 +tp224 +Rp225 +ag2 +(S'0.180' +p226 +tp227 +Rp228 +ag2 +(S'0.180' +p229 +tp230 +Rp231 +aa(lp232 +g2 +(S'0.188' +p233 +tp234 +Rp235 +ag2 +(S'0.188' +p236 +tp237 +Rp238 +ag2 +(S'0.188' +p239 +tp240 +Rp241 +aa(lp242 +g2 +(S'0.195' +p243 +tp244 +Rp245 +ag2 +(S'0.195' +p246 +tp247 +Rp248 +ag2 +(S'0.195' +p249 +tp250 +Rp251 +aa(lp252 +g2 +(S'0.203' +p253 +tp254 +Rp255 +ag2 +(S'0.203' +p256 +tp257 +Rp258 +ag2 +(S'0.203' +p259 +tp260 +Rp261 +aa(lp262 +g2 +(S'0.211' +p263 +tp264 +Rp265 +ag2 +(S'0.211' +p266 +tp267 +Rp268 +ag2 +(S'0.211' +p269 +tp270 +Rp271 +aa(lp272 +g2 +(S'0.219' +p273 +tp274 +Rp275 +ag2 +(S'0.219' +p276 +tp277 +Rp278 +ag2 +(S'0.219' +p279 +tp280 +Rp281 +aa(lp282 +g2 +(S'0.227' +p283 +tp284 +Rp285 +ag2 +(S'0.227' +p286 +tp287 +Rp288 +ag2 +(S'0.227' +p289 +tp290 +Rp291 +aa(lp292 +g2 +(S'0.234' +p293 +tp294 +Rp295 +ag2 +(S'0.234' +p296 +tp297 +Rp298 +ag2 +(S'0.234' +p299 +tp300 +Rp301 +aa(lp302 +g2 +(S'0.242' +p303 +tp304 +Rp305 +ag2 +(S'0.242' +p306 +tp307 +Rp308 +ag2 +(S'0.242' +p309 +tp310 +Rp311 +aa(lp312 +g2 +(S'0.250' +p313 +tp314 +Rp315 +ag2 +(S'0.250' +p316 +tp317 +Rp318 +ag2 +(S'0.250' +p319 +tp320 +Rp321 +aa(lp322 +g2 +(S'0.258' +p323 +tp324 +Rp325 +ag2 +(S'0.258' +p326 +tp327 +Rp328 +ag2 +(S'0.258' +p329 +tp330 +Rp331 +aa(lp332 +g2 +(S'0.266' +p333 +tp334 +Rp335 +ag2 +(S'0.266' +p336 +tp337 +Rp338 +ag2 +(S'0.266' +p339 +tp340 +Rp341 +aa(lp342 +g2 +(S'0.273' +p343 +tp344 +Rp345 +ag2 +(S'0.273' +p346 +tp347 +Rp348 +ag2 +(S'0.273' +p349 +tp350 +Rp351 +aa(lp352 +g2 +(S'0.281' +p353 +tp354 +Rp355 +ag2 +(S'0.281' +p356 +tp357 +Rp358 +ag2 +(S'0.281' +p359 +tp360 +Rp361 +aa(lp362 +g2 +(S'0.289' +p363 +tp364 +Rp365 +ag2 +(S'0.289' +p366 +tp367 +Rp368 +ag2 +(S'0.289' +p369 +tp370 +Rp371 +aa(lp372 +g2 +(S'0.297' +p373 +tp374 +Rp375 +ag2 +(S'0.297' +p376 +tp377 +Rp378 +ag2 +(S'0.297' +p379 +tp380 +Rp381 +aa(lp382 +g2 +(S'0.305' +p383 +tp384 +Rp385 +ag2 +(S'0.305' +p386 +tp387 +Rp388 +ag2 +(S'0.305' +p389 +tp390 +Rp391 +aa(lp392 +g2 +(S'0.313' +p393 +tp394 +Rp395 +ag2 +(S'0.313' +p396 +tp397 +Rp398 +ag2 +(S'0.313' +p399 +tp400 +Rp401 +aa(lp402 +g2 +(S'0.320' +p403 +tp404 +Rp405 +ag2 +(S'0.320' +p406 +tp407 +Rp408 +ag2 +(S'0.320' +p409 +tp410 +Rp411 +aa(lp412 +g2 +(S'0.328' +p413 +tp414 +Rp415 +ag2 +(S'0.328' +p416 +tp417 +Rp418 +ag2 +(S'0.328' +p419 +tp420 +Rp421 +aa(lp422 +g2 +(S'0.336' +p423 +tp424 +Rp425 +ag2 +(S'0.336' +p426 +tp427 +Rp428 +ag2 +(S'0.336' +p429 +tp430 +Rp431 +aa(lp432 +g2 +(S'0.344' +p433 +tp434 +Rp435 +ag2 +(S'0.344' +p436 +tp437 +Rp438 +ag2 +(S'0.344' +p439 +tp440 +Rp441 +aa(lp442 +g2 +(S'0.352' +p443 +tp444 +Rp445 +ag2 +(S'0.352' +p446 +tp447 +Rp448 +ag2 +(S'0.352' +p449 +tp450 +Rp451 +aa(lp452 +g2 +(S'0.359' +p453 +tp454 +Rp455 +ag2 +(S'0.359' +p456 +tp457 +Rp458 +ag2 +(S'0.359' +p459 +tp460 +Rp461 +aa(lp462 +g2 +(S'0.367' +p463 +tp464 +Rp465 +ag2 +(S'0.367' +p466 +tp467 +Rp468 +ag2 +(S'0.367' +p469 +tp470 +Rp471 +aa(lp472 +g2 +(S'0.375' +p473 +tp474 +Rp475 +ag2 +(S'0.375' +p476 +tp477 +Rp478 +ag2 +(S'0.375' +p479 +tp480 +Rp481 +aa(lp482 +g2 +(S'0.383' +p483 +tp484 +Rp485 +ag2 +(S'0.383' +p486 +tp487 +Rp488 +ag2 +(S'0.383' +p489 +tp490 +Rp491 +aa(lp492 +g2 +(S'0.391' +p493 +tp494 +Rp495 +ag2 +(S'0.391' +p496 +tp497 +Rp498 +ag2 +(S'0.391' +p499 +tp500 +Rp501 +aa(lp502 +g2 +(S'0.398' +p503 +tp504 +Rp505 +ag2 +(S'0.398' +p506 +tp507 +Rp508 +ag2 +(S'0.398' +p509 +tp510 +Rp511 +aa(lp512 +g2 +(S'0.406' +p513 +tp514 +Rp515 +ag2 +(S'0.406' +p516 +tp517 +Rp518 +ag2 +(S'0.406' +p519 +tp520 +Rp521 +aa(lp522 +g2 +(S'0.414' +p523 +tp524 +Rp525 +ag2 +(S'0.414' +p526 +tp527 +Rp528 +ag2 +(S'0.414' +p529 +tp530 +Rp531 +aa(lp532 +g2 +(S'0.422' +p533 +tp534 +Rp535 +ag2 +(S'0.422' +p536 +tp537 +Rp538 +ag2 +(S'0.422' +p539 +tp540 +Rp541 +aa(lp542 +g2 +(S'0.430' +p543 +tp544 +Rp545 +ag2 +(S'0.430' +p546 +tp547 +Rp548 +ag2 +(S'0.430' +p549 +tp550 +Rp551 +aa(lp552 +g2 +(S'0.438' +p553 +tp554 +Rp555 +ag2 +(S'0.438' +p556 +tp557 +Rp558 +ag2 +(S'0.438' +p559 +tp560 +Rp561 +aa(lp562 +g2 +(S'0.445' +p563 +tp564 +Rp565 +ag2 +(S'0.445' +p566 +tp567 +Rp568 +ag2 +(S'0.445' +p569 +tp570 +Rp571 +aa(lp572 +g2 +(S'0.453' +p573 +tp574 +Rp575 +ag2 +(S'0.453' +p576 +tp577 +Rp578 +ag2 +(S'0.453' +p579 +tp580 +Rp581 +aa(lp582 +g2 +(S'0.461' +p583 +tp584 +Rp585 +ag2 +(S'0.461' +p586 +tp587 +Rp588 +ag2 +(S'0.461' +p589 +tp590 +Rp591 +aa(lp592 +g2 +(S'0.469' +p593 +tp594 +Rp595 +ag2 +(S'0.469' +p596 +tp597 +Rp598 +ag2 +(S'0.469' +p599 +tp600 +Rp601 +aa(lp602 +g2 +(S'0.477' +p603 +tp604 +Rp605 +ag2 +(S'0.477' +p606 +tp607 +Rp608 +ag2 +(S'0.477' +p609 +tp610 +Rp611 +aa(lp612 +g2 +(S'0.484' +p613 +tp614 +Rp615 +ag2 +(S'0.484' +p616 +tp617 +Rp618 +ag2 +(S'0.484' +p619 +tp620 +Rp621 +aa(lp622 +g2 +(S'0.492' +p623 +tp624 +Rp625 +ag2 +(S'0.492' +p626 +tp627 +Rp628 +ag2 +(S'0.492' +p629 +tp630 +Rp631 +aa(lp632 +g2 +(S'0.500' +p633 +tp634 +Rp635 +ag2 +(S'0.500' +p636 +tp637 +Rp638 +ag2 +(S'0.500' +p639 +tp640 +Rp641 +aa(lp642 +g2 +(S'0.508' +p643 +tp644 +Rp645 +ag2 +(S'0.508' +p646 +tp647 +Rp648 +ag2 +(S'0.508' +p649 +tp650 +Rp651 +aa(lp652 +g2 +(S'0.516' +p653 +tp654 +Rp655 +ag2 +(S'0.516' +p656 +tp657 +Rp658 +ag2 +(S'0.516' +p659 +tp660 +Rp661 +aa(lp662 +g2 +(S'0.523' +p663 +tp664 +Rp665 +ag2 +(S'0.523' +p666 +tp667 +Rp668 +ag2 +(S'0.523' +p669 +tp670 +Rp671 +aa(lp672 +g2 +(S'0.531' +p673 +tp674 +Rp675 +ag2 +(S'0.531' +p676 +tp677 +Rp678 +ag2 +(S'0.531' +p679 +tp680 +Rp681 +aa(lp682 +g2 +(S'0.539' +p683 +tp684 +Rp685 +ag2 +(S'0.539' +p686 +tp687 +Rp688 +ag2 +(S'0.539' +p689 +tp690 +Rp691 +aa(lp692 +g2 +(S'0.547' +p693 +tp694 +Rp695 +ag2 +(S'0.547' +p696 +tp697 +Rp698 +ag2 +(S'0.547' +p699 +tp700 +Rp701 +aa(lp702 +g2 +(S'0.555' +p703 +tp704 +Rp705 +ag2 +(S'0.555' +p706 +tp707 +Rp708 +ag2 +(S'0.555' +p709 +tp710 +Rp711 +aa(lp712 +g2 +(S'0.563' +p713 +tp714 +Rp715 +ag2 +(S'0.563' +p716 +tp717 +Rp718 +ag2 +(S'0.563' +p719 +tp720 +Rp721 +aa(lp722 +g2 +(S'0.570' +p723 +tp724 +Rp725 +ag2 +(S'0.570' +p726 +tp727 +Rp728 +ag2 +(S'0.570' +p729 +tp730 +Rp731 +aa(lp732 +g2 +(S'0.578' +p733 +tp734 +Rp735 +ag2 +(S'0.578' +p736 +tp737 +Rp738 +ag2 +(S'0.578' +p739 +tp740 +Rp741 +aa(lp742 +g2 +(S'0.586' +p743 +tp744 +Rp745 +ag2 +(S'0.586' +p746 +tp747 +Rp748 +ag2 +(S'0.586' +p749 +tp750 +Rp751 +aa(lp752 +g2 +(S'0.594' +p753 +tp754 +Rp755 +ag2 +(S'0.594' +p756 +tp757 +Rp758 +ag2 +(S'0.594' +p759 +tp760 +Rp761 +aa(lp762 +g2 +(S'0.602' +p763 +tp764 +Rp765 +ag2 +(S'0.602' +p766 +tp767 +Rp768 +ag2 +(S'0.602' +p769 +tp770 +Rp771 +aa(lp772 +g2 +(S'0.609' +p773 +tp774 +Rp775 +ag2 +(S'0.609' +p776 +tp777 +Rp778 +ag2 +(S'0.609' +p779 +tp780 +Rp781 +aa(lp782 +g2 +(S'0.617' +p783 +tp784 +Rp785 +ag2 +(S'0.617' +p786 +tp787 +Rp788 +ag2 +(S'0.617' +p789 +tp790 +Rp791 +aa(lp792 +g2 +(S'0.625' +p793 +tp794 +Rp795 +ag2 +(S'0.625' +p796 +tp797 +Rp798 +ag2 +(S'0.625' +p799 +tp800 +Rp801 +aa(lp802 +g2 +(S'0.633' +p803 +tp804 +Rp805 +ag2 +(S'0.633' +p806 +tp807 +Rp808 +ag2 +(S'0.633' +p809 +tp810 +Rp811 +aa(lp812 +g2 +(S'0.641' +p813 +tp814 +Rp815 +ag2 +(S'0.641' +p816 +tp817 +Rp818 +ag2 +(S'0.641' +p819 +tp820 +Rp821 +aa(lp822 +g2 +(S'0.648' +p823 +tp824 +Rp825 +ag2 +(S'0.648' +p826 +tp827 +Rp828 +ag2 +(S'0.648' +p829 +tp830 +Rp831 +aa(lp832 +g2 +(S'0.656' +p833 +tp834 +Rp835 +ag2 +(S'0.656' +p836 +tp837 +Rp838 +ag2 +(S'0.656' +p839 +tp840 +Rp841 +aa(lp842 +g2 +(S'0.664' +p843 +tp844 +Rp845 +ag2 +(S'0.664' +p846 +tp847 +Rp848 +ag2 +(S'0.664' +p849 +tp850 +Rp851 +aa(lp852 +g2 +(S'0.672' +p853 +tp854 +Rp855 +ag2 +(S'0.672' +p856 +tp857 +Rp858 +ag2 +(S'0.672' +p859 +tp860 +Rp861 +aa(lp862 +g2 +(S'0.680' +p863 +tp864 +Rp865 +ag2 +(S'0.680' +p866 +tp867 +Rp868 +ag2 +(S'0.680' +p869 +tp870 +Rp871 +aa(lp872 +g2 +(S'0.688' +p873 +tp874 +Rp875 +ag2 +(S'0.688' +p876 +tp877 +Rp878 +ag2 +(S'0.688' +p879 +tp880 +Rp881 +aa(lp882 +g2 +(S'0.695' +p883 +tp884 +Rp885 +ag2 +(S'0.695' +p886 +tp887 +Rp888 +ag2 +(S'0.695' +p889 +tp890 +Rp891 +aa(lp892 +g2 +(S'0.703' +p893 +tp894 +Rp895 +ag2 +(S'0.703' +p896 +tp897 +Rp898 +ag2 +(S'0.703' +p899 +tp900 +Rp901 +aa(lp902 +g2 +(S'0.711' +p903 +tp904 +Rp905 +ag2 +(S'0.711' +p906 +tp907 +Rp908 +ag2 +(S'0.711' +p909 +tp910 +Rp911 +aa(lp912 +g2 +(S'0.719' +p913 +tp914 +Rp915 +ag2 +(S'0.719' +p916 +tp917 +Rp918 +ag2 +(S'0.719' +p919 +tp920 +Rp921 +aa(lp922 +g2 +(S'0.727' +p923 +tp924 +Rp925 +ag2 +(S'0.727' +p926 +tp927 +Rp928 +ag2 +(S'0.727' +p929 +tp930 +Rp931 +aa(lp932 +g2 +(S'0.734' +p933 +tp934 +Rp935 +ag2 +(S'0.734' +p936 +tp937 +Rp938 +ag2 +(S'0.734' +p939 +tp940 +Rp941 +aa(lp942 +g2 +(S'0.742' +p943 +tp944 +Rp945 +ag2 +(S'0.742' +p946 +tp947 +Rp948 +ag2 +(S'0.742' +p949 +tp950 +Rp951 +aa(lp952 +g2 +(S'0.750' +p953 +tp954 +Rp955 +ag2 +(S'0.750' +p956 +tp957 +Rp958 +ag2 +(S'0.750' +p959 +tp960 +Rp961 +aa(lp962 +g2 +(S'0.758' +p963 +tp964 +Rp965 +ag2 +(S'0.758' +p966 +tp967 +Rp968 +ag2 +(S'0.758' +p969 +tp970 +Rp971 +aa(lp972 +g2 +(S'0.766' +p973 +tp974 +Rp975 +ag2 +(S'0.766' +p976 +tp977 +Rp978 +ag2 +(S'0.766' +p979 +tp980 +Rp981 +aa(lp982 +g2 +(S'0.773' +p983 +tp984 +Rp985 +ag2 +(S'0.773' +p986 +tp987 +Rp988 +ag2 +(S'0.773' +p989 +tp990 +Rp991 +aa(lp992 +g2 +(S'0.781' +p993 +tp994 +Rp995 +ag2 +(S'0.781' +p996 +tp997 +Rp998 +ag2 +(S'0.781' +p999 +tp1000 +Rp1001 +aa(lp1002 +g2 +(S'0.789' +p1003 +tp1004 +Rp1005 +ag2 +(S'0.789' +p1006 +tp1007 +Rp1008 +ag2 +(S'0.789' +p1009 +tp1010 +Rp1011 +aa(lp1012 +g2 +(S'0.797' +p1013 +tp1014 +Rp1015 +ag2 +(S'0.797' +p1016 +tp1017 +Rp1018 +ag2 +(S'0.797' +p1019 +tp1020 +Rp1021 +aa(lp1022 +g2 +(S'0.805' +p1023 +tp1024 +Rp1025 +ag2 +(S'0.805' +p1026 +tp1027 +Rp1028 +ag2 +(S'0.805' +p1029 +tp1030 +Rp1031 +aa(lp1032 +g2 +(S'0.813' +p1033 +tp1034 +Rp1035 +ag2 +(S'0.813' +p1036 +tp1037 +Rp1038 +ag2 +(S'0.813' +p1039 +tp1040 +Rp1041 +aa(lp1042 +g2 +(S'0.820' +p1043 +tp1044 +Rp1045 +ag2 +(S'0.820' +p1046 +tp1047 +Rp1048 +ag2 +(S'0.820' +p1049 +tp1050 +Rp1051 +aa(lp1052 +g2 +(S'0.828' +p1053 +tp1054 +Rp1055 +ag2 +(S'0.828' +p1056 +tp1057 +Rp1058 +ag2 +(S'0.828' +p1059 +tp1060 +Rp1061 +aa(lp1062 +g2 +(S'0.836' +p1063 +tp1064 +Rp1065 +ag2 +(S'0.836' +p1066 +tp1067 +Rp1068 +ag2 +(S'0.836' +p1069 +tp1070 +Rp1071 +aa(lp1072 +g2 +(S'0.844' +p1073 +tp1074 +Rp1075 +ag2 +(S'0.844' +p1076 +tp1077 +Rp1078 +ag2 +(S'0.844' +p1079 +tp1080 +Rp1081 +aa(lp1082 +g2 +(S'0.852' +p1083 +tp1084 +Rp1085 +ag2 +(S'0.852' +p1086 +tp1087 +Rp1088 +ag2 +(S'0.852' +p1089 +tp1090 +Rp1091 +aa(lp1092 +g2 +(S'0.859' +p1093 +tp1094 +Rp1095 +ag2 +(S'0.859' +p1096 +tp1097 +Rp1098 +ag2 +(S'0.859' +p1099 +tp1100 +Rp1101 +aa(lp1102 +g2 +(S'0.867' +p1103 +tp1104 +Rp1105 +ag2 +(S'0.867' +p1106 +tp1107 +Rp1108 +ag2 +(S'0.867' +p1109 +tp1110 +Rp1111 +aa(lp1112 +g2 +(S'0.875' +p1113 +tp1114 +Rp1115 +ag2 +(S'0.875' +p1116 +tp1117 +Rp1118 +ag2 +(S'0.875' +p1119 +tp1120 +Rp1121 +aa(lp1122 +g2 +(S'0.883' +p1123 +tp1124 +Rp1125 +ag2 +(S'0.883' +p1126 +tp1127 +Rp1128 +ag2 +(S'0.883' +p1129 +tp1130 +Rp1131 +aa(lp1132 +g2 +(S'0.891' +p1133 +tp1134 +Rp1135 +ag2 +(S'0.891' +p1136 +tp1137 +Rp1138 +ag2 +(S'0.891' +p1139 +tp1140 +Rp1141 +aa(lp1142 +g2 +(S'0.898' +p1143 +tp1144 +Rp1145 +ag2 +(S'0.898' +p1146 +tp1147 +Rp1148 +ag2 +(S'0.898' +p1149 +tp1150 +Rp1151 +aa(lp1152 +g2 +(S'0.906' +p1153 +tp1154 +Rp1155 +ag2 +(S'0.906' +p1156 +tp1157 +Rp1158 +ag2 +(S'0.906' +p1159 +tp1160 +Rp1161 +aa(lp1162 +g2 +(S'0.914' +p1163 +tp1164 +Rp1165 +ag2 +(S'0.914' +p1166 +tp1167 +Rp1168 +ag2 +(S'0.914' +p1169 +tp1170 +Rp1171 +aa(lp1172 +g2 +(S'0.922' +p1173 +tp1174 +Rp1175 +ag2 +(S'0.922' +p1176 +tp1177 +Rp1178 +ag2 +(S'0.922' +p1179 +tp1180 +Rp1181 +aa(lp1182 +g2 +(S'0.930' +p1183 +tp1184 +Rp1185 +ag2 +(S'0.930' +p1186 +tp1187 +Rp1188 +ag2 +(S'0.930' +p1189 +tp1190 +Rp1191 +aa(lp1192 +g2 +(S'0.938' +p1193 +tp1194 +Rp1195 +ag2 +(S'0.938' +p1196 +tp1197 +Rp1198 +ag2 +(S'0.938' +p1199 +tp1200 +Rp1201 +aa(lp1202 +g2 +(S'0.945' +p1203 +tp1204 +Rp1205 +ag2 +(S'0.945' +p1206 +tp1207 +Rp1208 +ag2 +(S'0.945' +p1209 +tp1210 +Rp1211 +aa(lp1212 +g2 +(S'0.953' +p1213 +tp1214 +Rp1215 +ag2 +(S'0.953' +p1216 +tp1217 +Rp1218 +ag2 +(S'0.953' +p1219 +tp1220 +Rp1221 +aa(lp1222 +g2 +(S'0.961' +p1223 +tp1224 +Rp1225 +ag2 +(S'0.961' +p1226 +tp1227 +Rp1228 +ag2 +(S'0.961' +p1229 +tp1230 +Rp1231 +aa(lp1232 +g2 +(S'0.969' +p1233 +tp1234 +Rp1235 +ag2 +(S'0.969' +p1236 +tp1237 +Rp1238 +ag2 +(S'0.969' +p1239 +tp1240 +Rp1241 +aa(lp1242 +g2 +(S'0.977' +p1243 +tp1244 +Rp1245 +ag2 +(S'0.977' +p1246 +tp1247 +Rp1248 +ag2 +(S'0.977' +p1249 +tp1250 +Rp1251 +aa(lp1252 +g2 +(S'0.984' +p1253 +tp1254 +Rp1255 +ag2 +(S'0.984' +p1256 +tp1257 +Rp1258 +ag2 +(S'0.984' +p1259 +tp1260 +Rp1261 +aa(lp1262 +g2 +(S'0.992' +p1263 +tp1264 +Rp1265 +ag2 +(S'0.992' +p1266 +tp1267 +Rp1268 +ag2 +(S'0.992' +p1269 +tp1270 +Rp1271 +aa(lp1272 +g2 +(S'1' +p1273 +tp1274 +Rp1275 +ag2 +(g1273 +tp1276 +Rp1277 +ag2 +(g1273 +tp1278 +Rp1279 +aa. \ No newline at end of file diff --git a/moose-gui/colormaps/heat b/moose-gui/colormaps/heat new file mode 100644 index 0000000000000000000000000000000000000000..42afa8643106d909ce19568d67af985ab30e7e40 --- /dev/null +++ b/moose-gui/colormaps/heat @@ -0,0 +1,3588 @@ +(lp0 +(lp1 +cdecimal +Decimal +p2 +(S'0' +p3 +tp4 +Rp5 +ag2 +(g3 +tp6 +Rp7 +ag2 +(g3 +tp8 +Rp9 +aa(lp10 +g2 +(S'0.0118' +p11 +tp12 +Rp13 +ag2 +(g3 +tp14 +Rp15 +ag2 +(g3 +tp16 +Rp17 +aa(lp18 +g2 +(S'0.0235' +p19 +tp20 +Rp21 +ag2 +(g3 +tp22 +Rp23 +ag2 +(g3 +tp24 +Rp25 +aa(lp26 +g2 +(S'0.0353' +p27 +tp28 +Rp29 +ag2 +(g3 +tp30 +Rp31 +ag2 +(g3 +tp32 +Rp33 +aa(lp34 +g2 +(S'0.0471' +p35 +tp36 +Rp37 +ag2 +(g3 +tp38 +Rp39 +ag2 +(g3 +tp40 +Rp41 +aa(lp42 +g2 +(S'0.0588' +p43 +tp44 +Rp45 +ag2 +(g3 +tp46 +Rp47 +ag2 +(g3 +tp48 +Rp49 +aa(lp50 +g2 +(S'0.0706' +p51 +tp52 +Rp53 +ag2 +(g3 +tp54 +Rp55 +ag2 +(g3 +tp56 +Rp57 +aa(lp58 +g2 +(S'0.0824' +p59 +tp60 +Rp61 +ag2 +(g3 +tp62 +Rp63 +ag2 +(g3 +tp64 +Rp65 +aa(lp66 +g2 +(S'0.0941' +p67 +tp68 +Rp69 +ag2 +(g3 +tp70 +Rp71 +ag2 +(g3 +tp72 +Rp73 +aa(lp74 +g2 +(S'0.106' +p75 +tp76 +Rp77 +ag2 +(g3 +tp78 +Rp79 +ag2 +(g3 +tp80 +Rp81 +aa(lp82 +g2 +(S'0.118' +p83 +tp84 +Rp85 +ag2 +(g3 +tp86 +Rp87 +ag2 +(g3 +tp88 +Rp89 +aa(lp90 +g2 +(S'0.129' +p91 +tp92 +Rp93 +ag2 +(g3 +tp94 +Rp95 +ag2 +(g3 +tp96 +Rp97 +aa(lp98 +g2 +(S'0.141' +p99 +tp100 +Rp101 +ag2 +(g3 +tp102 +Rp103 +ag2 +(g3 +tp104 +Rp105 +aa(lp106 +g2 +(S'0.153' +p107 +tp108 +Rp109 +ag2 +(g3 +tp110 +Rp111 +ag2 +(g3 +tp112 +Rp113 +aa(lp114 +g2 +(S'0.165' +p115 +tp116 +Rp117 +ag2 +(g3 +tp118 +Rp119 +ag2 +(g3 +tp120 +Rp121 +aa(lp122 +g2 +(S'0.176' +p123 +tp124 +Rp125 +ag2 +(g3 +tp126 +Rp127 +ag2 +(g3 +tp128 +Rp129 +aa(lp130 +g2 +(S'0.188' +p131 +tp132 +Rp133 +ag2 +(g3 +tp134 +Rp135 +ag2 +(g3 +tp136 +Rp137 +aa(lp138 +g2 +(S'0.2' +p139 +tp140 +Rp141 +ag2 +(g3 +tp142 +Rp143 +ag2 +(g3 +tp144 +Rp145 +aa(lp146 +g2 +(S'0.212' +p147 +tp148 +Rp149 +ag2 +(g3 +tp150 +Rp151 +ag2 +(g3 +tp152 +Rp153 +aa(lp154 +g2 +(S'0.224' +p155 +tp156 +Rp157 +ag2 +(g3 +tp158 +Rp159 +ag2 +(g3 +tp160 +Rp161 +aa(lp162 +g2 +(S'0.235' +p163 +tp164 +Rp165 +ag2 +(g3 +tp166 +Rp167 +ag2 +(g3 +tp168 +Rp169 +aa(lp170 +g2 +(S'0.247' +p171 +tp172 +Rp173 +ag2 +(g3 +tp174 +Rp175 +ag2 +(g3 +tp176 +Rp177 +aa(lp178 +g2 +(S'0.259' +p179 +tp180 +Rp181 +ag2 +(g3 +tp182 +Rp183 +ag2 +(g3 +tp184 +Rp185 +aa(lp186 +g2 +(S'0.271' +p187 +tp188 +Rp189 +ag2 +(g3 +tp190 +Rp191 +ag2 +(g3 +tp192 +Rp193 +aa(lp194 +g2 +(S'0.282' +p195 +tp196 +Rp197 +ag2 +(g3 +tp198 +Rp199 +ag2 +(g3 +tp200 +Rp201 +aa(lp202 +g2 +(S'0.294' +p203 +tp204 +Rp205 +ag2 +(g3 +tp206 +Rp207 +ag2 +(g3 +tp208 +Rp209 +aa(lp210 +g2 +(S'0.306' +p211 +tp212 +Rp213 +ag2 +(g3 +tp214 +Rp215 +ag2 +(g3 +tp216 +Rp217 +aa(lp218 +g2 +(S'0.318' +p219 +tp220 +Rp221 +ag2 +(g3 +tp222 +Rp223 +ag2 +(g3 +tp224 +Rp225 +aa(lp226 +g2 +(S'0.329' +p227 +tp228 +Rp229 +ag2 +(g3 +tp230 +Rp231 +ag2 +(g3 +tp232 +Rp233 +aa(lp234 +g2 +(S'0.341' +p235 +tp236 +Rp237 +ag2 +(g3 +tp238 +Rp239 +ag2 +(g3 +tp240 +Rp241 +aa(lp242 +g2 +(S'0.353' +p243 +tp244 +Rp245 +ag2 +(g3 +tp246 +Rp247 +ag2 +(g3 +tp248 +Rp249 +aa(lp250 +g2 +(S'0.365' +p251 +tp252 +Rp253 +ag2 +(g3 +tp254 +Rp255 +ag2 +(g3 +tp256 +Rp257 +aa(lp258 +g2 +(S'0.376' +p259 +tp260 +Rp261 +ag2 +(g3 +tp262 +Rp263 +ag2 +(g3 +tp264 +Rp265 +aa(lp266 +g2 +(S'0.388' +p267 +tp268 +Rp269 +ag2 +(g3 +tp270 +Rp271 +ag2 +(g3 +tp272 +Rp273 +aa(lp274 +g2 +(S'0.4' +p275 +tp276 +Rp277 +ag2 +(g3 +tp278 +Rp279 +ag2 +(g3 +tp280 +Rp281 +aa(lp282 +g2 +(S'0.412' +p283 +tp284 +Rp285 +ag2 +(g3 +tp286 +Rp287 +ag2 +(g3 +tp288 +Rp289 +aa(lp290 +g2 +(S'0.424' +p291 +tp292 +Rp293 +ag2 +(g3 +tp294 +Rp295 +ag2 +(g3 +tp296 +Rp297 +aa(lp298 +g2 +(S'0.435' +p299 +tp300 +Rp301 +ag2 +(g3 +tp302 +Rp303 +ag2 +(g3 +tp304 +Rp305 +aa(lp306 +g2 +(S'0.447' +p307 +tp308 +Rp309 +ag2 +(g3 +tp310 +Rp311 +ag2 +(g3 +tp312 +Rp313 +aa(lp314 +g2 +(S'0.459' +p315 +tp316 +Rp317 +ag2 +(g3 +tp318 +Rp319 +ag2 +(g3 +tp320 +Rp321 +aa(lp322 +g2 +(S'0.471' +p323 +tp324 +Rp325 +ag2 +(g3 +tp326 +Rp327 +ag2 +(g3 +tp328 +Rp329 +aa(lp330 +g2 +(S'0.482' +p331 +tp332 +Rp333 +ag2 +(g3 +tp334 +Rp335 +ag2 +(g3 +tp336 +Rp337 +aa(lp338 +g2 +(S'0.494' +p339 +tp340 +Rp341 +ag2 +(g3 +tp342 +Rp343 +ag2 +(g3 +tp344 +Rp345 +aa(lp346 +g2 +(S'0.506' +p347 +tp348 +Rp349 +ag2 +(g3 +tp350 +Rp351 +ag2 +(g3 +tp352 +Rp353 +aa(lp354 +g2 +(S'0.518' +p355 +tp356 +Rp357 +ag2 +(g3 +tp358 +Rp359 +ag2 +(g3 +tp360 +Rp361 +aa(lp362 +g2 +(S'0.529' +p363 +tp364 +Rp365 +ag2 +(g3 +tp366 +Rp367 +ag2 +(g3 +tp368 +Rp369 +aa(lp370 +g2 +(S'0.541' +p371 +tp372 +Rp373 +ag2 +(g3 +tp374 +Rp375 +ag2 +(g3 +tp376 +Rp377 +aa(lp378 +g2 +(S'0.553' +p379 +tp380 +Rp381 +ag2 +(g3 +tp382 +Rp383 +ag2 +(g3 +tp384 +Rp385 +aa(lp386 +g2 +(S'0.565' +p387 +tp388 +Rp389 +ag2 +(g3 +tp390 +Rp391 +ag2 +(g3 +tp392 +Rp393 +aa(lp394 +g2 +(S'0.576' +p395 +tp396 +Rp397 +ag2 +(g3 +tp398 +Rp399 +ag2 +(g3 +tp400 +Rp401 +aa(lp402 +g2 +(S'0.588' +p403 +tp404 +Rp405 +ag2 +(g3 +tp406 +Rp407 +ag2 +(g3 +tp408 +Rp409 +aa(lp410 +g2 +(S'0.6' +p411 +tp412 +Rp413 +ag2 +(g3 +tp414 +Rp415 +ag2 +(g3 +tp416 +Rp417 +aa(lp418 +g2 +(S'0.612' +p419 +tp420 +Rp421 +ag2 +(g3 +tp422 +Rp423 +ag2 +(g3 +tp424 +Rp425 +aa(lp426 +g2 +(S'0.624' +p427 +tp428 +Rp429 +ag2 +(g3 +tp430 +Rp431 +ag2 +(g3 +tp432 +Rp433 +aa(lp434 +g2 +(S'0.635' +p435 +tp436 +Rp437 +ag2 +(g3 +tp438 +Rp439 +ag2 +(g3 +tp440 +Rp441 +aa(lp442 +g2 +(S'0.647' +p443 +tp444 +Rp445 +ag2 +(g3 +tp446 +Rp447 +ag2 +(g3 +tp448 +Rp449 +aa(lp450 +g2 +(S'0.659' +p451 +tp452 +Rp453 +ag2 +(g3 +tp454 +Rp455 +ag2 +(g3 +tp456 +Rp457 +aa(lp458 +g2 +(S'0.671' +p459 +tp460 +Rp461 +ag2 +(g3 +tp462 +Rp463 +ag2 +(g3 +tp464 +Rp465 +aa(lp466 +g2 +(S'0.682' +p467 +tp468 +Rp469 +ag2 +(g3 +tp470 +Rp471 +ag2 +(g3 +tp472 +Rp473 +aa(lp474 +g2 +(S'0.694' +p475 +tp476 +Rp477 +ag2 +(g3 +tp478 +Rp479 +ag2 +(g3 +tp480 +Rp481 +aa(lp482 +g2 +(S'0.706' +p483 +tp484 +Rp485 +ag2 +(g3 +tp486 +Rp487 +ag2 +(g3 +tp488 +Rp489 +aa(lp490 +g2 +(S'0.718' +p491 +tp492 +Rp493 +ag2 +(g3 +tp494 +Rp495 +ag2 +(g3 +tp496 +Rp497 +aa(lp498 +g2 +(S'0.729' +p499 +tp500 +Rp501 +ag2 +(g3 +tp502 +Rp503 +ag2 +(g3 +tp504 +Rp505 +aa(lp506 +g2 +(S'0.741' +p507 +tp508 +Rp509 +ag2 +(g3 +tp510 +Rp511 +ag2 +(g3 +tp512 +Rp513 +aa(lp514 +g2 +(S'0.753' +p515 +tp516 +Rp517 +ag2 +(g3 +tp518 +Rp519 +ag2 +(g3 +tp520 +Rp521 +aa(lp522 +g2 +(S'0.765' +p523 +tp524 +Rp525 +ag2 +(g3 +tp526 +Rp527 +ag2 +(g3 +tp528 +Rp529 +aa(lp530 +g2 +(S'0.776' +p531 +tp532 +Rp533 +ag2 +(g3 +tp534 +Rp535 +ag2 +(g3 +tp536 +Rp537 +aa(lp538 +g2 +(S'0.788' +p539 +tp540 +Rp541 +ag2 +(g3 +tp542 +Rp543 +ag2 +(g3 +tp544 +Rp545 +aa(lp546 +g2 +(S'0.8' +p547 +tp548 +Rp549 +ag2 +(g3 +tp550 +Rp551 +ag2 +(g3 +tp552 +Rp553 +aa(lp554 +g2 +(S'0.812' +p555 +tp556 +Rp557 +ag2 +(g3 +tp558 +Rp559 +ag2 +(g3 +tp560 +Rp561 +aa(lp562 +g2 +(S'0.824' +p563 +tp564 +Rp565 +ag2 +(g3 +tp566 +Rp567 +ag2 +(g3 +tp568 +Rp569 +aa(lp570 +g2 +(S'0.835' +p571 +tp572 +Rp573 +ag2 +(g3 +tp574 +Rp575 +ag2 +(g3 +tp576 +Rp577 +aa(lp578 +g2 +(S'0.847' +p579 +tp580 +Rp581 +ag2 +(g3 +tp582 +Rp583 +ag2 +(g3 +tp584 +Rp585 +aa(lp586 +g2 +(S'0.859' +p587 +tp588 +Rp589 +ag2 +(g3 +tp590 +Rp591 +ag2 +(g3 +tp592 +Rp593 +aa(lp594 +g2 +(S'0.871' +p595 +tp596 +Rp597 +ag2 +(g3 +tp598 +Rp599 +ag2 +(g3 +tp600 +Rp601 +aa(lp602 +g2 +(S'0.882' +p603 +tp604 +Rp605 +ag2 +(g3 +tp606 +Rp607 +ag2 +(g3 +tp608 +Rp609 +aa(lp610 +g2 +(S'0.894' +p611 +tp612 +Rp613 +ag2 +(g3 +tp614 +Rp615 +ag2 +(g3 +tp616 +Rp617 +aa(lp618 +g2 +(S'0.906' +p619 +tp620 +Rp621 +ag2 +(g3 +tp622 +Rp623 +ag2 +(g3 +tp624 +Rp625 +aa(lp626 +g2 +(S'0.918' +p627 +tp628 +Rp629 +ag2 +(g3 +tp630 +Rp631 +ag2 +(g3 +tp632 +Rp633 +aa(lp634 +g2 +(S'0.929' +p635 +tp636 +Rp637 +ag2 +(g3 +tp638 +Rp639 +ag2 +(g3 +tp640 +Rp641 +aa(lp642 +g2 +(S'0.941' +p643 +tp644 +Rp645 +ag2 +(g3 +tp646 +Rp647 +ag2 +(g3 +tp648 +Rp649 +aa(lp650 +g2 +(S'0.953' +p651 +tp652 +Rp653 +ag2 +(g3 +tp654 +Rp655 +ag2 +(g3 +tp656 +Rp657 +aa(lp658 +g2 +(S'0.965' +p659 +tp660 +Rp661 +ag2 +(g3 +tp662 +Rp663 +ag2 +(g3 +tp664 +Rp665 +aa(lp666 +g2 +(S'0.976' +p667 +tp668 +Rp669 +ag2 +(g3 +tp670 +Rp671 +ag2 +(g3 +tp672 +Rp673 +aa(lp674 +g2 +(S'0.988' +p675 +tp676 +Rp677 +ag2 +(g3 +tp678 +Rp679 +ag2 +(g3 +tp680 +Rp681 +aa(lp682 +g2 +(S'1' +p683 +tp684 +Rp685 +ag2 +(g3 +tp686 +Rp687 +ag2 +(g3 +tp688 +Rp689 +aa(lp690 +g2 +(g683 +tp691 +Rp692 +ag2 +(S'0.00784' +p693 +tp694 +Rp695 +ag2 +(g3 +tp696 +Rp697 +aa(lp698 +g2 +(g683 +tp699 +Rp700 +ag2 +(S'0.0196' +p701 +tp702 +Rp703 +ag2 +(g3 +tp704 +Rp705 +aa(lp706 +g2 +(g683 +tp707 +Rp708 +ag2 +(S'0.0314' +p709 +tp710 +Rp711 +ag2 +(g3 +tp712 +Rp713 +aa(lp714 +g2 +(g683 +tp715 +Rp716 +ag2 +(S'0.0431' +p717 +tp718 +Rp719 +ag2 +(g3 +tp720 +Rp721 +aa(lp722 +g2 +(g683 +tp723 +Rp724 +ag2 +(S'0.0549' +p725 +tp726 +Rp727 +ag2 +(g3 +tp728 +Rp729 +aa(lp730 +g2 +(g683 +tp731 +Rp732 +ag2 +(S'0.0667' +p733 +tp734 +Rp735 +ag2 +(g3 +tp736 +Rp737 +aa(lp738 +g2 +(g683 +tp739 +Rp740 +ag2 +(S'0.0784' +p741 +tp742 +Rp743 +ag2 +(g3 +tp744 +Rp745 +aa(lp746 +g2 +(g683 +tp747 +Rp748 +ag2 +(S'0.0902' +p749 +tp750 +Rp751 +ag2 +(g3 +tp752 +Rp753 +aa(lp754 +g2 +(g683 +tp755 +Rp756 +ag2 +(S'0.102' +p757 +tp758 +Rp759 +ag2 +(g3 +tp760 +Rp761 +aa(lp762 +g2 +(g683 +tp763 +Rp764 +ag2 +(S'0.114' +p765 +tp766 +Rp767 +ag2 +(g3 +tp768 +Rp769 +aa(lp770 +g2 +(g683 +tp771 +Rp772 +ag2 +(S'0.125' +p773 +tp774 +Rp775 +ag2 +(g3 +tp776 +Rp777 +aa(lp778 +g2 +(g683 +tp779 +Rp780 +ag2 +(S'0.137' +p781 +tp782 +Rp783 +ag2 +(g3 +tp784 +Rp785 +aa(lp786 +g2 +(g683 +tp787 +Rp788 +ag2 +(S'0.149' +p789 +tp790 +Rp791 +ag2 +(g3 +tp792 +Rp793 +aa(lp794 +g2 +(g683 +tp795 +Rp796 +ag2 +(S'0.161' +p797 +tp798 +Rp799 +ag2 +(g3 +tp800 +Rp801 +aa(lp802 +g2 +(g683 +tp803 +Rp804 +ag2 +(S'0.173' +p805 +tp806 +Rp807 +ag2 +(g3 +tp808 +Rp809 +aa(lp810 +g2 +(g683 +tp811 +Rp812 +ag2 +(S'0.184' +p813 +tp814 +Rp815 +ag2 +(g3 +tp816 +Rp817 +aa(lp818 +g2 +(g683 +tp819 +Rp820 +ag2 +(S'0.196' +p821 +tp822 +Rp823 +ag2 +(g3 +tp824 +Rp825 +aa(lp826 +g2 +(g683 +tp827 +Rp828 +ag2 +(S'0.208' +p829 +tp830 +Rp831 +ag2 +(g3 +tp832 +Rp833 +aa(lp834 +g2 +(g683 +tp835 +Rp836 +ag2 +(S'0.220' +p837 +tp838 +Rp839 +ag2 +(g3 +tp840 +Rp841 +aa(lp842 +g2 +(g683 +tp843 +Rp844 +ag2 +(S'0.231' +p845 +tp846 +Rp847 +ag2 +(g3 +tp848 +Rp849 +aa(lp850 +g2 +(g683 +tp851 +Rp852 +ag2 +(S'0.243' +p853 +tp854 +Rp855 +ag2 +(g3 +tp856 +Rp857 +aa(lp858 +g2 +(g683 +tp859 +Rp860 +ag2 +(S'0.255' +p861 +tp862 +Rp863 +ag2 +(g3 +tp864 +Rp865 +aa(lp866 +g2 +(g683 +tp867 +Rp868 +ag2 +(S'0.267' +p869 +tp870 +Rp871 +ag2 +(g3 +tp872 +Rp873 +aa(lp874 +g2 +(g683 +tp875 +Rp876 +ag2 +(S'0.278' +p877 +tp878 +Rp879 +ag2 +(g3 +tp880 +Rp881 +aa(lp882 +g2 +(g683 +tp883 +Rp884 +ag2 +(S'0.290' +p885 +tp886 +Rp887 +ag2 +(g3 +tp888 +Rp889 +aa(lp890 +g2 +(g683 +tp891 +Rp892 +ag2 +(S'0.302' +p893 +tp894 +Rp895 +ag2 +(g3 +tp896 +Rp897 +aa(lp898 +g2 +(g683 +tp899 +Rp900 +ag2 +(S'0.314' +p901 +tp902 +Rp903 +ag2 +(g3 +tp904 +Rp905 +aa(lp906 +g2 +(g683 +tp907 +Rp908 +ag2 +(S'0.325' +p909 +tp910 +Rp911 +ag2 +(g3 +tp912 +Rp913 +aa(lp914 +g2 +(g683 +tp915 +Rp916 +ag2 +(S'0.337' +p917 +tp918 +Rp919 +ag2 +(g3 +tp920 +Rp921 +aa(lp922 +g2 +(g683 +tp923 +Rp924 +ag2 +(S'0.349' +p925 +tp926 +Rp927 +ag2 +(g3 +tp928 +Rp929 +aa(lp930 +g2 +(g683 +tp931 +Rp932 +ag2 +(S'0.361' +p933 +tp934 +Rp935 +ag2 +(g3 +tp936 +Rp937 +aa(lp938 +g2 +(g683 +tp939 +Rp940 +ag2 +(S'0.373' +p941 +tp942 +Rp943 +ag2 +(g3 +tp944 +Rp945 +aa(lp946 +g2 +(g683 +tp947 +Rp948 +ag2 +(S'0.384' +p949 +tp950 +Rp951 +ag2 +(g3 +tp952 +Rp953 +aa(lp954 +g2 +(g683 +tp955 +Rp956 +ag2 +(S'0.396' +p957 +tp958 +Rp959 +ag2 +(g3 +tp960 +Rp961 +aa(lp962 +g2 +(g683 +tp963 +Rp964 +ag2 +(S'0.408' +p965 +tp966 +Rp967 +ag2 +(g3 +tp968 +Rp969 +aa(lp970 +g2 +(g683 +tp971 +Rp972 +ag2 +(S'0.420' +p973 +tp974 +Rp975 +ag2 +(g3 +tp976 +Rp977 +aa(lp978 +g2 +(g683 +tp979 +Rp980 +ag2 +(S'0.431' +p981 +tp982 +Rp983 +ag2 +(g3 +tp984 +Rp985 +aa(lp986 +g2 +(g683 +tp987 +Rp988 +ag2 +(S'0.443' +p989 +tp990 +Rp991 +ag2 +(g3 +tp992 +Rp993 +aa(lp994 +g2 +(g683 +tp995 +Rp996 +ag2 +(S'0.455' +p997 +tp998 +Rp999 +ag2 +(g3 +tp1000 +Rp1001 +aa(lp1002 +g2 +(g683 +tp1003 +Rp1004 +ag2 +(S'0.467' +p1005 +tp1006 +Rp1007 +ag2 +(g3 +tp1008 +Rp1009 +aa(lp1010 +g2 +(g683 +tp1011 +Rp1012 +ag2 +(S'0.478' +p1013 +tp1014 +Rp1015 +ag2 +(g3 +tp1016 +Rp1017 +aa(lp1018 +g2 +(g683 +tp1019 +Rp1020 +ag2 +(S'0.490' +p1021 +tp1022 +Rp1023 +ag2 +(g3 +tp1024 +Rp1025 +aa(lp1026 +g2 +(g683 +tp1027 +Rp1028 +ag2 +(S'0.502' +p1029 +tp1030 +Rp1031 +ag2 +(g3 +tp1032 +Rp1033 +aa(lp1034 +g2 +(g683 +tp1035 +Rp1036 +ag2 +(S'0.514' +p1037 +tp1038 +Rp1039 +ag2 +(g3 +tp1040 +Rp1041 +aa(lp1042 +g2 +(g683 +tp1043 +Rp1044 +ag2 +(S'0.525' +p1045 +tp1046 +Rp1047 +ag2 +(g3 +tp1048 +Rp1049 +aa(lp1050 +g2 +(g683 +tp1051 +Rp1052 +ag2 +(S'0.537' +p1053 +tp1054 +Rp1055 +ag2 +(g3 +tp1056 +Rp1057 +aa(lp1058 +g2 +(g683 +tp1059 +Rp1060 +ag2 +(S'0.549' +p1061 +tp1062 +Rp1063 +ag2 +(g3 +tp1064 +Rp1065 +aa(lp1066 +g2 +(g683 +tp1067 +Rp1068 +ag2 +(S'0.561' +p1069 +tp1070 +Rp1071 +ag2 +(g3 +tp1072 +Rp1073 +aa(lp1074 +g2 +(g683 +tp1075 +Rp1076 +ag2 +(S'0.573' +p1077 +tp1078 +Rp1079 +ag2 +(g3 +tp1080 +Rp1081 +aa(lp1082 +g2 +(g683 +tp1083 +Rp1084 +ag2 +(S'0.584' +p1085 +tp1086 +Rp1087 +ag2 +(g3 +tp1088 +Rp1089 +aa(lp1090 +g2 +(g683 +tp1091 +Rp1092 +ag2 +(S'0.596' +p1093 +tp1094 +Rp1095 +ag2 +(g3 +tp1096 +Rp1097 +aa(lp1098 +g2 +(g683 +tp1099 +Rp1100 +ag2 +(S'0.608' +p1101 +tp1102 +Rp1103 +ag2 +(g3 +tp1104 +Rp1105 +aa(lp1106 +g2 +(g683 +tp1107 +Rp1108 +ag2 +(S'0.620' +p1109 +tp1110 +Rp1111 +ag2 +(g3 +tp1112 +Rp1113 +aa(lp1114 +g2 +(g683 +tp1115 +Rp1116 +ag2 +(S'0.631' +p1117 +tp1118 +Rp1119 +ag2 +(g3 +tp1120 +Rp1121 +aa(lp1122 +g2 +(g683 +tp1123 +Rp1124 +ag2 +(S'0.643' +p1125 +tp1126 +Rp1127 +ag2 +(g3 +tp1128 +Rp1129 +aa(lp1130 +g2 +(g683 +tp1131 +Rp1132 +ag2 +(S'0.655' +p1133 +tp1134 +Rp1135 +ag2 +(g3 +tp1136 +Rp1137 +aa(lp1138 +g2 +(g683 +tp1139 +Rp1140 +ag2 +(S'0.667' +p1141 +tp1142 +Rp1143 +ag2 +(g3 +tp1144 +Rp1145 +aa(lp1146 +g2 +(g683 +tp1147 +Rp1148 +ag2 +(S'0.678' +p1149 +tp1150 +Rp1151 +ag2 +(g3 +tp1152 +Rp1153 +aa(lp1154 +g2 +(g683 +tp1155 +Rp1156 +ag2 +(S'0.690' +p1157 +tp1158 +Rp1159 +ag2 +(g3 +tp1160 +Rp1161 +aa(lp1162 +g2 +(g683 +tp1163 +Rp1164 +ag2 +(S'0.702' +p1165 +tp1166 +Rp1167 +ag2 +(g3 +tp1168 +Rp1169 +aa(lp1170 +g2 +(g683 +tp1171 +Rp1172 +ag2 +(S'0.714' +p1173 +tp1174 +Rp1175 +ag2 +(g3 +tp1176 +Rp1177 +aa(lp1178 +g2 +(g683 +tp1179 +Rp1180 +ag2 +(S'0.725' +p1181 +tp1182 +Rp1183 +ag2 +(g3 +tp1184 +Rp1185 +aa(lp1186 +g2 +(g683 +tp1187 +Rp1188 +ag2 +(S'0.737' +p1189 +tp1190 +Rp1191 +ag2 +(g3 +tp1192 +Rp1193 +aa(lp1194 +g2 +(g683 +tp1195 +Rp1196 +ag2 +(S'0.749' +p1197 +tp1198 +Rp1199 +ag2 +(g3 +tp1200 +Rp1201 +aa(lp1202 +g2 +(g683 +tp1203 +Rp1204 +ag2 +(S'0.761' +p1205 +tp1206 +Rp1207 +ag2 +(g3 +tp1208 +Rp1209 +aa(lp1210 +g2 +(g683 +tp1211 +Rp1212 +ag2 +(S'0.773' +p1213 +tp1214 +Rp1215 +ag2 +(g3 +tp1216 +Rp1217 +aa(lp1218 +g2 +(g683 +tp1219 +Rp1220 +ag2 +(S'0.784' +p1221 +tp1222 +Rp1223 +ag2 +(g3 +tp1224 +Rp1225 +aa(lp1226 +g2 +(g683 +tp1227 +Rp1228 +ag2 +(S'0.796' +p1229 +tp1230 +Rp1231 +ag2 +(g3 +tp1232 +Rp1233 +aa(lp1234 +g2 +(g683 +tp1235 +Rp1236 +ag2 +(S'0.808' +p1237 +tp1238 +Rp1239 +ag2 +(g3 +tp1240 +Rp1241 +aa(lp1242 +g2 +(g683 +tp1243 +Rp1244 +ag2 +(S'0.820' +p1245 +tp1246 +Rp1247 +ag2 +(g3 +tp1248 +Rp1249 +aa(lp1250 +g2 +(g683 +tp1251 +Rp1252 +ag2 +(S'0.831' +p1253 +tp1254 +Rp1255 +ag2 +(g3 +tp1256 +Rp1257 +aa(lp1258 +g2 +(g683 +tp1259 +Rp1260 +ag2 +(S'0.843' +p1261 +tp1262 +Rp1263 +ag2 +(g3 +tp1264 +Rp1265 +aa(lp1266 +g2 +(g683 +tp1267 +Rp1268 +ag2 +(S'0.855' +p1269 +tp1270 +Rp1271 +ag2 +(g3 +tp1272 +Rp1273 +aa(lp1274 +g2 +(g683 +tp1275 +Rp1276 +ag2 +(S'0.867' +p1277 +tp1278 +Rp1279 +ag2 +(g3 +tp1280 +Rp1281 +aa(lp1282 +g2 +(g683 +tp1283 +Rp1284 +ag2 +(S'0.878' +p1285 +tp1286 +Rp1287 +ag2 +(g3 +tp1288 +Rp1289 +aa(lp1290 +g2 +(g683 +tp1291 +Rp1292 +ag2 +(S'0.890' +p1293 +tp1294 +Rp1295 +ag2 +(g3 +tp1296 +Rp1297 +aa(lp1298 +g2 +(g683 +tp1299 +Rp1300 +ag2 +(S'0.902' +p1301 +tp1302 +Rp1303 +ag2 +(g3 +tp1304 +Rp1305 +aa(lp1306 +g2 +(g683 +tp1307 +Rp1308 +ag2 +(S'0.914' +p1309 +tp1310 +Rp1311 +ag2 +(g3 +tp1312 +Rp1313 +aa(lp1314 +g2 +(g683 +tp1315 +Rp1316 +ag2 +(S'0.925' +p1317 +tp1318 +Rp1319 +ag2 +(g3 +tp1320 +Rp1321 +aa(lp1322 +g2 +(g683 +tp1323 +Rp1324 +ag2 +(S'0.937' +p1325 +tp1326 +Rp1327 +ag2 +(g3 +tp1328 +Rp1329 +aa(lp1330 +g2 +(g683 +tp1331 +Rp1332 +ag2 +(S'0.949' +p1333 +tp1334 +Rp1335 +ag2 +(g3 +tp1336 +Rp1337 +aa(lp1338 +g2 +(g683 +tp1339 +Rp1340 +ag2 +(S'0.961' +p1341 +tp1342 +Rp1343 +ag2 +(g3 +tp1344 +Rp1345 +aa(lp1346 +g2 +(g683 +tp1347 +Rp1348 +ag2 +(S'0.973' +p1349 +tp1350 +Rp1351 +ag2 +(g3 +tp1352 +Rp1353 +aa(lp1354 +g2 +(g683 +tp1355 +Rp1356 +ag2 +(S'0.984' +p1357 +tp1358 +Rp1359 +ag2 +(g3 +tp1360 +Rp1361 +aa(lp1362 +g2 +(g683 +tp1363 +Rp1364 +ag2 +(S'0.996' +p1365 +tp1366 +Rp1367 +ag2 +(g3 +tp1368 +Rp1369 +aa(lp1370 +g2 +(g683 +tp1371 +Rp1372 +ag2 +(g683 +tp1373 +Rp1374 +ag2 +(S'0.00392' +p1375 +tp1376 +Rp1377 +aa(lp1378 +g2 +(g683 +tp1379 +Rp1380 +ag2 +(g683 +tp1381 +Rp1382 +ag2 +(S'0.0157' +p1383 +tp1384 +Rp1385 +aa(lp1386 +g2 +(g683 +tp1387 +Rp1388 +ag2 +(g683 +tp1389 +Rp1390 +ag2 +(S'0.0275' +p1391 +tp1392 +Rp1393 +aa(lp1394 +g2 +(g683 +tp1395 +Rp1396 +ag2 +(g683 +tp1397 +Rp1398 +ag2 +(S'0.0392' +p1399 +tp1400 +Rp1401 +aa(lp1402 +g2 +(g683 +tp1403 +Rp1404 +ag2 +(g683 +tp1405 +Rp1406 +ag2 +(S'0.0510' +p1407 +tp1408 +Rp1409 +aa(lp1410 +g2 +(g683 +tp1411 +Rp1412 +ag2 +(g683 +tp1413 +Rp1414 +ag2 +(S'0.0627' +p1415 +tp1416 +Rp1417 +aa(lp1418 +g2 +(g683 +tp1419 +Rp1420 +ag2 +(g683 +tp1421 +Rp1422 +ag2 +(S'0.0745' +p1423 +tp1424 +Rp1425 +aa(lp1426 +g2 +(g683 +tp1427 +Rp1428 +ag2 +(g683 +tp1429 +Rp1430 +ag2 +(S'0.0863' +p1431 +tp1432 +Rp1433 +aa(lp1434 +g2 +(g683 +tp1435 +Rp1436 +ag2 +(g683 +tp1437 +Rp1438 +ag2 +(S'0.0980' +p1439 +tp1440 +Rp1441 +aa(lp1442 +g2 +(g683 +tp1443 +Rp1444 +ag2 +(g683 +tp1445 +Rp1446 +ag2 +(S'0.110' +p1447 +tp1448 +Rp1449 +aa(lp1450 +g2 +(g683 +tp1451 +Rp1452 +ag2 +(g683 +tp1453 +Rp1454 +ag2 +(S'0.122' +p1455 +tp1456 +Rp1457 +aa(lp1458 +g2 +(g683 +tp1459 +Rp1460 +ag2 +(g683 +tp1461 +Rp1462 +ag2 +(S'0.133' +p1463 +tp1464 +Rp1465 +aa(lp1466 +g2 +(g683 +tp1467 +Rp1468 +ag2 +(g683 +tp1469 +Rp1470 +ag2 +(S'0.145' +p1471 +tp1472 +Rp1473 +aa(lp1474 +g2 +(g683 +tp1475 +Rp1476 +ag2 +(g683 +tp1477 +Rp1478 +ag2 +(S'0.157' +p1479 +tp1480 +Rp1481 +aa(lp1482 +g2 +(g683 +tp1483 +Rp1484 +ag2 +(g683 +tp1485 +Rp1486 +ag2 +(S'0.169' +p1487 +tp1488 +Rp1489 +aa(lp1490 +g2 +(g683 +tp1491 +Rp1492 +ag2 +(g683 +tp1493 +Rp1494 +ag2 +(S'0.180' +p1495 +tp1496 +Rp1497 +aa(lp1498 +g2 +(g683 +tp1499 +Rp1500 +ag2 +(g683 +tp1501 +Rp1502 +ag2 +(S'0.192' +p1503 +tp1504 +Rp1505 +aa(lp1506 +g2 +(g683 +tp1507 +Rp1508 +ag2 +(g683 +tp1509 +Rp1510 +ag2 +(S'0.204' +p1511 +tp1512 +Rp1513 +aa(lp1514 +g2 +(g683 +tp1515 +Rp1516 +ag2 +(g683 +tp1517 +Rp1518 +ag2 +(S'0.216' +p1519 +tp1520 +Rp1521 +aa(lp1522 +g2 +(g683 +tp1523 +Rp1524 +ag2 +(g683 +tp1525 +Rp1526 +ag2 +(S'0.227' +p1527 +tp1528 +Rp1529 +aa(lp1530 +g2 +(g683 +tp1531 +Rp1532 +ag2 +(g683 +tp1533 +Rp1534 +ag2 +(S'0.239' +p1535 +tp1536 +Rp1537 +aa(lp1538 +g2 +(g683 +tp1539 +Rp1540 +ag2 +(g683 +tp1541 +Rp1542 +ag2 +(S'0.251' +p1543 +tp1544 +Rp1545 +aa(lp1546 +g2 +(g683 +tp1547 +Rp1548 +ag2 +(g683 +tp1549 +Rp1550 +ag2 +(S'0.263' +p1551 +tp1552 +Rp1553 +aa(lp1554 +g2 +(g683 +tp1555 +Rp1556 +ag2 +(g683 +tp1557 +Rp1558 +ag2 +(S'0.275' +p1559 +tp1560 +Rp1561 +aa(lp1562 +g2 +(g683 +tp1563 +Rp1564 +ag2 +(g683 +tp1565 +Rp1566 +ag2 +(S'0.286' +p1567 +tp1568 +Rp1569 +aa(lp1570 +g2 +(g683 +tp1571 +Rp1572 +ag2 +(g683 +tp1573 +Rp1574 +ag2 +(S'0.298' +p1575 +tp1576 +Rp1577 +aa(lp1578 +g2 +(g683 +tp1579 +Rp1580 +ag2 +(g683 +tp1581 +Rp1582 +ag2 +(S'0.310' +p1583 +tp1584 +Rp1585 +aa(lp1586 +g2 +(g683 +tp1587 +Rp1588 +ag2 +(g683 +tp1589 +Rp1590 +ag2 +(S'0.322' +p1591 +tp1592 +Rp1593 +aa(lp1594 +g2 +(g683 +tp1595 +Rp1596 +ag2 +(g683 +tp1597 +Rp1598 +ag2 +(S'0.333' +p1599 +tp1600 +Rp1601 +aa(lp1602 +g2 +(g683 +tp1603 +Rp1604 +ag2 +(g683 +tp1605 +Rp1606 +ag2 +(S'0.345' +p1607 +tp1608 +Rp1609 +aa(lp1610 +g2 +(g683 +tp1611 +Rp1612 +ag2 +(g683 +tp1613 +Rp1614 +ag2 +(S'0.357' +p1615 +tp1616 +Rp1617 +aa(lp1618 +g2 +(g683 +tp1619 +Rp1620 +ag2 +(g683 +tp1621 +Rp1622 +ag2 +(S'0.369' +p1623 +tp1624 +Rp1625 +aa(lp1626 +g2 +(g683 +tp1627 +Rp1628 +ag2 +(g683 +tp1629 +Rp1630 +ag2 +(S'0.380' +p1631 +tp1632 +Rp1633 +aa(lp1634 +g2 +(g683 +tp1635 +Rp1636 +ag2 +(g683 +tp1637 +Rp1638 +ag2 +(S'0.392' +p1639 +tp1640 +Rp1641 +aa(lp1642 +g2 +(g683 +tp1643 +Rp1644 +ag2 +(g683 +tp1645 +Rp1646 +ag2 +(S'0.404' +p1647 +tp1648 +Rp1649 +aa(lp1650 +g2 +(g683 +tp1651 +Rp1652 +ag2 +(g683 +tp1653 +Rp1654 +ag2 +(S'0.416' +p1655 +tp1656 +Rp1657 +aa(lp1658 +g2 +(g683 +tp1659 +Rp1660 +ag2 +(g683 +tp1661 +Rp1662 +ag2 +(S'0.427' +p1663 +tp1664 +Rp1665 +aa(lp1666 +g2 +(g683 +tp1667 +Rp1668 +ag2 +(g683 +tp1669 +Rp1670 +ag2 +(S'0.439' +p1671 +tp1672 +Rp1673 +aa(lp1674 +g2 +(g683 +tp1675 +Rp1676 +ag2 +(g683 +tp1677 +Rp1678 +ag2 +(S'0.451' +p1679 +tp1680 +Rp1681 +aa(lp1682 +g2 +(g683 +tp1683 +Rp1684 +ag2 +(g683 +tp1685 +Rp1686 +ag2 +(S'0.463' +p1687 +tp1688 +Rp1689 +aa(lp1690 +g2 +(g683 +tp1691 +Rp1692 +ag2 +(g683 +tp1693 +Rp1694 +ag2 +(S'0.475' +p1695 +tp1696 +Rp1697 +aa(lp1698 +g2 +(g683 +tp1699 +Rp1700 +ag2 +(g683 +tp1701 +Rp1702 +ag2 +(S'0.486' +p1703 +tp1704 +Rp1705 +aa(lp1706 +g2 +(g683 +tp1707 +Rp1708 +ag2 +(g683 +tp1709 +Rp1710 +ag2 +(S'0.498' +p1711 +tp1712 +Rp1713 +aa(lp1714 +g2 +(g683 +tp1715 +Rp1716 +ag2 +(g683 +tp1717 +Rp1718 +ag2 +(S'0.510' +p1719 +tp1720 +Rp1721 +aa(lp1722 +g2 +(g683 +tp1723 +Rp1724 +ag2 +(g683 +tp1725 +Rp1726 +ag2 +(S'0.522' +p1727 +tp1728 +Rp1729 +aa(lp1730 +g2 +(g683 +tp1731 +Rp1732 +ag2 +(g683 +tp1733 +Rp1734 +ag2 +(S'0.533' +p1735 +tp1736 +Rp1737 +aa(lp1738 +g2 +(g683 +tp1739 +Rp1740 +ag2 +(g683 +tp1741 +Rp1742 +ag2 +(S'0.545' +p1743 +tp1744 +Rp1745 +aa(lp1746 +g2 +(g683 +tp1747 +Rp1748 +ag2 +(g683 +tp1749 +Rp1750 +ag2 +(S'0.557' +p1751 +tp1752 +Rp1753 +aa(lp1754 +g2 +(g683 +tp1755 +Rp1756 +ag2 +(g683 +tp1757 +Rp1758 +ag2 +(S'0.569' +p1759 +tp1760 +Rp1761 +aa(lp1762 +g2 +(g683 +tp1763 +Rp1764 +ag2 +(g683 +tp1765 +Rp1766 +ag2 +(S'0.580' +p1767 +tp1768 +Rp1769 +aa(lp1770 +g2 +(g683 +tp1771 +Rp1772 +ag2 +(g683 +tp1773 +Rp1774 +ag2 +(S'0.592' +p1775 +tp1776 +Rp1777 +aa(lp1778 +g2 +(g683 +tp1779 +Rp1780 +ag2 +(g683 +tp1781 +Rp1782 +ag2 +(S'0.604' +p1783 +tp1784 +Rp1785 +aa(lp1786 +g2 +(g683 +tp1787 +Rp1788 +ag2 +(g683 +tp1789 +Rp1790 +ag2 +(S'0.616' +p1791 +tp1792 +Rp1793 +aa(lp1794 +g2 +(g683 +tp1795 +Rp1796 +ag2 +(g683 +tp1797 +Rp1798 +ag2 +(S'0.627' +p1799 +tp1800 +Rp1801 +aa(lp1802 +g2 +(g683 +tp1803 +Rp1804 +ag2 +(g683 +tp1805 +Rp1806 +ag2 +(S'0.639' +p1807 +tp1808 +Rp1809 +aa(lp1810 +g2 +(g683 +tp1811 +Rp1812 +ag2 +(g683 +tp1813 +Rp1814 +ag2 +(S'0.651' +p1815 +tp1816 +Rp1817 +aa(lp1818 +g2 +(g683 +tp1819 +Rp1820 +ag2 +(g683 +tp1821 +Rp1822 +ag2 +(S'0.663' +p1823 +tp1824 +Rp1825 +aa(lp1826 +g2 +(g683 +tp1827 +Rp1828 +ag2 +(g683 +tp1829 +Rp1830 +ag2 +(S'0.675' +p1831 +tp1832 +Rp1833 +aa(lp1834 +g2 +(g683 +tp1835 +Rp1836 +ag2 +(g683 +tp1837 +Rp1838 +ag2 +(S'0.686' +p1839 +tp1840 +Rp1841 +aa(lp1842 +g2 +(g683 +tp1843 +Rp1844 +ag2 +(g683 +tp1845 +Rp1846 +ag2 +(S'0.698' +p1847 +tp1848 +Rp1849 +aa(lp1850 +g2 +(g683 +tp1851 +Rp1852 +ag2 +(g683 +tp1853 +Rp1854 +ag2 +(S'0.710' +p1855 +tp1856 +Rp1857 +aa(lp1858 +g2 +(g683 +tp1859 +Rp1860 +ag2 +(g683 +tp1861 +Rp1862 +ag2 +(S'0.722' +p1863 +tp1864 +Rp1865 +aa(lp1866 +g2 +(g683 +tp1867 +Rp1868 +ag2 +(g683 +tp1869 +Rp1870 +ag2 +(S'0.733' +p1871 +tp1872 +Rp1873 +aa(lp1874 +g2 +(g683 +tp1875 +Rp1876 +ag2 +(g683 +tp1877 +Rp1878 +ag2 +(S'0.745' +p1879 +tp1880 +Rp1881 +aa(lp1882 +g2 +(g683 +tp1883 +Rp1884 +ag2 +(g683 +tp1885 +Rp1886 +ag2 +(S'0.757' +p1887 +tp1888 +Rp1889 +aa(lp1890 +g2 +(g683 +tp1891 +Rp1892 +ag2 +(g683 +tp1893 +Rp1894 +ag2 +(S'0.769' +p1895 +tp1896 +Rp1897 +aa(lp1898 +g2 +(g683 +tp1899 +Rp1900 +ag2 +(g683 +tp1901 +Rp1902 +ag2 +(S'0.780' +p1903 +tp1904 +Rp1905 +aa(lp1906 +g2 +(g683 +tp1907 +Rp1908 +ag2 +(g683 +tp1909 +Rp1910 +ag2 +(S'0.792' +p1911 +tp1912 +Rp1913 +aa(lp1914 +g2 +(g683 +tp1915 +Rp1916 +ag2 +(g683 +tp1917 +Rp1918 +ag2 +(S'0.804' +p1919 +tp1920 +Rp1921 +aa(lp1922 +g2 +(g683 +tp1923 +Rp1924 +ag2 +(g683 +tp1925 +Rp1926 +ag2 +(S'0.816' +p1927 +tp1928 +Rp1929 +aa(lp1930 +g2 +(g683 +tp1931 +Rp1932 +ag2 +(g683 +tp1933 +Rp1934 +ag2 +(S'0.827' +p1935 +tp1936 +Rp1937 +aa(lp1938 +g2 +(g683 +tp1939 +Rp1940 +ag2 +(g683 +tp1941 +Rp1942 +ag2 +(S'0.839' +p1943 +tp1944 +Rp1945 +aa(lp1946 +g2 +(g683 +tp1947 +Rp1948 +ag2 +(g683 +tp1949 +Rp1950 +ag2 +(S'0.851' +p1951 +tp1952 +Rp1953 +aa(lp1954 +g2 +(g683 +tp1955 +Rp1956 +ag2 +(g683 +tp1957 +Rp1958 +ag2 +(S'0.863' +p1959 +tp1960 +Rp1961 +aa(lp1962 +g2 +(g683 +tp1963 +Rp1964 +ag2 +(g683 +tp1965 +Rp1966 +ag2 +(S'0.875' +p1967 +tp1968 +Rp1969 +aa(lp1970 +g2 +(g683 +tp1971 +Rp1972 +ag2 +(g683 +tp1973 +Rp1974 +ag2 +(S'0.886' +p1975 +tp1976 +Rp1977 +aa(lp1978 +g2 +(g683 +tp1979 +Rp1980 +ag2 +(g683 +tp1981 +Rp1982 +ag2 +(S'0.898' +p1983 +tp1984 +Rp1985 +aa(lp1986 +g2 +(g683 +tp1987 +Rp1988 +ag2 +(g683 +tp1989 +Rp1990 +ag2 +(S'0.910' +p1991 +tp1992 +Rp1993 +aa(lp1994 +g2 +(g683 +tp1995 +Rp1996 +ag2 +(g683 +tp1997 +Rp1998 +ag2 +(S'0.922' +p1999 +tp2000 +Rp2001 +aa(lp2002 +g2 +(g683 +tp2003 +Rp2004 +ag2 +(g683 +tp2005 +Rp2006 +ag2 +(S'0.933' +p2007 +tp2008 +Rp2009 +aa(lp2010 +g2 +(g683 +tp2011 +Rp2012 +ag2 +(g683 +tp2013 +Rp2014 +ag2 +(S'0.945' +p2015 +tp2016 +Rp2017 +aa(lp2018 +g2 +(g683 +tp2019 +Rp2020 +ag2 +(g683 +tp2021 +Rp2022 +ag2 +(S'0.957' +p2023 +tp2024 +Rp2025 +aa(lp2026 +g2 +(g683 +tp2027 +Rp2028 +ag2 +(g683 +tp2029 +Rp2030 +ag2 +(S'0.969' +p2031 +tp2032 +Rp2033 +aa(lp2034 +g2 +(g683 +tp2035 +Rp2036 +ag2 +(g683 +tp2037 +Rp2038 +ag2 +(S'0.980' +p2039 +tp2040 +Rp2041 +aa(lp2042 +g2 +(g683 +tp2043 +Rp2044 +ag2 +(g683 +tp2045 +Rp2046 +ag2 +(S'0.992' +p2047 +tp2048 +Rp2049 +aa. \ No newline at end of file diff --git a/moose-gui/colormaps/jet b/moose-gui/colormaps/jet new file mode 100644 index 0000000000000000000000000000000000000000..99ec8b83470ec412d574eb3a44bf80ce05ca720f --- /dev/null +++ b/moose-gui/colormaps/jet @@ -0,0 +1,3649 @@ +(lp0 +(lp1 +cdecimal +Decimal +p2 +(S'0' +p3 +tp4 +Rp5 +ag2 +(g3 +tp6 +Rp7 +ag2 +(S'0.498' +p8 +tp9 +Rp10 +aa(lp11 +g2 +(g3 +tp12 +Rp13 +ag2 +(g3 +tp14 +Rp15 +ag2 +(S'0.514' +p16 +tp17 +Rp18 +aa(lp19 +g2 +(g3 +tp20 +Rp21 +ag2 +(g3 +tp22 +Rp23 +ag2 +(S'0.529' +p24 +tp25 +Rp26 +aa(lp27 +g2 +(g3 +tp28 +Rp29 +ag2 +(g3 +tp30 +Rp31 +ag2 +(S'0.545' +p32 +tp33 +Rp34 +aa(lp35 +g2 +(g3 +tp36 +Rp37 +ag2 +(g3 +tp38 +Rp39 +ag2 +(S'0.561' +p40 +tp41 +Rp42 +aa(lp43 +g2 +(g3 +tp44 +Rp45 +ag2 +(g3 +tp46 +Rp47 +ag2 +(S'0.576' +p48 +tp49 +Rp50 +aa(lp51 +g2 +(g3 +tp52 +Rp53 +ag2 +(g3 +tp54 +Rp55 +ag2 +(S'0.592' +p56 +tp57 +Rp58 +aa(lp59 +g2 +(g3 +tp60 +Rp61 +ag2 +(g3 +tp62 +Rp63 +ag2 +(S'0.608' +p64 +tp65 +Rp66 +aa(lp67 +g2 +(g3 +tp68 +Rp69 +ag2 +(g3 +tp70 +Rp71 +ag2 +(S'0.624' +p72 +tp73 +Rp74 +aa(lp75 +g2 +(g3 +tp76 +Rp77 +ag2 +(g3 +tp78 +Rp79 +ag2 +(S'0.639' +p80 +tp81 +Rp82 +aa(lp83 +g2 +(g3 +tp84 +Rp85 +ag2 +(g3 +tp86 +Rp87 +ag2 +(S'0.655' +p88 +tp89 +Rp90 +aa(lp91 +g2 +(g3 +tp92 +Rp93 +ag2 +(g3 +tp94 +Rp95 +ag2 +(S'0.671' +p96 +tp97 +Rp98 +aa(lp99 +g2 +(g3 +tp100 +Rp101 +ag2 +(g3 +tp102 +Rp103 +ag2 +(S'0.686' +p104 +tp105 +Rp106 +aa(lp107 +g2 +(g3 +tp108 +Rp109 +ag2 +(g3 +tp110 +Rp111 +ag2 +(S'0.702' +p112 +tp113 +Rp114 +aa(lp115 +g2 +(g3 +tp116 +Rp117 +ag2 +(g3 +tp118 +Rp119 +ag2 +(S'0.718' +p120 +tp121 +Rp122 +aa(lp123 +g2 +(g3 +tp124 +Rp125 +ag2 +(g3 +tp126 +Rp127 +ag2 +(S'0.733' +p128 +tp129 +Rp130 +aa(lp131 +g2 +(g3 +tp132 +Rp133 +ag2 +(g3 +tp134 +Rp135 +ag2 +(S'0.749' +p136 +tp137 +Rp138 +aa(lp139 +g2 +(g3 +tp140 +Rp141 +ag2 +(g3 +tp142 +Rp143 +ag2 +(S'0.765' +p144 +tp145 +Rp146 +aa(lp147 +g2 +(g3 +tp148 +Rp149 +ag2 +(g3 +tp150 +Rp151 +ag2 +(S'0.780' +p152 +tp153 +Rp154 +aa(lp155 +g2 +(g3 +tp156 +Rp157 +ag2 +(g3 +tp158 +Rp159 +ag2 +(S'0.796' +p160 +tp161 +Rp162 +aa(lp163 +g2 +(g3 +tp164 +Rp165 +ag2 +(g3 +tp166 +Rp167 +ag2 +(S'0.812' +p168 +tp169 +Rp170 +aa(lp171 +g2 +(g3 +tp172 +Rp173 +ag2 +(g3 +tp174 +Rp175 +ag2 +(S'0.827' +p176 +tp177 +Rp178 +aa(lp179 +g2 +(g3 +tp180 +Rp181 +ag2 +(g3 +tp182 +Rp183 +ag2 +(S'0.843' +p184 +tp185 +Rp186 +aa(lp187 +g2 +(g3 +tp188 +Rp189 +ag2 +(g3 +tp190 +Rp191 +ag2 +(S'0.859' +p192 +tp193 +Rp194 +aa(lp195 +g2 +(g3 +tp196 +Rp197 +ag2 +(g3 +tp198 +Rp199 +ag2 +(S'0.875' +p200 +tp201 +Rp202 +aa(lp203 +g2 +(g3 +tp204 +Rp205 +ag2 +(g3 +tp206 +Rp207 +ag2 +(S'0.890' +p208 +tp209 +Rp210 +aa(lp211 +g2 +(g3 +tp212 +Rp213 +ag2 +(g3 +tp214 +Rp215 +ag2 +(S'0.906' +p216 +tp217 +Rp218 +aa(lp219 +g2 +(g3 +tp220 +Rp221 +ag2 +(g3 +tp222 +Rp223 +ag2 +(S'0.922' +p224 +tp225 +Rp226 +aa(lp227 +g2 +(g3 +tp228 +Rp229 +ag2 +(g3 +tp230 +Rp231 +ag2 +(S'0.937' +p232 +tp233 +Rp234 +aa(lp235 +g2 +(g3 +tp236 +Rp237 +ag2 +(g3 +tp238 +Rp239 +ag2 +(S'0.953' +p240 +tp241 +Rp242 +aa(lp243 +g2 +(g3 +tp244 +Rp245 +ag2 +(g3 +tp246 +Rp247 +ag2 +(S'0.969' +p248 +tp249 +Rp250 +aa(lp251 +g2 +(g3 +tp252 +Rp253 +ag2 +(g3 +tp254 +Rp255 +ag2 +(S'0.984' +p256 +tp257 +Rp258 +aa(lp259 +g2 +(g3 +tp260 +Rp261 +ag2 +(g3 +tp262 +Rp263 +ag2 +(S'1' +p264 +tp265 +Rp266 +aa(lp267 +g2 +(g3 +tp268 +Rp269 +ag2 +(S'0.0157' +p270 +tp271 +Rp272 +ag2 +(g264 +tp273 +Rp274 +aa(lp275 +g2 +(g3 +tp276 +Rp277 +ag2 +(S'0.0314' +p278 +tp279 +Rp280 +ag2 +(g264 +tp281 +Rp282 +aa(lp283 +g2 +(g3 +tp284 +Rp285 +ag2 +(S'0.0471' +p286 +tp287 +Rp288 +ag2 +(g264 +tp289 +Rp290 +aa(lp291 +g2 +(g3 +tp292 +Rp293 +ag2 +(S'0.0627' +p294 +tp295 +Rp296 +ag2 +(g264 +tp297 +Rp298 +aa(lp299 +g2 +(g3 +tp300 +Rp301 +ag2 +(S'0.0784' +p302 +tp303 +Rp304 +ag2 +(g264 +tp305 +Rp306 +aa(lp307 +g2 +(g3 +tp308 +Rp309 +ag2 +(S'0.0941' +p310 +tp311 +Rp312 +ag2 +(g264 +tp313 +Rp314 +aa(lp315 +g2 +(g3 +tp316 +Rp317 +ag2 +(S'0.110' +p318 +tp319 +Rp320 +ag2 +(g264 +tp321 +Rp322 +aa(lp323 +g2 +(g3 +tp324 +Rp325 +ag2 +(S'0.125' +p326 +tp327 +Rp328 +ag2 +(g264 +tp329 +Rp330 +aa(lp331 +g2 +(g3 +tp332 +Rp333 +ag2 +(S'0.141' +p334 +tp335 +Rp336 +ag2 +(g264 +tp337 +Rp338 +aa(lp339 +g2 +(g3 +tp340 +Rp341 +ag2 +(S'0.157' +p342 +tp343 +Rp344 +ag2 +(g264 +tp345 +Rp346 +aa(lp347 +g2 +(g3 +tp348 +Rp349 +ag2 +(S'0.173' +p350 +tp351 +Rp352 +ag2 +(g264 +tp353 +Rp354 +aa(lp355 +g2 +(g3 +tp356 +Rp357 +ag2 +(S'0.188' +p358 +tp359 +Rp360 +ag2 +(g264 +tp361 +Rp362 +aa(lp363 +g2 +(g3 +tp364 +Rp365 +ag2 +(S'0.204' +p366 +tp367 +Rp368 +ag2 +(g264 +tp369 +Rp370 +aa(lp371 +g2 +(g3 +tp372 +Rp373 +ag2 +(S'0.220' +p374 +tp375 +Rp376 +ag2 +(g264 +tp377 +Rp378 +aa(lp379 +g2 +(g3 +tp380 +Rp381 +ag2 +(S'0.235' +p382 +tp383 +Rp384 +ag2 +(g264 +tp385 +Rp386 +aa(lp387 +g2 +(g3 +tp388 +Rp389 +ag2 +(S'0.251' +p390 +tp391 +Rp392 +ag2 +(g264 +tp393 +Rp394 +aa(lp395 +g2 +(g3 +tp396 +Rp397 +ag2 +(S'0.267' +p398 +tp399 +Rp400 +ag2 +(g264 +tp401 +Rp402 +aa(lp403 +g2 +(g3 +tp404 +Rp405 +ag2 +(S'0.282' +p406 +tp407 +Rp408 +ag2 +(g264 +tp409 +Rp410 +aa(lp411 +g2 +(g3 +tp412 +Rp413 +ag2 +(S'0.298' +p414 +tp415 +Rp416 +ag2 +(g264 +tp417 +Rp418 +aa(lp419 +g2 +(g3 +tp420 +Rp421 +ag2 +(S'0.314' +p422 +tp423 +Rp424 +ag2 +(g264 +tp425 +Rp426 +aa(lp427 +g2 +(g3 +tp428 +Rp429 +ag2 +(S'0.329' +p430 +tp431 +Rp432 +ag2 +(g264 +tp433 +Rp434 +aa(lp435 +g2 +(g3 +tp436 +Rp437 +ag2 +(S'0.345' +p438 +tp439 +Rp440 +ag2 +(g264 +tp441 +Rp442 +aa(lp443 +g2 +(g3 +tp444 +Rp445 +ag2 +(S'0.361' +p446 +tp447 +Rp448 +ag2 +(g264 +tp449 +Rp450 +aa(lp451 +g2 +(g3 +tp452 +Rp453 +ag2 +(S'0.376' +p454 +tp455 +Rp456 +ag2 +(g264 +tp457 +Rp458 +aa(lp459 +g2 +(g3 +tp460 +Rp461 +ag2 +(S'0.392' +p462 +tp463 +Rp464 +ag2 +(g264 +tp465 +Rp466 +aa(lp467 +g2 +(g3 +tp468 +Rp469 +ag2 +(S'0.408' +p470 +tp471 +Rp472 +ag2 +(g264 +tp473 +Rp474 +aa(lp475 +g2 +(g3 +tp476 +Rp477 +ag2 +(S'0.424' +p478 +tp479 +Rp480 +ag2 +(g264 +tp481 +Rp482 +aa(lp483 +g2 +(g3 +tp484 +Rp485 +ag2 +(S'0.439' +p486 +tp487 +Rp488 +ag2 +(g264 +tp489 +Rp490 +aa(lp491 +g2 +(g3 +tp492 +Rp493 +ag2 +(S'0.455' +p494 +tp495 +Rp496 +ag2 +(g264 +tp497 +Rp498 +aa(lp499 +g2 +(g3 +tp500 +Rp501 +ag2 +(S'0.471' +p502 +tp503 +Rp504 +ag2 +(g264 +tp505 +Rp506 +aa(lp507 +g2 +(g3 +tp508 +Rp509 +ag2 +(S'0.486' +p510 +tp511 +Rp512 +ag2 +(g264 +tp513 +Rp514 +aa(lp515 +g2 +(g3 +tp516 +Rp517 +ag2 +(S'0.502' +p518 +tp519 +Rp520 +ag2 +(g264 +tp521 +Rp522 +aa(lp523 +g2 +(g3 +tp524 +Rp525 +ag2 +(S'0.518' +p526 +tp527 +Rp528 +ag2 +(g264 +tp529 +Rp530 +aa(lp531 +g2 +(g3 +tp532 +Rp533 +ag2 +(S'0.533' +p534 +tp535 +Rp536 +ag2 +(g264 +tp537 +Rp538 +aa(lp539 +g2 +(g3 +tp540 +Rp541 +ag2 +(S'0.549' +p542 +tp543 +Rp544 +ag2 +(g264 +tp545 +Rp546 +aa(lp547 +g2 +(g3 +tp548 +Rp549 +ag2 +(S'0.565' +p550 +tp551 +Rp552 +ag2 +(g264 +tp553 +Rp554 +aa(lp555 +g2 +(g3 +tp556 +Rp557 +ag2 +(S'0.580' +p558 +tp559 +Rp560 +ag2 +(g264 +tp561 +Rp562 +aa(lp563 +g2 +(g3 +tp564 +Rp565 +ag2 +(S'0.596' +p566 +tp567 +Rp568 +ag2 +(g264 +tp569 +Rp570 +aa(lp571 +g2 +(g3 +tp572 +Rp573 +ag2 +(S'0.612' +p574 +tp575 +Rp576 +ag2 +(g264 +tp577 +Rp578 +aa(lp579 +g2 +(g3 +tp580 +Rp581 +ag2 +(S'0.627' +p582 +tp583 +Rp584 +ag2 +(g264 +tp585 +Rp586 +aa(lp587 +g2 +(g3 +tp588 +Rp589 +ag2 +(S'0.643' +p590 +tp591 +Rp592 +ag2 +(g264 +tp593 +Rp594 +aa(lp595 +g2 +(g3 +tp596 +Rp597 +ag2 +(S'0.659' +p598 +tp599 +Rp600 +ag2 +(g264 +tp601 +Rp602 +aa(lp603 +g2 +(g3 +tp604 +Rp605 +ag2 +(S'0.675' +p606 +tp607 +Rp608 +ag2 +(g264 +tp609 +Rp610 +aa(lp611 +g2 +(g3 +tp612 +Rp613 +ag2 +(S'0.690' +p614 +tp615 +Rp616 +ag2 +(g264 +tp617 +Rp618 +aa(lp619 +g2 +(g3 +tp620 +Rp621 +ag2 +(S'0.706' +p622 +tp623 +Rp624 +ag2 +(g264 +tp625 +Rp626 +aa(lp627 +g2 +(g3 +tp628 +Rp629 +ag2 +(S'0.722' +p630 +tp631 +Rp632 +ag2 +(g264 +tp633 +Rp634 +aa(lp635 +g2 +(g3 +tp636 +Rp637 +ag2 +(S'0.737' +p638 +tp639 +Rp640 +ag2 +(g264 +tp641 +Rp642 +aa(lp643 +g2 +(g3 +tp644 +Rp645 +ag2 +(S'0.753' +p646 +tp647 +Rp648 +ag2 +(g264 +tp649 +Rp650 +aa(lp651 +g2 +(g3 +tp652 +Rp653 +ag2 +(S'0.769' +p654 +tp655 +Rp656 +ag2 +(g264 +tp657 +Rp658 +aa(lp659 +g2 +(g3 +tp660 +Rp661 +ag2 +(S'0.784' +p662 +tp663 +Rp664 +ag2 +(g264 +tp665 +Rp666 +aa(lp667 +g2 +(g3 +tp668 +Rp669 +ag2 +(S'0.8' +p670 +tp671 +Rp672 +ag2 +(g264 +tp673 +Rp674 +aa(lp675 +g2 +(g3 +tp676 +Rp677 +ag2 +(S'0.816' +p678 +tp679 +Rp680 +ag2 +(g264 +tp681 +Rp682 +aa(lp683 +g2 +(g3 +tp684 +Rp685 +ag2 +(S'0.831' +p686 +tp687 +Rp688 +ag2 +(g264 +tp689 +Rp690 +aa(lp691 +g2 +(g3 +tp692 +Rp693 +ag2 +(S'0.847' +p694 +tp695 +Rp696 +ag2 +(g264 +tp697 +Rp698 +aa(lp699 +g2 +(g3 +tp700 +Rp701 +ag2 +(S'0.863' +p702 +tp703 +Rp704 +ag2 +(g264 +tp705 +Rp706 +aa(lp707 +g2 +(g3 +tp708 +Rp709 +ag2 +(S'0.878' +p710 +tp711 +Rp712 +ag2 +(g264 +tp713 +Rp714 +aa(lp715 +g2 +(g3 +tp716 +Rp717 +ag2 +(S'0.894' +p718 +tp719 +Rp720 +ag2 +(g264 +tp721 +Rp722 +aa(lp723 +g2 +(g3 +tp724 +Rp725 +ag2 +(S'0.910' +p726 +tp727 +Rp728 +ag2 +(g264 +tp729 +Rp730 +aa(lp731 +g2 +(g3 +tp732 +Rp733 +ag2 +(S'0.925' +p734 +tp735 +Rp736 +ag2 +(g264 +tp737 +Rp738 +aa(lp739 +g2 +(g3 +tp740 +Rp741 +ag2 +(S'0.941' +p742 +tp743 +Rp744 +ag2 +(g264 +tp745 +Rp746 +aa(lp747 +g2 +(g3 +tp748 +Rp749 +ag2 +(S'0.957' +p750 +tp751 +Rp752 +ag2 +(g264 +tp753 +Rp754 +aa(lp755 +g2 +(g3 +tp756 +Rp757 +ag2 +(S'0.973' +p758 +tp759 +Rp760 +ag2 +(g264 +tp761 +Rp762 +aa(lp763 +g2 +(g3 +tp764 +Rp765 +ag2 +(S'0.988' +p766 +tp767 +Rp768 +ag2 +(g264 +tp769 +Rp770 +aa(lp771 +g2 +(g3 +tp772 +Rp773 +ag2 +(g264 +tp774 +Rp775 +ag2 +(g264 +tp776 +Rp777 +aa(lp778 +g2 +(S'0.0157' +p779 +tp780 +Rp781 +ag2 +(g264 +tp782 +Rp783 +ag2 +(S'0.984' +p784 +tp785 +Rp786 +aa(lp787 +g2 +(S'0.0314' +p788 +tp789 +Rp790 +ag2 +(g264 +tp791 +Rp792 +ag2 +(S'0.969' +p793 +tp794 +Rp795 +aa(lp796 +g2 +(S'0.0471' +p797 +tp798 +Rp799 +ag2 +(g264 +tp800 +Rp801 +ag2 +(S'0.953' +p802 +tp803 +Rp804 +aa(lp805 +g2 +(S'0.0627' +p806 +tp807 +Rp808 +ag2 +(g264 +tp809 +Rp810 +ag2 +(S'0.937' +p811 +tp812 +Rp813 +aa(lp814 +g2 +(S'0.0784' +p815 +tp816 +Rp817 +ag2 +(g264 +tp818 +Rp819 +ag2 +(S'0.922' +p820 +tp821 +Rp822 +aa(lp823 +g2 +(S'0.0941' +p824 +tp825 +Rp826 +ag2 +(g264 +tp827 +Rp828 +ag2 +(S'0.906' +p829 +tp830 +Rp831 +aa(lp832 +g2 +(S'0.110' +p833 +tp834 +Rp835 +ag2 +(g264 +tp836 +Rp837 +ag2 +(S'0.890' +p838 +tp839 +Rp840 +aa(lp841 +g2 +(S'0.125' +p842 +tp843 +Rp844 +ag2 +(g264 +tp845 +Rp846 +ag2 +(S'0.875' +p847 +tp848 +Rp849 +aa(lp850 +g2 +(S'0.141' +p851 +tp852 +Rp853 +ag2 +(g264 +tp854 +Rp855 +ag2 +(S'0.859' +p856 +tp857 +Rp858 +aa(lp859 +g2 +(S'0.157' +p860 +tp861 +Rp862 +ag2 +(g264 +tp863 +Rp864 +ag2 +(S'0.843' +p865 +tp866 +Rp867 +aa(lp868 +g2 +(S'0.173' +p869 +tp870 +Rp871 +ag2 +(g264 +tp872 +Rp873 +ag2 +(S'0.827' +p874 +tp875 +Rp876 +aa(lp877 +g2 +(S'0.188' +p878 +tp879 +Rp880 +ag2 +(g264 +tp881 +Rp882 +ag2 +(S'0.812' +p883 +tp884 +Rp885 +aa(lp886 +g2 +(S'0.204' +p887 +tp888 +Rp889 +ag2 +(g264 +tp890 +Rp891 +ag2 +(S'0.796' +p892 +tp893 +Rp894 +aa(lp895 +g2 +(S'0.220' +p896 +tp897 +Rp898 +ag2 +(g264 +tp899 +Rp900 +ag2 +(S'0.780' +p901 +tp902 +Rp903 +aa(lp904 +g2 +(S'0.235' +p905 +tp906 +Rp907 +ag2 +(g264 +tp908 +Rp909 +ag2 +(S'0.765' +p910 +tp911 +Rp912 +aa(lp913 +g2 +(S'0.251' +p914 +tp915 +Rp916 +ag2 +(g264 +tp917 +Rp918 +ag2 +(S'0.749' +p919 +tp920 +Rp921 +aa(lp922 +g2 +(S'0.267' +p923 +tp924 +Rp925 +ag2 +(g264 +tp926 +Rp927 +ag2 +(S'0.733' +p928 +tp929 +Rp930 +aa(lp931 +g2 +(S'0.282' +p932 +tp933 +Rp934 +ag2 +(g264 +tp935 +Rp936 +ag2 +(S'0.718' +p937 +tp938 +Rp939 +aa(lp940 +g2 +(S'0.298' +p941 +tp942 +Rp943 +ag2 +(g264 +tp944 +Rp945 +ag2 +(S'0.702' +p946 +tp947 +Rp948 +aa(lp949 +g2 +(S'0.314' +p950 +tp951 +Rp952 +ag2 +(g264 +tp953 +Rp954 +ag2 +(S'0.686' +p955 +tp956 +Rp957 +aa(lp958 +g2 +(S'0.329' +p959 +tp960 +Rp961 +ag2 +(g264 +tp962 +Rp963 +ag2 +(S'0.671' +p964 +tp965 +Rp966 +aa(lp967 +g2 +(S'0.345' +p968 +tp969 +Rp970 +ag2 +(g264 +tp971 +Rp972 +ag2 +(S'0.655' +p973 +tp974 +Rp975 +aa(lp976 +g2 +(S'0.361' +p977 +tp978 +Rp979 +ag2 +(g264 +tp980 +Rp981 +ag2 +(S'0.639' +p982 +tp983 +Rp984 +aa(lp985 +g2 +(S'0.376' +p986 +tp987 +Rp988 +ag2 +(g264 +tp989 +Rp990 +ag2 +(S'0.624' +p991 +tp992 +Rp993 +aa(lp994 +g2 +(S'0.392' +p995 +tp996 +Rp997 +ag2 +(g264 +tp998 +Rp999 +ag2 +(S'0.608' +p1000 +tp1001 +Rp1002 +aa(lp1003 +g2 +(S'0.408' +p1004 +tp1005 +Rp1006 +ag2 +(g264 +tp1007 +Rp1008 +ag2 +(S'0.592' +p1009 +tp1010 +Rp1011 +aa(lp1012 +g2 +(S'0.424' +p1013 +tp1014 +Rp1015 +ag2 +(g264 +tp1016 +Rp1017 +ag2 +(S'0.576' +p1018 +tp1019 +Rp1020 +aa(lp1021 +g2 +(S'0.439' +p1022 +tp1023 +Rp1024 +ag2 +(g264 +tp1025 +Rp1026 +ag2 +(S'0.561' +p1027 +tp1028 +Rp1029 +aa(lp1030 +g2 +(S'0.455' +p1031 +tp1032 +Rp1033 +ag2 +(g264 +tp1034 +Rp1035 +ag2 +(S'0.545' +p1036 +tp1037 +Rp1038 +aa(lp1039 +g2 +(S'0.471' +p1040 +tp1041 +Rp1042 +ag2 +(g264 +tp1043 +Rp1044 +ag2 +(S'0.529' +p1045 +tp1046 +Rp1047 +aa(lp1048 +g2 +(S'0.486' +p1049 +tp1050 +Rp1051 +ag2 +(g264 +tp1052 +Rp1053 +ag2 +(S'0.514' +p1054 +tp1055 +Rp1056 +aa(lp1057 +g2 +(S'0.502' +p1058 +tp1059 +Rp1060 +ag2 +(g264 +tp1061 +Rp1062 +ag2 +(S'0.498' +p1063 +tp1064 +Rp1065 +aa(lp1066 +g2 +(S'0.518' +p1067 +tp1068 +Rp1069 +ag2 +(g264 +tp1070 +Rp1071 +ag2 +(S'0.482' +p1072 +tp1073 +Rp1074 +aa(lp1075 +g2 +(S'0.533' +p1076 +tp1077 +Rp1078 +ag2 +(g264 +tp1079 +Rp1080 +ag2 +(S'0.467' +p1081 +tp1082 +Rp1083 +aa(lp1084 +g2 +(S'0.549' +p1085 +tp1086 +Rp1087 +ag2 +(g264 +tp1088 +Rp1089 +ag2 +(S'0.451' +p1090 +tp1091 +Rp1092 +aa(lp1093 +g2 +(S'0.565' +p1094 +tp1095 +Rp1096 +ag2 +(g264 +tp1097 +Rp1098 +ag2 +(S'0.435' +p1099 +tp1100 +Rp1101 +aa(lp1102 +g2 +(S'0.580' +p1103 +tp1104 +Rp1105 +ag2 +(g264 +tp1106 +Rp1107 +ag2 +(S'0.420' +p1108 +tp1109 +Rp1110 +aa(lp1111 +g2 +(S'0.596' +p1112 +tp1113 +Rp1114 +ag2 +(g264 +tp1115 +Rp1116 +ag2 +(S'0.404' +p1117 +tp1118 +Rp1119 +aa(lp1120 +g2 +(S'0.612' +p1121 +tp1122 +Rp1123 +ag2 +(g264 +tp1124 +Rp1125 +ag2 +(S'0.388' +p1126 +tp1127 +Rp1128 +aa(lp1129 +g2 +(S'0.627' +p1130 +tp1131 +Rp1132 +ag2 +(g264 +tp1133 +Rp1134 +ag2 +(S'0.373' +p1135 +tp1136 +Rp1137 +aa(lp1138 +g2 +(S'0.643' +p1139 +tp1140 +Rp1141 +ag2 +(g264 +tp1142 +Rp1143 +ag2 +(S'0.357' +p1144 +tp1145 +Rp1146 +aa(lp1147 +g2 +(S'0.659' +p1148 +tp1149 +Rp1150 +ag2 +(g264 +tp1151 +Rp1152 +ag2 +(S'0.341' +p1153 +tp1154 +Rp1155 +aa(lp1156 +g2 +(S'0.675' +p1157 +tp1158 +Rp1159 +ag2 +(g264 +tp1160 +Rp1161 +ag2 +(S'0.325' +p1162 +tp1163 +Rp1164 +aa(lp1165 +g2 +(S'0.690' +p1166 +tp1167 +Rp1168 +ag2 +(g264 +tp1169 +Rp1170 +ag2 +(S'0.310' +p1171 +tp1172 +Rp1173 +aa(lp1174 +g2 +(S'0.706' +p1175 +tp1176 +Rp1177 +ag2 +(g264 +tp1178 +Rp1179 +ag2 +(S'0.294' +p1180 +tp1181 +Rp1182 +aa(lp1183 +g2 +(S'0.722' +p1184 +tp1185 +Rp1186 +ag2 +(g264 +tp1187 +Rp1188 +ag2 +(S'0.278' +p1189 +tp1190 +Rp1191 +aa(lp1192 +g2 +(S'0.737' +p1193 +tp1194 +Rp1195 +ag2 +(g264 +tp1196 +Rp1197 +ag2 +(S'0.263' +p1198 +tp1199 +Rp1200 +aa(lp1201 +g2 +(S'0.753' +p1202 +tp1203 +Rp1204 +ag2 +(g264 +tp1205 +Rp1206 +ag2 +(S'0.247' +p1207 +tp1208 +Rp1209 +aa(lp1210 +g2 +(S'0.769' +p1211 +tp1212 +Rp1213 +ag2 +(g264 +tp1214 +Rp1215 +ag2 +(S'0.231' +p1216 +tp1217 +Rp1218 +aa(lp1219 +g2 +(S'0.784' +p1220 +tp1221 +Rp1222 +ag2 +(g264 +tp1223 +Rp1224 +ag2 +(S'0.216' +p1225 +tp1226 +Rp1227 +aa(lp1228 +g2 +(S'0.8' +p1229 +tp1230 +Rp1231 +ag2 +(g264 +tp1232 +Rp1233 +ag2 +(S'0.2' +p1234 +tp1235 +Rp1236 +aa(lp1237 +g2 +(S'0.816' +p1238 +tp1239 +Rp1240 +ag2 +(g264 +tp1241 +Rp1242 +ag2 +(S'0.184' +p1243 +tp1244 +Rp1245 +aa(lp1246 +g2 +(S'0.831' +p1247 +tp1248 +Rp1249 +ag2 +(g264 +tp1250 +Rp1251 +ag2 +(S'0.169' +p1252 +tp1253 +Rp1254 +aa(lp1255 +g2 +(S'0.847' +p1256 +tp1257 +Rp1258 +ag2 +(g264 +tp1259 +Rp1260 +ag2 +(S'0.153' +p1261 +tp1262 +Rp1263 +aa(lp1264 +g2 +(S'0.863' +p1265 +tp1266 +Rp1267 +ag2 +(g264 +tp1268 +Rp1269 +ag2 +(S'0.137' +p1270 +tp1271 +Rp1272 +aa(lp1273 +g2 +(S'0.878' +p1274 +tp1275 +Rp1276 +ag2 +(g264 +tp1277 +Rp1278 +ag2 +(S'0.122' +p1279 +tp1280 +Rp1281 +aa(lp1282 +g2 +(S'0.894' +p1283 +tp1284 +Rp1285 +ag2 +(g264 +tp1286 +Rp1287 +ag2 +(S'0.106' +p1288 +tp1289 +Rp1290 +aa(lp1291 +g2 +(S'0.910' +p1292 +tp1293 +Rp1294 +ag2 +(g264 +tp1295 +Rp1296 +ag2 +(S'0.0902' +p1297 +tp1298 +Rp1299 +aa(lp1300 +g2 +(S'0.925' +p1301 +tp1302 +Rp1303 +ag2 +(g264 +tp1304 +Rp1305 +ag2 +(S'0.0745' +p1306 +tp1307 +Rp1308 +aa(lp1309 +g2 +(S'0.941' +p1310 +tp1311 +Rp1312 +ag2 +(g264 +tp1313 +Rp1314 +ag2 +(S'0.0588' +p1315 +tp1316 +Rp1317 +aa(lp1318 +g2 +(S'0.957' +p1319 +tp1320 +Rp1321 +ag2 +(g264 +tp1322 +Rp1323 +ag2 +(S'0.0431' +p1324 +tp1325 +Rp1326 +aa(lp1327 +g2 +(S'0.973' +p1328 +tp1329 +Rp1330 +ag2 +(g264 +tp1331 +Rp1332 +ag2 +(S'0.0275' +p1333 +tp1334 +Rp1335 +aa(lp1336 +g2 +(S'0.988' +p1337 +tp1338 +Rp1339 +ag2 +(g264 +tp1340 +Rp1341 +ag2 +(S'0.0118' +p1342 +tp1343 +Rp1344 +aa(lp1345 +g2 +(g264 +tp1346 +Rp1347 +ag2 +(g264 +tp1348 +Rp1349 +ag2 +(g3 +tp1350 +Rp1351 +aa(lp1352 +g2 +(g264 +tp1353 +Rp1354 +ag2 +(S'0.984' +p1355 +tp1356 +Rp1357 +ag2 +(g3 +tp1358 +Rp1359 +aa(lp1360 +g2 +(g264 +tp1361 +Rp1362 +ag2 +(S'0.969' +p1363 +tp1364 +Rp1365 +ag2 +(g3 +tp1366 +Rp1367 +aa(lp1368 +g2 +(g264 +tp1369 +Rp1370 +ag2 +(S'0.953' +p1371 +tp1372 +Rp1373 +ag2 +(g3 +tp1374 +Rp1375 +aa(lp1376 +g2 +(g264 +tp1377 +Rp1378 +ag2 +(S'0.937' +p1379 +tp1380 +Rp1381 +ag2 +(g3 +tp1382 +Rp1383 +aa(lp1384 +g2 +(g264 +tp1385 +Rp1386 +ag2 +(S'0.922' +p1387 +tp1388 +Rp1389 +ag2 +(g3 +tp1390 +Rp1391 +aa(lp1392 +g2 +(g264 +tp1393 +Rp1394 +ag2 +(S'0.906' +p1395 +tp1396 +Rp1397 +ag2 +(g3 +tp1398 +Rp1399 +aa(lp1400 +g2 +(g264 +tp1401 +Rp1402 +ag2 +(S'0.890' +p1403 +tp1404 +Rp1405 +ag2 +(g3 +tp1406 +Rp1407 +aa(lp1408 +g2 +(g264 +tp1409 +Rp1410 +ag2 +(S'0.875' +p1411 +tp1412 +Rp1413 +ag2 +(g3 +tp1414 +Rp1415 +aa(lp1416 +g2 +(g264 +tp1417 +Rp1418 +ag2 +(S'0.859' +p1419 +tp1420 +Rp1421 +ag2 +(g3 +tp1422 +Rp1423 +aa(lp1424 +g2 +(g264 +tp1425 +Rp1426 +ag2 +(S'0.843' +p1427 +tp1428 +Rp1429 +ag2 +(g3 +tp1430 +Rp1431 +aa(lp1432 +g2 +(g264 +tp1433 +Rp1434 +ag2 +(S'0.827' +p1435 +tp1436 +Rp1437 +ag2 +(g3 +tp1438 +Rp1439 +aa(lp1440 +g2 +(g264 +tp1441 +Rp1442 +ag2 +(S'0.812' +p1443 +tp1444 +Rp1445 +ag2 +(g3 +tp1446 +Rp1447 +aa(lp1448 +g2 +(g264 +tp1449 +Rp1450 +ag2 +(S'0.796' +p1451 +tp1452 +Rp1453 +ag2 +(g3 +tp1454 +Rp1455 +aa(lp1456 +g2 +(g264 +tp1457 +Rp1458 +ag2 +(S'0.780' +p1459 +tp1460 +Rp1461 +ag2 +(g3 +tp1462 +Rp1463 +aa(lp1464 +g2 +(g264 +tp1465 +Rp1466 +ag2 +(S'0.765' +p1467 +tp1468 +Rp1469 +ag2 +(g3 +tp1470 +Rp1471 +aa(lp1472 +g2 +(g264 +tp1473 +Rp1474 +ag2 +(S'0.749' +p1475 +tp1476 +Rp1477 +ag2 +(g3 +tp1478 +Rp1479 +aa(lp1480 +g2 +(g264 +tp1481 +Rp1482 +ag2 +(S'0.733' +p1483 +tp1484 +Rp1485 +ag2 +(g3 +tp1486 +Rp1487 +aa(lp1488 +g2 +(g264 +tp1489 +Rp1490 +ag2 +(S'0.718' +p1491 +tp1492 +Rp1493 +ag2 +(g3 +tp1494 +Rp1495 +aa(lp1496 +g2 +(g264 +tp1497 +Rp1498 +ag2 +(S'0.702' +p1499 +tp1500 +Rp1501 +ag2 +(g3 +tp1502 +Rp1503 +aa(lp1504 +g2 +(g264 +tp1505 +Rp1506 +ag2 +(S'0.686' +p1507 +tp1508 +Rp1509 +ag2 +(g3 +tp1510 +Rp1511 +aa(lp1512 +g2 +(g264 +tp1513 +Rp1514 +ag2 +(S'0.671' +p1515 +tp1516 +Rp1517 +ag2 +(g3 +tp1518 +Rp1519 +aa(lp1520 +g2 +(g264 +tp1521 +Rp1522 +ag2 +(S'0.655' +p1523 +tp1524 +Rp1525 +ag2 +(g3 +tp1526 +Rp1527 +aa(lp1528 +g2 +(g264 +tp1529 +Rp1530 +ag2 +(S'0.639' +p1531 +tp1532 +Rp1533 +ag2 +(g3 +tp1534 +Rp1535 +aa(lp1536 +g2 +(g264 +tp1537 +Rp1538 +ag2 +(S'0.624' +p1539 +tp1540 +Rp1541 +ag2 +(g3 +tp1542 +Rp1543 +aa(lp1544 +g2 +(g264 +tp1545 +Rp1546 +ag2 +(S'0.608' +p1547 +tp1548 +Rp1549 +ag2 +(g3 +tp1550 +Rp1551 +aa(lp1552 +g2 +(g264 +tp1553 +Rp1554 +ag2 +(S'0.592' +p1555 +tp1556 +Rp1557 +ag2 +(g3 +tp1558 +Rp1559 +aa(lp1560 +g2 +(g264 +tp1561 +Rp1562 +ag2 +(S'0.576' +p1563 +tp1564 +Rp1565 +ag2 +(g3 +tp1566 +Rp1567 +aa(lp1568 +g2 +(g264 +tp1569 +Rp1570 +ag2 +(S'0.561' +p1571 +tp1572 +Rp1573 +ag2 +(g3 +tp1574 +Rp1575 +aa(lp1576 +g2 +(g264 +tp1577 +Rp1578 +ag2 +(S'0.545' +p1579 +tp1580 +Rp1581 +ag2 +(g3 +tp1582 +Rp1583 +aa(lp1584 +g2 +(g264 +tp1585 +Rp1586 +ag2 +(S'0.529' +p1587 +tp1588 +Rp1589 +ag2 +(g3 +tp1590 +Rp1591 +aa(lp1592 +g2 +(g264 +tp1593 +Rp1594 +ag2 +(S'0.514' +p1595 +tp1596 +Rp1597 +ag2 +(g3 +tp1598 +Rp1599 +aa(lp1600 +g2 +(g264 +tp1601 +Rp1602 +ag2 +(S'0.498' +p1603 +tp1604 +Rp1605 +ag2 +(g3 +tp1606 +Rp1607 +aa(lp1608 +g2 +(g264 +tp1609 +Rp1610 +ag2 +(S'0.482' +p1611 +tp1612 +Rp1613 +ag2 +(g3 +tp1614 +Rp1615 +aa(lp1616 +g2 +(g264 +tp1617 +Rp1618 +ag2 +(S'0.467' +p1619 +tp1620 +Rp1621 +ag2 +(g3 +tp1622 +Rp1623 +aa(lp1624 +g2 +(g264 +tp1625 +Rp1626 +ag2 +(S'0.451' +p1627 +tp1628 +Rp1629 +ag2 +(g3 +tp1630 +Rp1631 +aa(lp1632 +g2 +(g264 +tp1633 +Rp1634 +ag2 +(S'0.435' +p1635 +tp1636 +Rp1637 +ag2 +(g3 +tp1638 +Rp1639 +aa(lp1640 +g2 +(g264 +tp1641 +Rp1642 +ag2 +(S'0.420' +p1643 +tp1644 +Rp1645 +ag2 +(g3 +tp1646 +Rp1647 +aa(lp1648 +g2 +(g264 +tp1649 +Rp1650 +ag2 +(S'0.404' +p1651 +tp1652 +Rp1653 +ag2 +(g3 +tp1654 +Rp1655 +aa(lp1656 +g2 +(g264 +tp1657 +Rp1658 +ag2 +(S'0.388' +p1659 +tp1660 +Rp1661 +ag2 +(g3 +tp1662 +Rp1663 +aa(lp1664 +g2 +(g264 +tp1665 +Rp1666 +ag2 +(S'0.373' +p1667 +tp1668 +Rp1669 +ag2 +(g3 +tp1670 +Rp1671 +aa(lp1672 +g2 +(g264 +tp1673 +Rp1674 +ag2 +(S'0.357' +p1675 +tp1676 +Rp1677 +ag2 +(g3 +tp1678 +Rp1679 +aa(lp1680 +g2 +(g264 +tp1681 +Rp1682 +ag2 +(S'0.341' +p1683 +tp1684 +Rp1685 +ag2 +(g3 +tp1686 +Rp1687 +aa(lp1688 +g2 +(g264 +tp1689 +Rp1690 +ag2 +(S'0.325' +p1691 +tp1692 +Rp1693 +ag2 +(g3 +tp1694 +Rp1695 +aa(lp1696 +g2 +(g264 +tp1697 +Rp1698 +ag2 +(S'0.310' +p1699 +tp1700 +Rp1701 +ag2 +(g3 +tp1702 +Rp1703 +aa(lp1704 +g2 +(g264 +tp1705 +Rp1706 +ag2 +(S'0.294' +p1707 +tp1708 +Rp1709 +ag2 +(g3 +tp1710 +Rp1711 +aa(lp1712 +g2 +(g264 +tp1713 +Rp1714 +ag2 +(S'0.278' +p1715 +tp1716 +Rp1717 +ag2 +(g3 +tp1718 +Rp1719 +aa(lp1720 +g2 +(g264 +tp1721 +Rp1722 +ag2 +(S'0.263' +p1723 +tp1724 +Rp1725 +ag2 +(g3 +tp1726 +Rp1727 +aa(lp1728 +g2 +(g264 +tp1729 +Rp1730 +ag2 +(S'0.247' +p1731 +tp1732 +Rp1733 +ag2 +(g3 +tp1734 +Rp1735 +aa(lp1736 +g2 +(g264 +tp1737 +Rp1738 +ag2 +(S'0.231' +p1739 +tp1740 +Rp1741 +ag2 +(g3 +tp1742 +Rp1743 +aa(lp1744 +g2 +(g264 +tp1745 +Rp1746 +ag2 +(S'0.216' +p1747 +tp1748 +Rp1749 +ag2 +(g3 +tp1750 +Rp1751 +aa(lp1752 +g2 +(g264 +tp1753 +Rp1754 +ag2 +(S'0.2' +p1755 +tp1756 +Rp1757 +ag2 +(g3 +tp1758 +Rp1759 +aa(lp1760 +g2 +(g264 +tp1761 +Rp1762 +ag2 +(S'0.184' +p1763 +tp1764 +Rp1765 +ag2 +(g3 +tp1766 +Rp1767 +aa(lp1768 +g2 +(g264 +tp1769 +Rp1770 +ag2 +(S'0.169' +p1771 +tp1772 +Rp1773 +ag2 +(g3 +tp1774 +Rp1775 +aa(lp1776 +g2 +(g264 +tp1777 +Rp1778 +ag2 +(S'0.153' +p1779 +tp1780 +Rp1781 +ag2 +(g3 +tp1782 +Rp1783 +aa(lp1784 +g2 +(g264 +tp1785 +Rp1786 +ag2 +(S'0.137' +p1787 +tp1788 +Rp1789 +ag2 +(g3 +tp1790 +Rp1791 +aa(lp1792 +g2 +(g264 +tp1793 +Rp1794 +ag2 +(S'0.122' +p1795 +tp1796 +Rp1797 +ag2 +(g3 +tp1798 +Rp1799 +aa(lp1800 +g2 +(g264 +tp1801 +Rp1802 +ag2 +(S'0.106' +p1803 +tp1804 +Rp1805 +ag2 +(g3 +tp1806 +Rp1807 +aa(lp1808 +g2 +(g264 +tp1809 +Rp1810 +ag2 +(S'0.0902' +p1811 +tp1812 +Rp1813 +ag2 +(g3 +tp1814 +Rp1815 +aa(lp1816 +g2 +(g264 +tp1817 +Rp1818 +ag2 +(S'0.0745' +p1819 +tp1820 +Rp1821 +ag2 +(g3 +tp1822 +Rp1823 +aa(lp1824 +g2 +(g264 +tp1825 +Rp1826 +ag2 +(S'0.0588' +p1827 +tp1828 +Rp1829 +ag2 +(g3 +tp1830 +Rp1831 +aa(lp1832 +g2 +(g264 +tp1833 +Rp1834 +ag2 +(S'0.0431' +p1835 +tp1836 +Rp1837 +ag2 +(g3 +tp1838 +Rp1839 +aa(lp1840 +g2 +(g264 +tp1841 +Rp1842 +ag2 +(S'0.0275' +p1843 +tp1844 +Rp1845 +ag2 +(g3 +tp1846 +Rp1847 +aa(lp1848 +g2 +(g264 +tp1849 +Rp1850 +ag2 +(S'0.0118' +p1851 +tp1852 +Rp1853 +ag2 +(g3 +tp1854 +Rp1855 +aa(lp1856 +g2 +(g264 +tp1857 +Rp1858 +ag2 +(g3 +tp1859 +Rp1860 +ag2 +(g3 +tp1861 +Rp1862 +aa(lp1863 +g2 +(S'0.984' +p1864 +tp1865 +Rp1866 +ag2 +(g3 +tp1867 +Rp1868 +ag2 +(g3 +tp1869 +Rp1870 +aa(lp1871 +g2 +(S'0.969' +p1872 +tp1873 +Rp1874 +ag2 +(g3 +tp1875 +Rp1876 +ag2 +(g3 +tp1877 +Rp1878 +aa(lp1879 +g2 +(S'0.953' +p1880 +tp1881 +Rp1882 +ag2 +(g3 +tp1883 +Rp1884 +ag2 +(g3 +tp1885 +Rp1886 +aa(lp1887 +g2 +(S'0.937' +p1888 +tp1889 +Rp1890 +ag2 +(g3 +tp1891 +Rp1892 +ag2 +(g3 +tp1893 +Rp1894 +aa(lp1895 +g2 +(S'0.922' +p1896 +tp1897 +Rp1898 +ag2 +(g3 +tp1899 +Rp1900 +ag2 +(g3 +tp1901 +Rp1902 +aa(lp1903 +g2 +(S'0.906' +p1904 +tp1905 +Rp1906 +ag2 +(g3 +tp1907 +Rp1908 +ag2 +(g3 +tp1909 +Rp1910 +aa(lp1911 +g2 +(S'0.890' +p1912 +tp1913 +Rp1914 +ag2 +(g3 +tp1915 +Rp1916 +ag2 +(g3 +tp1917 +Rp1918 +aa(lp1919 +g2 +(S'0.875' +p1920 +tp1921 +Rp1922 +ag2 +(g3 +tp1923 +Rp1924 +ag2 +(g3 +tp1925 +Rp1926 +aa(lp1927 +g2 +(S'0.859' +p1928 +tp1929 +Rp1930 +ag2 +(g3 +tp1931 +Rp1932 +ag2 +(g3 +tp1933 +Rp1934 +aa(lp1935 +g2 +(S'0.843' +p1936 +tp1937 +Rp1938 +ag2 +(g3 +tp1939 +Rp1940 +ag2 +(g3 +tp1941 +Rp1942 +aa(lp1943 +g2 +(S'0.827' +p1944 +tp1945 +Rp1946 +ag2 +(g3 +tp1947 +Rp1948 +ag2 +(g3 +tp1949 +Rp1950 +aa(lp1951 +g2 +(S'0.812' +p1952 +tp1953 +Rp1954 +ag2 +(g3 +tp1955 +Rp1956 +ag2 +(g3 +tp1957 +Rp1958 +aa(lp1959 +g2 +(S'0.796' +p1960 +tp1961 +Rp1962 +ag2 +(g3 +tp1963 +Rp1964 +ag2 +(g3 +tp1965 +Rp1966 +aa(lp1967 +g2 +(S'0.780' +p1968 +tp1969 +Rp1970 +ag2 +(g3 +tp1971 +Rp1972 +ag2 +(g3 +tp1973 +Rp1974 +aa(lp1975 +g2 +(S'0.765' +p1976 +tp1977 +Rp1978 +ag2 +(g3 +tp1979 +Rp1980 +ag2 +(g3 +tp1981 +Rp1982 +aa(lp1983 +g2 +(S'0.749' +p1984 +tp1985 +Rp1986 +ag2 +(g3 +tp1987 +Rp1988 +ag2 +(g3 +tp1989 +Rp1990 +aa(lp1991 +g2 +(S'0.733' +p1992 +tp1993 +Rp1994 +ag2 +(g3 +tp1995 +Rp1996 +ag2 +(g3 +tp1997 +Rp1998 +aa(lp1999 +g2 +(S'0.718' +p2000 +tp2001 +Rp2002 +ag2 +(g3 +tp2003 +Rp2004 +ag2 +(g3 +tp2005 +Rp2006 +aa(lp2007 +g2 +(S'0.702' +p2008 +tp2009 +Rp2010 +ag2 +(g3 +tp2011 +Rp2012 +ag2 +(g3 +tp2013 +Rp2014 +aa(lp2015 +g2 +(S'0.686' +p2016 +tp2017 +Rp2018 +ag2 +(g3 +tp2019 +Rp2020 +ag2 +(g3 +tp2021 +Rp2022 +aa(lp2023 +g2 +(S'0.671' +p2024 +tp2025 +Rp2026 +ag2 +(g3 +tp2027 +Rp2028 +ag2 +(g3 +tp2029 +Rp2030 +aa(lp2031 +g2 +(S'0.655' +p2032 +tp2033 +Rp2034 +ag2 +(g3 +tp2035 +Rp2036 +ag2 +(g3 +tp2037 +Rp2038 +aa(lp2039 +g2 +(S'0.639' +p2040 +tp2041 +Rp2042 +ag2 +(g3 +tp2043 +Rp2044 +ag2 +(g3 +tp2045 +Rp2046 +aa(lp2047 +g2 +(S'0.624' +p2048 +tp2049 +Rp2050 +ag2 +(g3 +tp2051 +Rp2052 +ag2 +(g3 +tp2053 +Rp2054 +aa(lp2055 +g2 +(S'0.608' +p2056 +tp2057 +Rp2058 +ag2 +(g3 +tp2059 +Rp2060 +ag2 +(g3 +tp2061 +Rp2062 +aa(lp2063 +g2 +(S'0.592' +p2064 +tp2065 +Rp2066 +ag2 +(g3 +tp2067 +Rp2068 +ag2 +(g3 +tp2069 +Rp2070 +aa(lp2071 +g2 +(S'0.576' +p2072 +tp2073 +Rp2074 +ag2 +(g3 +tp2075 +Rp2076 +ag2 +(g3 +tp2077 +Rp2078 +aa(lp2079 +g2 +(S'0.561' +p2080 +tp2081 +Rp2082 +ag2 +(g3 +tp2083 +Rp2084 +ag2 +(g3 +tp2085 +Rp2086 +aa(lp2087 +g2 +(S'0.545' +p2088 +tp2089 +Rp2090 +ag2 +(g3 +tp2091 +Rp2092 +ag2 +(g3 +tp2093 +Rp2094 +aa(lp2095 +g2 +(S'0.529' +p2096 +tp2097 +Rp2098 +ag2 +(g3 +tp2099 +Rp2100 +ag2 +(g3 +tp2101 +Rp2102 +aa(lp2103 +g2 +(S'0.514' +p2104 +tp2105 +Rp2106 +ag2 +(g3 +tp2107 +Rp2108 +ag2 +(g3 +tp2109 +Rp2110 +aa. \ No newline at end of file diff --git a/moose-gui/colormaps/rainbow2.pkl b/moose-gui/colormaps/rainbow2.pkl new file mode 100644 index 0000000000000000000000000000000000000000..8097c29c7e173bd42aaec157acaf806579f61af2 --- /dev/null +++ b/moose-gui/colormaps/rainbow2.pkl @@ -0,0 +1,514 @@ +((I248 +I0 +I255 +tp0 +(I240 +I0 +I255 +tp1 +(I232 +I0 +I255 +tp2 +(I224 +I0 +I255 +tp3 +(I216 +I0 +I255 +tp4 +(I208 +I0 +I255 +tp5 +(I200 +I0 +I255 +tp6 +(I192 +I0 +I255 +tp7 +(I184 +I0 +I255 +tp8 +(I176 +I0 +I255 +tp9 +(I168 +I0 +I255 +tp10 +(I160 +I0 +I255 +tp11 +(I152 +I0 +I255 +tp12 +(I144 +I0 +I255 +tp13 +(I136 +I0 +I255 +tp14 +(I128 +I0 +I255 +tp15 +(I120 +I0 +I255 +tp16 +(I112 +I0 +I255 +tp17 +(I104 +I0 +I255 +tp18 +(I96 +I0 +I255 +tp19 +(I88 +I0 +I255 +tp20 +(I80 +I0 +I255 +tp21 +(I72 +I0 +I255 +tp22 +(I64 +I0 +I255 +tp23 +(I56 +I0 +I255 +tp24 +(I48 +I0 +I255 +tp25 +(I40 +I0 +I255 +tp26 +(I32 +I0 +I255 +tp27 +(I24 +I0 +I255 +tp28 +(I16 +I0 +I255 +tp29 +(I8 +I0 +I255 +tp30 +(I0 +I0 +I255 +tp31 +(I0 +I8 +I248 +tp32 +(I0 +I16 +I240 +tp33 +(I0 +I24 +I232 +tp34 +(I0 +I32 +I224 +tp35 +(I0 +I40 +I216 +tp36 +(I0 +I48 +I208 +tp37 +(I0 +I56 +I200 +tp38 +(I0 +I64 +I192 +tp39 +(I0 +I72 +I184 +tp40 +(I0 +I80 +I176 +tp41 +(I0 +I88 +I168 +tp42 +(I0 +I96 +I160 +tp43 +(I0 +I104 +I152 +tp44 +(I0 +I112 +I144 +tp45 +(I0 +I120 +I136 +tp46 +(I0 +I128 +I128 +tp47 +(I0 +I136 +I120 +tp48 +(I0 +I144 +I112 +tp49 +(I0 +I152 +I104 +tp50 +(I0 +I160 +I96 +tp51 +(I0 +I168 +I88 +tp52 +(I0 +I176 +I80 +tp53 +(I0 +I184 +I72 +tp54 +(I0 +I192 +I64 +tp55 +(I0 +I200 +I56 +tp56 +(I0 +I208 +I48 +tp57 +(I0 +I216 +I40 +tp58 +(I0 +I224 +I32 +tp59 +(I0 +I232 +I24 +tp60 +(I0 +I240 +I16 +tp61 +(I0 +I248 +I8 +tp62 +(I0 +I255 +I0 +tp63 +(I8 +I255 +I0 +tp64 +(I16 +I255 +I0 +tp65 +(I24 +I255 +I0 +tp66 +(I32 +I255 +I0 +tp67 +(I40 +I255 +I0 +tp68 +(I48 +I255 +I0 +tp69 +(I56 +I255 +I0 +tp70 +(I64 +I255 +I0 +tp71 +(I72 +I255 +I0 +tp72 +(I80 +I255 +I0 +tp73 +(I88 +I255 +I0 +tp74 +(I96 +I255 +I0 +tp75 +(I104 +I255 +I0 +tp76 +(I112 +I255 +I0 +tp77 +(I120 +I255 +I0 +tp78 +(I128 +I255 +I0 +tp79 +(I136 +I255 +I0 +tp80 +(I144 +I255 +I0 +tp81 +(I152 +I255 +I0 +tp82 +(I160 +I255 +I0 +tp83 +(I168 +I255 +I0 +tp84 +(I176 +I255 +I0 +tp85 +(I184 +I255 +I0 +tp86 +(I192 +I255 +I0 +tp87 +(I200 +I255 +I0 +tp88 +(I208 +I255 +I0 +tp89 +(I216 +I255 +I0 +tp90 +(I224 +I255 +I0 +tp91 +(I232 +I255 +I0 +tp92 +(I240 +I255 +I0 +tp93 +(I248 +I255 +I0 +tp94 +(I255 +I255 +I0 +tp95 +(I255 +I248 +I0 +tp96 +(I255 +I240 +I0 +tp97 +(I255 +I232 +I0 +tp98 +(I255 +I224 +I0 +tp99 +(I255 +I216 +I0 +tp100 +(I255 +I208 +I0 +tp101 +(I255 +I200 +I0 +tp102 +(I255 +I192 +I0 +tp103 +(I255 +I184 +I0 +tp104 +(I255 +I176 +I0 +tp105 +(I255 +I168 +I0 +tp106 +(I255 +I160 +I0 +tp107 +(I255 +I152 +I0 +tp108 +(I255 +I144 +I0 +tp109 +(I255 +I136 +I0 +tp110 +(I255 +I128 +I0 +tp111 +(I255 +I120 +I0 +tp112 +(I255 +I112 +I0 +tp113 +(I255 +I104 +I0 +tp114 +(I255 +I96 +I0 +tp115 +(I255 +I88 +I0 +tp116 +(I255 +I80 +I0 +tp117 +(I255 +I72 +I0 +tp118 +(I255 +I64 +I0 +tp119 +(I255 +I56 +I0 +tp120 +(I255 +I48 +I0 +tp121 +(I255 +I40 +I0 +tp122 +(I255 +I32 +I0 +tp123 +(I255 +I24 +I0 +tp124 +(I255 +I16 +I0 +tp125 +(I255 +I8 +I0 +tp126 +(I255 +I0 +I0 +tp127 +tp128 +. \ No newline at end of file diff --git a/moose-gui/colormaps/redhot b/moose-gui/colormaps/redhot new file mode 100644 index 0000000000000000000000000000000000000000..5adc2b6816af5b34b1f67362c13582fbd69c8528 --- /dev/null +++ b/moose-gui/colormaps/redhot @@ -0,0 +1,1882 @@ +(lp0 +(lp1 +cdecimal +Decimal +p2 +(S'0' +p3 +tp4 +Rp5 +ag2 +(g3 +tp6 +Rp7 +ag2 +(g3 +tp8 +Rp9 +aa(lp10 +g2 +(S'0.0311' +p11 +tp12 +Rp13 +ag2 +(g3 +tp14 +Rp15 +ag2 +(S'0.0960' +p16 +tp17 +Rp18 +aa(lp19 +g2 +(S'0.0623' +p20 +tp21 +Rp22 +ag2 +(g3 +tp23 +Rp24 +ag2 +(S'0.192' +p25 +tp26 +Rp27 +aa(lp28 +g2 +(S'0.0934' +p29 +tp30 +Rp31 +ag2 +(g3 +tp32 +Rp33 +ag2 +(S'0.288' +p34 +tp35 +Rp36 +aa(lp37 +g2 +(S'0.125' +p38 +tp39 +Rp40 +ag2 +(g3 +tp41 +Rp42 +ag2 +(S'0.384' +p43 +tp44 +Rp45 +aa(lp46 +g2 +(S'0.156' +p47 +tp48 +Rp49 +ag2 +(g3 +tp50 +Rp51 +ag2 +(S'0.480' +p52 +tp53 +Rp54 +aa(lp55 +g2 +(S'0.187' +p56 +tp57 +Rp58 +ag2 +(g3 +tp59 +Rp60 +ag2 +(S'0.576' +p61 +tp62 +Rp63 +aa(lp64 +g2 +(S'0.156' +p65 +tp66 +Rp67 +ag2 +(g3 +tp68 +Rp69 +ag2 +(S'0.582' +p70 +tp71 +Rp72 +aa(lp73 +g2 +(S'0.125' +p74 +tp75 +Rp76 +ag2 +(g3 +tp77 +Rp78 +ag2 +(S'0.589' +p79 +tp80 +Rp81 +aa(lp82 +g2 +(S'0.0934' +p83 +tp84 +Rp85 +ag2 +(g3 +tp86 +Rp87 +ag2 +(S'0.595' +p88 +tp89 +Rp90 +aa(lp91 +g2 +(S'0.0623' +p92 +tp93 +Rp94 +ag2 +(g3 +tp95 +Rp96 +ag2 +(S'0.602' +p97 +tp98 +Rp99 +aa(lp100 +g2 +(S'0.0311' +p101 +tp102 +Rp103 +ag2 +(g3 +tp104 +Rp105 +ag2 +(S'0.608' +p106 +tp107 +Rp108 +aa(lp109 +g2 +(g3 +tp110 +Rp111 +ag2 +(g3 +tp112 +Rp113 +ag2 +(S'0.615' +p114 +tp115 +Rp116 +aa(lp117 +g2 +(g3 +tp118 +Rp119 +ag2 +(g3 +tp120 +Rp121 +ag2 +(S'0.647' +p122 +tp123 +Rp124 +aa(lp125 +g2 +(g3 +tp126 +Rp127 +ag2 +(g3 +tp128 +Rp129 +ag2 +(S'0.680' +p130 +tp131 +Rp132 +aa(lp133 +g2 +(g3 +tp134 +Rp135 +ag2 +(g3 +tp136 +Rp137 +ag2 +(S'0.712' +p138 +tp139 +Rp140 +aa(lp141 +g2 +(g3 +tp142 +Rp143 +ag2 +(g3 +tp144 +Rp145 +ag2 +(S'0.744' +p146 +tp147 +Rp148 +aa(lp149 +g2 +(g3 +tp150 +Rp151 +ag2 +(g3 +tp152 +Rp153 +ag2 +(S'0.777' +p154 +tp155 +Rp156 +aa(lp157 +g2 +(g3 +tp158 +Rp159 +ag2 +(g3 +tp160 +Rp161 +ag2 +(S'0.809' +p162 +tp163 +Rp164 +aa(lp165 +g2 +(g3 +tp166 +Rp167 +ag2 +(g3 +tp168 +Rp169 +ag2 +(S'0.831' +p170 +tp171 +Rp172 +aa(lp173 +g2 +(g3 +tp174 +Rp175 +ag2 +(g3 +tp176 +Rp177 +ag2 +(S'0.852' +p178 +tp179 +Rp180 +aa(lp181 +g2 +(g3 +tp182 +Rp183 +ag2 +(g3 +tp184 +Rp185 +ag2 +(S'0.874' +p186 +tp187 +Rp188 +aa(lp189 +g2 +(g3 +tp190 +Rp191 +ag2 +(g3 +tp192 +Rp193 +ag2 +(S'0.895' +p194 +tp195 +Rp196 +aa(lp197 +g2 +(g3 +tp198 +Rp199 +ag2 +(g3 +tp200 +Rp201 +ag2 +(S'0.916' +p202 +tp203 +Rp204 +aa(lp205 +g2 +(g3 +tp206 +Rp207 +ag2 +(g3 +tp208 +Rp209 +ag2 +(S'0.938' +p210 +tp211 +Rp212 +aa(lp213 +g2 +(g3 +tp214 +Rp215 +ag2 +(S'0.0636' +p216 +tp217 +Rp218 +ag2 +(S'0.938' +p219 +tp220 +Rp221 +aa(lp222 +g2 +(g3 +tp223 +Rp224 +ag2 +(S'0.127' +p225 +tp226 +Rp227 +ag2 +(S'0.938' +p228 +tp229 +Rp230 +aa(lp231 +g2 +(g3 +tp232 +Rp233 +ag2 +(S'0.191' +p234 +tp235 +Rp236 +ag2 +(S'0.938' +p237 +tp238 +Rp239 +aa(lp240 +g2 +(g3 +tp241 +Rp242 +ag2 +(S'0.254' +p243 +tp244 +Rp245 +ag2 +(S'0.938' +p246 +tp247 +Rp248 +aa(lp249 +g2 +(g3 +tp250 +Rp251 +ag2 +(S'0.318' +p252 +tp253 +Rp254 +ag2 +(S'0.938' +p255 +tp256 +Rp257 +aa(lp258 +g2 +(g3 +tp259 +Rp260 +ag2 +(S'0.381' +p261 +tp262 +Rp263 +ag2 +(S'0.938' +p264 +tp265 +Rp266 +aa(lp267 +g2 +(g3 +tp268 +Rp269 +ag2 +(S'0.403' +p270 +tp271 +Rp272 +ag2 +(S'0.910' +p273 +tp274 +Rp275 +aa(lp276 +g2 +(g3 +tp277 +Rp278 +ag2 +(S'0.425' +p279 +tp280 +Rp281 +ag2 +(S'0.882' +p282 +tp283 +Rp284 +aa(lp285 +g2 +(g3 +tp286 +Rp287 +ag2 +(S'0.447' +p288 +tp289 +Rp290 +ag2 +(S'0.854' +p291 +tp292 +Rp293 +aa(lp294 +g2 +(g3 +tp295 +Rp296 +ag2 +(S'0.470' +p297 +tp298 +Rp299 +ag2 +(S'0.826' +p300 +tp301 +Rp302 +aa(lp303 +g2 +(g3 +tp304 +Rp305 +ag2 +(S'0.492' +p306 +tp307 +Rp308 +ag2 +(S'0.798' +p309 +tp310 +Rp311 +aa(lp312 +g2 +(g3 +tp313 +Rp314 +ag2 +(S'0.514' +p315 +tp316 +Rp317 +ag2 +(S'0.770' +p318 +tp319 +Rp320 +aa(lp321 +g2 +(g3 +tp322 +Rp323 +ag2 +(S'0.514' +p324 +tp325 +Rp326 +ag2 +(S'0.744' +p327 +tp328 +Rp329 +aa(lp330 +g2 +(g3 +tp331 +Rp332 +ag2 +(S'0.515' +p333 +tp334 +Rp335 +ag2 +(S'0.719' +p336 +tp337 +Rp338 +aa(lp339 +g2 +(g3 +tp340 +Rp341 +ag2 +(S'0.516' +p342 +tp343 +Rp344 +ag2 +(S'0.693' +p345 +tp346 +Rp347 +aa(lp348 +g2 +(g3 +tp349 +Rp350 +ag2 +(S'0.516' +p351 +tp352 +Rp353 +ag2 +(S'0.667' +p354 +tp355 +Rp356 +aa(lp357 +g2 +(g3 +tp358 +Rp359 +ag2 +(S'0.517' +p360 +tp361 +Rp362 +ag2 +(S'0.641' +p363 +tp364 +Rp365 +aa(lp366 +g2 +(g3 +tp367 +Rp368 +ag2 +(S'0.518' +p369 +tp370 +Rp371 +ag2 +(S'0.615' +p372 +tp373 +Rp374 +aa(lp375 +g2 +(g3 +tp376 +Rp377 +ag2 +(S'0.534' +p378 +tp379 +Rp380 +ag2 +(S'0.595' +p381 +tp382 +Rp383 +aa(lp384 +g2 +(g3 +tp385 +Rp386 +ag2 +(S'0.550' +p387 +tp388 +Rp389 +ag2 +(S'0.576' +p390 +tp391 +Rp392 +aa(lp393 +g2 +(g3 +tp394 +Rp395 +ag2 +(S'0.566' +p396 +tp397 +Rp398 +ag2 +(S'0.556' +p399 +tp400 +Rp401 +aa(lp402 +g2 +(g3 +tp403 +Rp404 +ag2 +(S'0.582' +p405 +tp406 +Rp407 +ag2 +(S'0.537' +p408 +tp409 +Rp410 +aa(lp411 +g2 +(g3 +tp412 +Rp413 +ag2 +(S'0.599' +p414 +tp415 +Rp416 +ag2 +(S'0.518' +p417 +tp418 +Rp419 +aa(lp420 +g2 +(g3 +tp421 +Rp422 +ag2 +(S'0.615' +p423 +tp424 +Rp425 +ag2 +(S'0.498' +p426 +tp427 +Rp428 +aa(lp429 +g2 +(g3 +tp430 +Rp431 +ag2 +(S'0.608' +p432 +tp433 +Rp434 +ag2 +(S'0.415' +p435 +tp436 +Rp437 +aa(lp438 +g2 +(g3 +tp439 +Rp440 +ag2 +(S'0.602' +p441 +tp442 +Rp443 +ag2 +(S'0.332' +p444 +tp445 +Rp446 +aa(lp447 +g2 +(g3 +tp448 +Rp449 +ag2 +(S'0.595' +p450 +tp451 +Rp452 +ag2 +(S'0.249' +p453 +tp454 +Rp455 +aa(lp456 +g2 +(g3 +tp457 +Rp458 +ag2 +(S'0.589' +p459 +tp460 +Rp461 +ag2 +(S'0.166' +p462 +tp463 +Rp464 +aa(lp465 +g2 +(g3 +tp466 +Rp467 +ag2 +(S'0.582' +p468 +tp469 +Rp470 +ag2 +(S'0.0830' +p471 +tp472 +Rp473 +aa(lp474 +g2 +(g3 +tp475 +Rp476 +ag2 +(S'0.576' +p477 +tp478 +Rp479 +ag2 +(g3 +tp480 +Rp481 +aa(lp482 +g2 +(g3 +tp483 +Rp484 +ag2 +(S'0.608' +p485 +tp486 +Rp487 +ag2 +(g3 +tp488 +Rp489 +aa(lp490 +g2 +(g3 +tp491 +Rp492 +ag2 +(S'0.641' +p493 +tp494 +Rp495 +ag2 +(g3 +tp496 +Rp497 +aa(lp498 +g2 +(g3 +tp499 +Rp500 +ag2 +(S'0.673' +p501 +tp502 +Rp503 +ag2 +(g3 +tp504 +Rp505 +aa(lp506 +g2 +(g3 +tp507 +Rp508 +ag2 +(S'0.706' +p509 +tp510 +Rp511 +ag2 +(g3 +tp512 +Rp513 +aa(lp514 +g2 +(g3 +tp515 +Rp516 +ag2 +(S'0.738' +p517 +tp518 +Rp519 +ag2 +(g3 +tp520 +Rp521 +aa(lp522 +g2 +(g3 +tp523 +Rp524 +ag2 +(S'0.770' +p525 +tp526 +Rp527 +ag2 +(g3 +tp528 +Rp529 +aa(lp530 +g2 +(g3 +tp531 +Rp532 +ag2 +(S'0.790' +p533 +tp534 +Rp535 +ag2 +(g3 +tp536 +Rp537 +aa(lp538 +g2 +(g3 +tp539 +Rp540 +ag2 +(S'0.809' +p541 +tp542 +Rp543 +ag2 +(g3 +tp544 +Rp545 +aa(lp546 +g2 +(g3 +tp547 +Rp548 +ag2 +(S'0.829' +p549 +tp550 +Rp551 +ag2 +(g3 +tp552 +Rp553 +aa(lp554 +g2 +(g3 +tp555 +Rp556 +ag2 +(S'0.848' +p557 +tp558 +Rp559 +ag2 +(g3 +tp560 +Rp561 +aa(lp562 +g2 +(g3 +tp563 +Rp564 +ag2 +(S'0.868' +p565 +tp566 +Rp567 +ag2 +(g3 +tp568 +Rp569 +aa(lp570 +g2 +(g3 +tp571 +Rp572 +ag2 +(S'0.887' +p573 +tp574 +Rp575 +ag2 +(g3 +tp576 +Rp577 +aa(lp578 +g2 +(S'0.0830' +p579 +tp580 +Rp581 +ag2 +(S'0.894' +p582 +tp583 +Rp584 +ag2 +(g3 +tp585 +Rp586 +aa(lp587 +g2 +(S'0.166' +p588 +tp589 +Rp590 +ag2 +(S'0.900' +p591 +tp592 +Rp593 +ag2 +(g3 +tp594 +Rp595 +aa(lp596 +g2 +(S'0.249' +p597 +tp598 +Rp599 +ag2 +(S'0.907' +p600 +tp601 +Rp602 +ag2 +(g3 +tp603 +Rp604 +aa(lp605 +g2 +(S'0.332' +p606 +tp607 +Rp608 +ag2 +(S'0.913' +p609 +tp610 +Rp611 +ag2 +(g3 +tp612 +Rp613 +aa(lp614 +g2 +(S'0.415' +p615 +tp616 +Rp617 +ag2 +(S'0.920' +p618 +tp619 +Rp620 +ag2 +(g3 +tp621 +Rp622 +aa(lp623 +g2 +(S'0.498' +p624 +tp625 +Rp626 +ag2 +(S'0.926' +p627 +tp628 +Rp629 +ag2 +(g3 +tp630 +Rp631 +aa(lp632 +g2 +(S'0.543' +p633 +tp634 +Rp635 +ag2 +(S'0.928' +p636 +tp637 +Rp638 +ag2 +(g3 +tp639 +Rp640 +aa(lp641 +g2 +(S'0.589' +p642 +tp643 +Rp644 +ag2 +(S'0.930' +p645 +tp646 +Rp647 +ag2 +(g3 +tp648 +Rp649 +aa(lp650 +g2 +(S'0.634' +p651 +tp652 +Rp653 +ag2 +(S'0.932' +p654 +tp655 +Rp656 +ag2 +(g3 +tp657 +Rp658 +aa(lp659 +g2 +(S'0.680' +p660 +tp661 +Rp662 +ag2 +(S'0.934' +p663 +tp664 +Rp665 +ag2 +(g3 +tp666 +Rp667 +aa(lp668 +g2 +(S'0.725' +p669 +tp670 +Rp671 +ag2 +(S'0.936' +p672 +tp673 +Rp674 +ag2 +(g3 +tp675 +Rp676 +aa(lp677 +g2 +(S'0.770' +p678 +tp679 +Rp680 +ag2 +(S'0.938' +p681 +tp682 +Rp683 +ag2 +(g3 +tp684 +Rp685 +aa(lp686 +g2 +(S'0.798' +p687 +tp688 +Rp689 +ag2 +(S'0.938' +p690 +tp691 +Rp692 +ag2 +(g3 +tp693 +Rp694 +aa(lp695 +g2 +(S'0.826' +p696 +tp697 +Rp698 +ag2 +(S'0.938' +p699 +tp700 +Rp701 +ag2 +(g3 +tp702 +Rp703 +aa(lp704 +g2 +(S'0.854' +p705 +tp706 +Rp707 +ag2 +(S'0.938' +p708 +tp709 +Rp710 +ag2 +(g3 +tp711 +Rp712 +aa(lp713 +g2 +(S'0.882' +p714 +tp715 +Rp716 +ag2 +(S'0.938' +p717 +tp718 +Rp719 +ag2 +(g3 +tp720 +Rp721 +aa(lp722 +g2 +(S'0.910' +p723 +tp724 +Rp725 +ag2 +(S'0.938' +p726 +tp727 +Rp728 +ag2 +(g3 +tp729 +Rp730 +aa(lp731 +g2 +(S'0.938' +p732 +tp733 +Rp734 +ag2 +(S'0.938' +p735 +tp736 +Rp737 +ag2 +(g3 +tp738 +Rp739 +aa(lp740 +g2 +(S'0.938' +p741 +tp742 +Rp743 +ag2 +(S'0.916' +p744 +tp745 +Rp746 +ag2 +(g3 +tp747 +Rp748 +aa(lp749 +g2 +(S'0.938' +p750 +tp751 +Rp752 +ag2 +(S'0.895' +p753 +tp754 +Rp755 +ag2 +(g3 +tp756 +Rp757 +aa(lp758 +g2 +(S'0.938' +p759 +tp760 +Rp761 +ag2 +(S'0.874' +p762 +tp763 +Rp764 +ag2 +(g3 +tp765 +Rp766 +aa(lp767 +g2 +(S'0.938' +p768 +tp769 +Rp770 +ag2 +(S'0.852' +p771 +tp772 +Rp773 +ag2 +(g3 +tp774 +Rp775 +aa(lp776 +g2 +(S'0.938' +p777 +tp778 +Rp779 +ag2 +(S'0.831' +p780 +tp781 +Rp782 +ag2 +(g3 +tp783 +Rp784 +aa(lp785 +g2 +(S'0.938' +p786 +tp787 +Rp788 +ag2 +(S'0.809' +p789 +tp790 +Rp791 +ag2 +(g3 +tp792 +Rp793 +aa(lp794 +g2 +(S'0.938' +p795 +tp796 +Rp797 +ag2 +(S'0.790' +p798 +tp799 +Rp800 +ag2 +(g3 +tp801 +Rp802 +aa(lp803 +g2 +(S'0.938' +p804 +tp805 +Rp806 +ag2 +(S'0.770' +p807 +tp808 +Rp809 +ag2 +(g3 +tp810 +Rp811 +aa(lp812 +g2 +(S'0.938' +p813 +tp814 +Rp815 +ag2 +(S'0.751' +p816 +tp817 +Rp818 +ag2 +(g3 +tp819 +Rp820 +aa(lp821 +g2 +(S'0.938' +p822 +tp823 +Rp824 +ag2 +(S'0.732' +p825 +tp826 +Rp827 +ag2 +(g3 +tp828 +Rp829 +aa(lp830 +g2 +(S'0.938' +p831 +tp832 +Rp833 +ag2 +(S'0.712' +p834 +tp835 +Rp836 +ag2 +(g3 +tp837 +Rp838 +aa(lp839 +g2 +(S'0.938' +p840 +tp841 +Rp842 +ag2 +(S'0.693' +p843 +tp844 +Rp845 +ag2 +(g3 +tp846 +Rp847 +aa(lp848 +g2 +(S'0.938' +p849 +tp850 +Rp851 +ag2 +(S'0.669' +p852 +tp853 +Rp854 +ag2 +(g3 +tp855 +Rp856 +aa(lp857 +g2 +(S'0.938' +p858 +tp859 +Rp860 +ag2 +(S'0.646' +p861 +tp862 +Rp863 +ag2 +(g3 +tp864 +Rp865 +aa(lp866 +g2 +(S'0.938' +p867 +tp868 +Rp869 +ag2 +(S'0.623' +p870 +tp871 +Rp872 +ag2 +(g3 +tp873 +Rp874 +aa(lp875 +g2 +(S'0.938' +p876 +tp877 +Rp878 +ag2 +(S'0.599' +p879 +tp880 +Rp881 +ag2 +(g3 +tp882 +Rp883 +aa(lp884 +g2 +(S'0.938' +p885 +tp886 +Rp887 +ag2 +(S'0.576' +p888 +tp889 +Rp890 +ag2 +(g3 +tp891 +Rp892 +aa(lp893 +g2 +(S'0.938' +p894 +tp895 +Rp896 +ag2 +(S'0.553' +p897 +tp898 +Rp899 +ag2 +(g3 +tp900 +Rp901 +aa(lp902 +g2 +(S'0.938' +p903 +tp904 +Rp905 +ag2 +(S'0.524' +p906 +tp907 +Rp908 +ag2 +(g3 +tp909 +Rp910 +aa(lp911 +g2 +(S'0.938' +p912 +tp913 +Rp914 +ag2 +(S'0.495' +p915 +tp916 +Rp917 +ag2 +(g3 +tp918 +Rp919 +aa(lp920 +g2 +(S'0.938' +p921 +tp922 +Rp923 +ag2 +(S'0.467' +p924 +tp925 +Rp926 +ag2 +(g3 +tp927 +Rp928 +aa(lp929 +g2 +(S'0.938' +p930 +tp931 +Rp932 +ag2 +(S'0.438' +p933 +tp934 +Rp935 +ag2 +(g3 +tp936 +Rp937 +aa(lp938 +g2 +(S'0.938' +p939 +tp940 +Rp941 +ag2 +(S'0.410' +p942 +tp943 +Rp944 +ag2 +(g3 +tp945 +Rp946 +aa(lp947 +g2 +(S'0.938' +p948 +tp949 +Rp950 +ag2 +(S'0.381' +p951 +tp952 +Rp953 +ag2 +(g3 +tp954 +Rp955 +aa(lp956 +g2 +(S'0.938' +p957 +tp958 +Rp959 +ag2 +(S'0.318' +p960 +tp961 +Rp962 +ag2 +(g3 +tp963 +Rp964 +aa(lp965 +g2 +(S'0.938' +p966 +tp967 +Rp968 +ag2 +(S'0.254' +p969 +tp970 +Rp971 +ag2 +(g3 +tp972 +Rp973 +aa(lp974 +g2 +(S'0.938' +p975 +tp976 +Rp977 +ag2 +(S'0.191' +p978 +tp979 +Rp980 +ag2 +(g3 +tp981 +Rp982 +aa(lp983 +g2 +(S'0.938' +p984 +tp985 +Rp986 +ag2 +(S'0.127' +p987 +tp988 +Rp989 +ag2 +(g3 +tp990 +Rp991 +aa(lp992 +g2 +(S'0.938' +p993 +tp994 +Rp995 +ag2 +(S'0.0636' +p996 +tp997 +Rp998 +ag2 +(g3 +tp999 +Rp1000 +aa(lp1001 +g2 +(S'0.938' +p1002 +tp1003 +Rp1004 +ag2 +(g3 +tp1005 +Rp1006 +ag2 +(g3 +tp1007 +Rp1008 +aa(lp1009 +g2 +(S'0.860' +p1010 +tp1011 +Rp1012 +ag2 +(g3 +tp1013 +Rp1014 +ag2 +(g3 +tp1015 +Rp1016 +aa(lp1017 +g2 +(S'0.781' +p1018 +tp1019 +Rp1020 +ag2 +(g3 +tp1021 +Rp1022 +ag2 +(g3 +tp1023 +Rp1024 +aa(lp1025 +g2 +(S'0.703' +p1026 +tp1027 +Rp1028 +ag2 +(g3 +tp1029 +Rp1030 +ag2 +(g3 +tp1031 +Rp1032 +aa(lp1033 +g2 +(S'0.625' +p1034 +tp1035 +Rp1036 +ag2 +(g3 +tp1037 +Rp1038 +ag2 +(g3 +tp1039 +Rp1040 +aa(lp1041 +g2 +(S'0.547' +p1042 +tp1043 +Rp1044 +ag2 +(g3 +tp1045 +Rp1046 +ag2 +(g3 +tp1047 +Rp1048 +aa(lp1049 +g2 +(S'0.469' +p1050 +tp1051 +Rp1052 +ag2 +(g3 +tp1053 +Rp1054 +ag2 +(g3 +tp1055 +Rp1056 +aa(lp1057 +g2 +(S'0.391' +p1058 +tp1059 +Rp1060 +ag2 +(g3 +tp1061 +Rp1062 +ag2 +(g3 +tp1063 +Rp1064 +aa(lp1065 +g2 +(S'0.313' +p1066 +tp1067 +Rp1068 +ag2 +(g3 +tp1069 +Rp1070 +ag2 +(g3 +tp1071 +Rp1072 +aa(lp1073 +g2 +(S'0.234' +p1074 +tp1075 +Rp1076 +ag2 +(g3 +tp1077 +Rp1078 +ag2 +(g3 +tp1079 +Rp1080 +aa(lp1081 +g2 +(S'0.156' +p1082 +tp1083 +Rp1084 +ag2 +(g3 +tp1085 +Rp1086 +ag2 +(g3 +tp1087 +Rp1088 +aa(lp1089 +g2 +(S'0.0781' +p1090 +tp1091 +Rp1092 +ag2 +(g3 +tp1093 +Rp1094 +ag2 +(g3 +tp1095 +Rp1096 +aa(lp1097 +g2 +(S'0.0389' +p1098 +tp1099 +Rp1100 +ag2 +(g3 +tp1101 +Rp1102 +ag2 +(g3 +tp1103 +Rp1104 +aa(lp1105 +g2 +(g3 +tp1106 +Rp1107 +ag2 +(g3 +tp1108 +Rp1109 +ag2 +(g3 +tp1110 +Rp1111 +aa. \ No newline at end of file diff --git a/moose-gui/config.py b/moose-gui/config.py new file mode 100644 index 0000000000000000000000000000000000000000..cf1a9a647f1c646544f2b866b1512b928c7881dc --- /dev/null +++ b/moose-gui/config.py @@ -0,0 +1,232 @@ +# config.py --- +# +# Filename: config.py +# Description: +# Author: Subhasis Ray +# Maintainer: +# Created: Sat Feb 13 16:07:56 2010 (+0530) +# Version: +# Last-Updated: Wed Nov 12 19:10:08 2014 (+0530) +# By: Subhasis Ray +# Update #: 369 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# Provides keys for accessing per-user settings. +# Provides initialization of several per-user variables for MooseGUI. +# As part of initialization, creates `~/.moose` and `~/moose` +# directories. +# +# + +# Change log: +# +# 2012-09-22 13:49:36 (+0530) Subha: cleaned up the initialization +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: + +import os +import sys +import tempfile +import logging +import errno +from PyQt4.Qt import Qt +from PyQt4 import QtGui, QtCore + +TEMPDIR = tempfile.gettempdir() +KEY_FIRSTTIME = 'firsttime' +# KEY_STATE_FILE = 'statefile' + +KEY_UNDO_LENGTH = 'main/undolength' +KEY_WINDOW_GEOMETRY = 'main/geometry' +KEY_WINDOW_LAYOUT = 'main/layout' +KEY_RUNTIME_AUTOHIDE = 'main/rtautohide' +KEY_DEMOS_DIR = 'main/demosdir' +KEY_DOCS_DIR = 'main/docsdir' +KEY_HOME_DIR = 'main/homedir' +KEY_ICON_DIR = 'main/icondir' +KEY_COLORMAP_DIR = 'main/colormapdir' +KEY_BIOMODEL_DIR = 'main/biomodelsdir' +KEY_LOCAL_DEMOS_DIR = 'main/localdemosdir' +KEY_MOOSE_LOCAL_DIR = 'main/localdir' +KEY_NUMPTHREADS = 'main/numpthreads' +KEY_LOCAL_BUILD = 'main/localbuild' +KEY_LAST_PLUGIN = 'main/lastplugin' + +# These are the keys for mode specific configuration. +# Ideally the default values should be provided by the plugin. +# We use the QSettings to remember the last values +KEY_KINETICS_SIMDT = 'kinetics/simdt' +KEY_KINETICS_PLOTDT = 'kinetics/plotdt' +KEY_ELECTRICAL_SIMDT = 'electrical/simdt' +KEY_ELECTRICAL_PLOTDT = 'electrical/plotdt' +KEY_SIMTIME = 'main/simtime' + +QT_VERSION = str(QtCore.QT_VERSION_STR).split('.') +QT_MAJOR_VERSION = int(QT_VERSION[0]) +QT_MINOR_VERSION = int(QT_VERSION[1]) + +MOOSE_DOC_URL = 'http://moose.ncbs.res.in/builtins_classes/moose_builtins.html' +MOOSE_REPORT_BUG_URL = 'http://sourceforge.net/tracker/?func=add&group_id=165660&atid=836272' +MOOSE_GUI_BUG_URL = 'https://github.com/BhallaLab/moose-gui/issues' +MOOSE_CORE_BUG_URL = 'https://github.com/BhallaLab/moose-core/issues' +MOOSE_DEMOS_DIR = '/usr/share/moose/Demos' +MOOSE_DOCS_DIR = '/usr/share/doc/moose' +MOOSE_GUI_DIR = os.path.dirname(os.path.abspath(__file__)) +MOOSE_PLUGIN_DIR = os.path.join(MOOSE_GUI_DIR, 'plugins') +NEUROKIT_PLUGIN_DIR = os.path.join(MOOSE_GUI_DIR, 'plugins/NeuroKit') +# MOOSE_CFG_DIR = os.path.join(os.environ['HOME'], '.moose') +MOOSE_LOCAL_DIR = os.path.join(os.environ['HOME'], 'moose') +MOOSE_NUMPTHREADS = '1' + +MOOSE_ABOUT_FILE = os.path.join(MOOSE_GUI_DIR, 'about.html') +MOOSE_UNDO_LENGTH = 128 # Arbitrary undo length +LOCAL_BUILD = False + +sys.path.append(os.path.join(MOOSE_PLUGIN_DIR)) + +class MooseSetting(dict): + """ + dict-like access to QSettings. + + This subclass of dict wraps a QSettings object and lets one set + and get values as Python strings rather than QVariant. + + This is supposed to be a singleton in the whole application (all + QSettings are with same parameters). + """ + _instance = None + def __new__(cls, *args, **kwargs): + # This is designed to check if the class has been + # instantiated, if so, returns the single instance, otherwise + # creates it. + if cls._instance is None: + cls._instance = super(MooseSetting, cls).__new__(cls, *args, **kwargs) + firsttime, errs = init_dirs() + for e in errs: + print e + QtCore.QCoreApplication.setOrganizationName('NCBS') + QtCore.QCoreApplication.setOrganizationDomain('ncbs.res.in') + QtCore.QCoreApplication.setApplicationName('MOOSE') + cls._instance.qsettings = QtCore.QSettings() + # If this is the first time, then set some defaults + cls._instance.qsettings.setValue(KEY_COLORMAP_DIR, os.path.join(MOOSE_GUI_DIR, 'colormaps')) + cls._instance.qsettings.setValue(KEY_BIOMODEL_DIR, os.path.join(MOOSE_GUI_DIR, 'bioModels')) + cls._instance.qsettings.setValue(KEY_ICON_DIR, os.path.join(MOOSE_GUI_DIR, 'icons')) + cls._instance.qsettings.setValue(KEY_NUMPTHREADS, '1') + cls._instance.qsettings.setValue(KEY_UNDO_LENGTH, str(MOOSE_UNDO_LENGTH)) + # These are to be checked at every run + cls._instance.qsettings.setValue(KEY_HOME_DIR, os.environ['HOME']) + cls._instance.qsettings.setValue(KEY_DEMOS_DIR, MOOSE_DEMOS_DIR) + cls._instance.qsettings.setValue(KEY_LOCAL_DEMOS_DIR, os.path.join(MOOSE_LOCAL_DIR, 'Demos/')) + cls._instance.qsettings.setValue(KEY_DOCS_DIR, MOOSE_DOCS_DIR) + cls._instance.qsettings.setValue(KEY_MOOSE_LOCAL_DIR, MOOSE_LOCAL_DIR) + cls._instance.qsettings.setValue(KEY_LOCAL_BUILD, LOCAL_BUILD) + os.environ['NUMPTHREADS'] = str(cls._instance.qsettings.value(KEY_NUMPTHREADS).toString()) + return cls._instance + + def __init__(self, *args, **kwargs): + super(MooseSetting, self).__init__(self, *args, **kwargs) + + def __iter__(self): + return (str(key) for key in self.qsettings.allKeys()) + + def __setitem__(self, key, value): + if isinstance(key, str): + self.qsettings.setValue(key, value) + else: + raise TypeError('Expect only strings as keys') + + def __getitem__(self, key): + return str(self.qsettings.value(key).toString()) + + def keys(self): + return [str(key) for key in self.qsettings.allKeys()] + + def values(self): + return [str(self.qsettings.value(key).toString()) for key in self.qsettings.allKeys()] + + def itervalues(self): + return (str(self.qsettings.value(key).toString()) for key in self.qsettings.allKeys()) + +def init_dirs(): + """Check if there is a `.moose` directory in user's home + directory. If not, we assume this to be the first run of MOOSE. + Then we try to create the `~/.moose` directory and `~/moose` + directory. + """ + firsttime = False + global MOOSE_DEMOS_DIR + global MOOSE_LOCAL_DIR + # global MOOSE_CFG_DIR + global MOOSE_DOCS_DIR + global LOCAL_BUILD + # If we have a Makefile above GUI directory, then this must be a + # locally built version + LOCAL_BUILD = os.access(os.path.join(MOOSE_GUI_DIR, '../Makefile'), os.R_OK) + errors = [] + ''' + moose_cfg_dir = os.path.join(os.environ['HOME'], '.moose') + if not os.path.exists(moose_cfg_dir): + firsttime = True + # try: + # # os.mkdir(moose_cfg_dir) + # # # MOOSE_CFG_DIR = moose_cfg_dir + # # print 'Created moose configuration directory:', moose_cfg_dir + # except OSError, e: + # errors.append(e) + # print e + if LOCAL_BUILD: + MOOSE_LOCAL_DIR = os.path.normpath(os.path.join(MOOSE_GUI_DIR, '..')) + MOOSE_DEMOS_DIR = os.path.join(MOOSE_LOCAL_DIR, 'Demos') + MOOSE_DOCS_DIR = os.path.join(MOOSE_LOCAL_DIR, 'Docs/user/py/_build/html/') + else: + MOOSE_LOCAL_DIR = os.path.join(os.environ['HOME'], 'moose') + if not os.path.exists(MOOSE_LOCAL_DIR): + try: + os.mkdir(MOOSE_LOCAL_DIR) + print 'Created local moose directory:', MOOSE_LOCAL_DIR + except OSError, e: + errors.append(e) + print e + if not os.access(MOOSE_DOCS_DIR, os.R_OK + os.X_OK): + print "Could not access Demos directory: %s" % (MOOSE_DOCS_DIR) + errors.append(OSError(errno.EACCES, 'Cannot access %s' % (MOOSE_DOCS_DIR))) + ''' + return firsttime, errors + +settings = MooseSetting() + +# LOG_FILENAME = os.path.join(TEMPDIR, 'moose.log') +LOG_LEVEL = logging.ERROR +# logging.basicConfig(filename=LOG_FILENAME, level=LOG_LEVEL, filemode='w', format='%(asctime)s %(levelname)s %(name)s %(filename)s %(funcName)s: %(lineno)d: %(message)s') +logging.basicConfig(stream=sys.stdout, level=LOG_LEVEL, filemode='w', format='%(asctime)s %(levelname)s %(name)s %(filename)s %(funcName)s: %(lineno)d: %(message)s') +LOGGER = logging.getLogger('moose') +BENCHMARK_LOGGER = logging.getLogger('moose.benchmark') +BENCHMARK_LOGGER.setLevel(logging.INFO) + +# +# config.py ends here diff --git a/moose-gui/configwidget.py b/moose-gui/configwidget.py new file mode 100644 index 0000000000000000000000000000000000000000..87d10c375ec2a127e9861ec09beee65eb631f3ff --- /dev/null +++ b/moose-gui/configwidget.py @@ -0,0 +1,122 @@ +# firsttime.py --- +# +# Filename: firsttime.py +# Description: +# Author: Subhasis Ray +# Maintainer: +# Created: Sun Jul 11 15:31:00 2010 (+0530) +# Version: +# Last-Updated: Sat Sep 22 15:30:15 2012 (+0530) +# By: subha +# Update #: 505 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# Wizard to take the user through selection of some basic +# configurations for MOOSE gui. +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: + +import shutil +import os +import config +from PyQt4 import QtGui, QtCore +import config +from utils import * + +class ConfigWidget(QtGui.QDialog): + """Widget to configure MOOSE.""" + def __init__(self, *args, **kwargs): + super(QtGui.QDialog, self).__init__(*args, **kwargs) + self.tabWidget = QtGui.QTabWidget(self) + self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | + QtGui.QDialogButtonBox.Cancel| + QtGui.QDialogButtonBox.RestoreDefaults) + self.connect(self.buttonBox, QtCore.SIGNAL('accepted()'), self.accept) + self.connect(self.buttonBox, QtCore.SIGNAL('rejected()'), self.reject) + self.connect(self.buttonBox.button(QtGui.QDialogButtonBox.RestoreDefaults), + QtCore.SIGNAL('clicked()'), + self._onRestoreDefaults) + self.connect(self, QtCore.SIGNAL('accepted()'), self._onAccept) + layout = QtGui.QVBoxLayout() + layout.addWidget(self.tabWidget) + layout.addWidget(self.buttonBox) + self.setLayout(layout) + self._createGeneralPanel() + + def _createGeneralPanel(self): + if hasattr(self, 'generalPanel'): + return self.generalPanel + self.generalPanel = QtGui.QWidget(self) + self.generalPanelLabel = QtGui.QLabel(self.generalPanel) + self.generalPanelLabel.setText('<center>General configuration for MOOSE</center>') + self.colormapDirLabel = QtGui.QLabel('Colormap directory', + self.generalPanel) + self.colormapDirEdit = QtGui.QLineEdit(config.settings[config.KEY_COLORMAP_DIR], + self.generalPanel) + self.demosDirLabel = QtGui.QLabel('Demos directory', self.generalPanel) + self.demosDirEdit = QtGui.QLineEdit(config.settings[config.KEY_DEMOS_DIR]) + self.numPThreadsLabel = QtGui.QLabel('Number of process threads<p><i>(restart MOOSE to take effect)</i></p>', self.generalPanel) + self.numPThreadsEdit = QtGui.QLineEdit(config.settings[config.KEY_NUMPTHREADS]) + layout = QtGui.QGridLayout() + layout.addWidget(self.generalPanelLabel, 0, 0, 1, 4) + layout.setRowStretch(0, 2) + layout.addWidget(self.colormapDirLabel, 1, 0) + layout.addWidget(self.colormapDirEdit, 1, 2) + layout.addWidget(self.demosDirLabel, 2, 0) + layout.addWidget(self.demosDirEdit, 2, 2) + layout.addWidget(self.numPThreadsLabel, 3, 0) + layout.addWidget(self.numPThreadsEdit, 3, 2) + self.generalPanel.setLayout(layout) + self.tabWidget.addTab(self.generalPanel, 'General') + return self.generalPanel + + def _onAccept(self): + config.settings[config.KEY_DEMOS_DIR] = self.demosDirEdit.text() + config.settings[config.KEY_COLORMAP_DIR] = self.colormapDirEdit.text() + config.settings[config.KEY_NUMPTHREADS] = self.numPThreadsEdit.text() + + def _onRestoreDefaults(self): + self.demosDirEdit.setText(config.MOOSE_DEMOS_DIR) + self.colormapDirEdit.setText(os.path.join(config.MOOSE_GUI_DIR, 'colormaps')) + self.numPThreadsEdit.setText('1') + + +if __name__ == '__main__': + """Test the configuration widget""" + app =QtGui.QApplication([]) + widget = ConfigWidget() + widget.setMinimumSize(600, 200) + widget.show() + app.exec_() + + diff --git a/moose-gui/defaults.py b/moose-gui/defaults.py new file mode 100644 index 0000000000000000000000000000000000000000..bb49b93c0cb5563f52b064a8e5c6e46bb0aed5ac --- /dev/null +++ b/moose-gui/defaults.py @@ -0,0 +1,36 @@ + +PLOT_FIELDS={ + 'LeakyIaF':['Vm'], + 'Compartment':['Vm','Im'], + 'HHChannel':['Ik','Gk'], + 'ZombiePool':['n','conc'], + 'ZombieBufPool':['n','conc'], + 'HHChannel2D':['Ik','Gk'], + 'CaConc':['Ca'] + } +FIELD_UNITS={ + 'Vm':'V', + 'conc':'mM', + 'concInit':'mM', + 'Rm':'ohm', + 'Ra':'ohm', + 'Cm':'F', + 'initVm':'V', + 'Im':'A', + 'Em':'V', + 'inject':'A', + 'Ek':'V', + 'Gk':'S', + 'Gbar':'S', + 'Ik':'A', + 'Ca':'mM', + 'CaBasal':'mM', + 'tau':'s', + 'Ca_base':'mM', + 'B':'mM/A', + 'thick':'m', + 'ceiling':'mM', + 'floor':'mM' +} + +OBJECT_EDIT_UNDO_LENGTH = 16 diff --git a/moose-gui/global_constants.py b/moose-gui/global_constants.py new file mode 100644 index 0000000000000000000000000000000000000000..247b5cbfc227fbfb71f6dea47fa497fffb23c4ea --- /dev/null +++ b/moose-gui/global_constants.py @@ -0,0 +1,3 @@ +from PreferencesPresenter import PreferencesPresenter + +preferences = PreferencesPresenter() diff --git a/moose-gui/icons/QMdiBackground.png b/moose-gui/icons/QMdiBackground.png new file mode 100644 index 0000000000000000000000000000000000000000..7bb524991fa8e05d22b8507846105b03401229b9 Binary files /dev/null and b/moose-gui/icons/QMdiBackground.png differ diff --git a/moose-gui/icons/add.png b/moose-gui/icons/add.png new file mode 100644 index 0000000000000000000000000000000000000000..31e4124cd7b164b37adb7697e459c62bd0ea36c1 Binary files /dev/null and b/moose-gui/icons/add.png differ diff --git a/moose-gui/icons/add_graph.png b/moose-gui/icons/add_graph.png new file mode 100644 index 0000000000000000000000000000000000000000..d3d85b4a06e89d0ad1c51abefb9eac575b50569a Binary files /dev/null and b/moose-gui/icons/add_graph.png differ diff --git a/moose-gui/icons/arrow.png b/moose-gui/icons/arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..14978c2e56e55e8e4fc8b7d944bef836d1d68ab7 Binary files /dev/null and b/moose-gui/icons/arrow.png differ diff --git a/moose-gui/icons/arrow_undo.png b/moose-gui/icons/arrow_undo.png new file mode 100644 index 0000000000000000000000000000000000000000..5af6c8ab64321e6fc73062a8923d26be6494d202 Binary files /dev/null and b/moose-gui/icons/arrow_undo.png differ diff --git a/moose-gui/icons/classIcon/BufPool.png b/moose-gui/icons/classIcon/BufPool.png new file mode 100644 index 0000000000000000000000000000000000000000..8136a3799af5f1502c1e2f8c23434228a5a39a15 Binary files /dev/null and b/moose-gui/icons/classIcon/BufPool.png differ diff --git a/moose-gui/icons/classIcon/CubeMesh.png b/moose-gui/icons/classIcon/CubeMesh.png new file mode 100644 index 0000000000000000000000000000000000000000..bb0553c10229bf4ca1625d748260c644ed0b958c Binary files /dev/null and b/moose-gui/icons/classIcon/CubeMesh.png differ diff --git a/moose-gui/icons/classIcon/CylMesh.png b/moose-gui/icons/classIcon/CylMesh.png new file mode 100644 index 0000000000000000000000000000000000000000..641327a93bd4f68923c4df6d4471b617da2675e4 Binary files /dev/null and b/moose-gui/icons/classIcon/CylMesh.png differ diff --git a/moose-gui/icons/classIcon/Enz.png b/moose-gui/icons/classIcon/Enz.png new file mode 100644 index 0000000000000000000000000000000000000000..5af49911853535913ffafaa5cfd6677017268785 Binary files /dev/null and b/moose-gui/icons/classIcon/Enz.png differ diff --git a/moose-gui/icons/classIcon/FuncPool.png b/moose-gui/icons/classIcon/FuncPool.png new file mode 100644 index 0000000000000000000000000000000000000000..cd17659503a400106b3c1e236cccf65ba79cadb8 Binary files /dev/null and b/moose-gui/icons/classIcon/FuncPool.png differ diff --git a/moose-gui/icons/classIcon/Function.png b/moose-gui/icons/classIcon/Function.png new file mode 100644 index 0000000000000000000000000000000000000000..cd17659503a400106b3c1e236cccf65ba79cadb8 Binary files /dev/null and b/moose-gui/icons/classIcon/Function.png differ diff --git a/moose-gui/icons/classIcon/MMenz.png b/moose-gui/icons/classIcon/MMenz.png new file mode 100644 index 0000000000000000000000000000000000000000..4d881a9a7f320e2b0e538bd9ac1c978f3ba25f85 Binary files /dev/null and b/moose-gui/icons/classIcon/MMenz.png differ diff --git a/moose-gui/icons/classIcon/Pool.png b/moose-gui/icons/classIcon/Pool.png new file mode 100644 index 0000000000000000000000000000000000000000..bb2ac460542bdea1f85fc85187fdda984dc49b70 Binary files /dev/null and b/moose-gui/icons/classIcon/Pool.png differ diff --git a/moose-gui/icons/classIcon/Reac.png b/moose-gui/icons/classIcon/Reac.png new file mode 100644 index 0000000000000000000000000000000000000000..07e9eec0fb92806a3cd506ac58f2c6decd051a2c Binary files /dev/null and b/moose-gui/icons/classIcon/Reac.png differ diff --git a/moose-gui/icons/classIcon/StimulusTable.png b/moose-gui/icons/classIcon/StimulusTable.png new file mode 100644 index 0000000000000000000000000000000000000000..ec8701e5aa85cd1087f1a03bb1460a64baa9ef9b Binary files /dev/null and b/moose-gui/icons/classIcon/StimulusTable.png differ diff --git a/moose-gui/icons/classIcon/SumFunc.png b/moose-gui/icons/classIcon/SumFunc.png new file mode 100644 index 0000000000000000000000000000000000000000..d516dddb3e6265868ddf7de3fdccc05507ac038a Binary files /dev/null and b/moose-gui/icons/classIcon/SumFunc.png differ diff --git a/moose-gui/icons/clone.svg b/moose-gui/icons/clone.svg new file mode 100644 index 0000000000000000000000000000000000000000..bb18fd9bd3e0d149718f026d5d9fa82a1e5118d8 --- /dev/null +++ b/moose-gui/icons/clone.svg @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> +<path d="M12.5,8H9V4.5C9,4.224,8.775,4,8.5,4C8.224,4,8,4.224,8,4.5V8H4.5C4.224,8,4,8.224,4,8.5C4,8.775,4.224,9,4.5,9H8v3.5 + C8,12.775,8.224,13,8.5,13C8.775,13,9,12.775,9,12.5V9h3.5C12.775,9,13,8.775,13,8.5C13,8.224,12.775,8,12.5,8z"/> +</svg> diff --git a/moose-gui/icons/connection.png b/moose-gui/icons/connection.png new file mode 100644 index 0000000000000000000000000000000000000000..91bf3c0b081c95f1cd7a6efb83c57118717f3ae9 Binary files /dev/null and b/moose-gui/icons/connection.png differ diff --git a/moose-gui/icons/continue.png b/moose-gui/icons/continue.png new file mode 100644 index 0000000000000000000000000000000000000000..0a15dc8a98ba5c26795988f7d98c9bd4231f3519 Binary files /dev/null and b/moose-gui/icons/continue.png differ diff --git a/moose-gui/icons/delete.svg b/moose-gui/icons/delete.svg new file mode 100644 index 0000000000000000000000000000000000000000..36c2711f19e11e95fc63034b275d78049dabbd06 --- /dev/null +++ b/moose-gui/icons/delete.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="pointer-events: none; display: block;"><g id="clear"><polygon points="19,6.4 17.6,5 12,10.6 6.4,5 5,6.4 10.6,12 5,17.6 6.4,19 12,13.4 17.6,19 19,17.6 13.4,12 "></polygon></g></svg> \ No newline at end of file diff --git a/moose-gui/icons/delete_graph.png b/moose-gui/icons/delete_graph.png new file mode 100644 index 0000000000000000000000000000000000000000..f7feb5c3c3ce63e833af61654a445779a4f04920 Binary files /dev/null and b/moose-gui/icons/delete_graph.png differ diff --git a/moose-gui/icons/grid.png b/moose-gui/icons/grid.png new file mode 100644 index 0000000000000000000000000000000000000000..5f07bbc31268ea8b897dbf564ff22d5918d71b77 Binary files /dev/null and b/moose-gui/icons/grid.png differ diff --git a/moose-gui/icons/hand.png b/moose-gui/icons/hand.png new file mode 100644 index 0000000000000000000000000000000000000000..20cfaf52a512781dec64328692e2bcc6fde2feb2 Binary files /dev/null and b/moose-gui/icons/hand.png differ diff --git a/moose-gui/icons/help.png b/moose-gui/icons/help.png new file mode 100644 index 0000000000000000000000000000000000000000..403c27d1c03c72687d14d156f8e8d5a009f1b5aa Binary files /dev/null and b/moose-gui/icons/help.png differ diff --git a/moose-gui/icons/hopfield.png b/moose-gui/icons/hopfield.png new file mode 100644 index 0000000000000000000000000000000000000000..ec832a8f5a1c7244ae98725762661a020c37ca30 Binary files /dev/null and b/moose-gui/icons/hopfield.png differ diff --git a/moose-gui/icons/list.png b/moose-gui/icons/list.png new file mode 100644 index 0000000000000000000000000000000000000000..ab96e07812b12479ad11a2bd6ed66bf430df671e Binary files /dev/null and b/moose-gui/icons/list.png differ diff --git a/moose-gui/icons/moose_icon.png b/moose-gui/icons/moose_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2be110d78bb773afb0da17c3cf650d5227f1485a Binary files /dev/null and b/moose-gui/icons/moose_icon.png differ diff --git a/moose-gui/icons/moose_icon_64x64.png b/moose-gui/icons/moose_icon_64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..270f5aa4fe31501e11b8e47b7777a43334309d6c Binary files /dev/null and b/moose-gui/icons/moose_icon_64x64.png differ diff --git a/moose-gui/icons/moose_icon_large.png b/moose-gui/icons/moose_icon_large.png new file mode 100644 index 0000000000000000000000000000000000000000..ab8a1f041a97b9ed4bff0e0e34b41e10ecb795d0 Binary files /dev/null and b/moose-gui/icons/moose_icon_large.png differ diff --git a/moose-gui/icons/move.svg b/moose-gui/icons/move.svg new file mode 100644 index 0000000000000000000000000000000000000000..5dd4d9a57e44427ae973b13b26744a52102de028 --- /dev/null +++ b/moose-gui/icons/move.svg @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 86.952 86.952" style="enable-background:new 0 0 86.952 86.952;" xml:space="preserve"> +<polygon points="86.952,43.312 74.296,30.609 74.296,40.874 46.078,40.874 46.078,12.656 56.343,12.656 43.641,0 30.609,12.656 + 40.875,12.656 40.875,40.874 12.657,40.874 12.657,30.609 0,43.312 12.657,56.343 12.657,46.077 40.875,46.077 40.875,74.296 + 30.609,74.296 43.641,86.952 56.343,74.296 46.078,74.296 46.078,46.077 74.296,46.077 74.296,56.343 "/> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +</svg> diff --git a/moose-gui/icons/plot.svg b/moose-gui/icons/plot.svg new file mode 100644 index 0000000000000000000000000000000000000000..ee9fd184f21f00c32deda784ee619292cf95395a --- /dev/null +++ b/moose-gui/icons/plot.svg @@ -0,0 +1,231 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.1" + id="Capa_1" + x="0px" + y="0px" + viewBox="0 0 32 32" + style="enable-background:new 0 0 32 32;" + xml:space="preserve" + inkscape:version="0.48.3.1 r9886" + width="100%" + height="100%" + sodipodi:docname="p1.svg"><metadata + id="metadata42"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs + id="defs40"><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3021"><rect + id="rect3023" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3025"><rect + id="rect3027" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3029"><rect + id="rect3031" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3033"><rect + id="rect3035" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3037"><rect + id="rect3039" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3041"><rect + id="rect3043" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3045"><rect + id="rect3047" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3049"><rect + id="rect3051" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3053"><rect + id="rect3055" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3057"><rect + id="rect3059" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3061"><rect + id="rect3063" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3065"><rect + id="rect3067" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3069"><rect + id="rect3071" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3073"><rect + id="rect3075" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3077"><rect + id="rect3079" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3081"><rect + id="rect3083" + width="25.220339" + height="15.322034" + x="6.6440678" + y="7.7288136" /></clipPath></defs><sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="640" + inkscape:window-height="480" + id="namedview38" + showgrid="false" + inkscape:zoom="7.375" + inkscape:cx="16" + inkscape:cy="16" + inkscape:window-x="65" + inkscape:window-y="24" + inkscape:window-maximized="0" + inkscape:current-layer="Capa_1" /> +<g + id="chart_2" + clip-path="url(#clipPath3081)" + transform="matrix(1.0724895,0,0,1.4875506,-7.3665026,-9.5875207)"> + <g + id="g4"> + <path + style="fill-rule:evenodd" + d="M 1,31 V 0 H 0 V 32 H 32 V 31 H 1 z m 9.856,-9 c 3.865,-0.217 6.6,-11.783 8.108,-11.783 1.248,0 3.026,9.247 6.096,10.66 2.354,1.084 6.909,0.123 6.909,0.123 v -2 c 0,0 -5.194,1.027 -6.62,-0.4 C 23.373,16.625 22.128,8 19,8 15.605,8 12.848,20.031 10.406,20.031 5.482,20.031 4.375,14.987 4.375,14.987 L 3,16 c 0,0 0.568,6.409 7.856,6 z" + id="path6" + inkscape:connector-curvature="0" /> + </g> +</g> +<g + id="g8" + clip-path="url(#clipPath3077)"> +</g> +<g + id="g10" + clip-path="url(#clipPath3073)"> +</g> +<g + id="g12" + clip-path="url(#clipPath3069)"> +</g> +<g + id="g14" + clip-path="url(#clipPath3065)"> +</g> +<g + id="g16" + clip-path="url(#clipPath3061)"> +</g> +<g + id="g18" + clip-path="url(#clipPath3057)"> +</g> +<g + id="g20" + clip-path="url(#clipPath3053)"> +</g> +<g + id="g22" + clip-path="url(#clipPath3049)"> +</g> +<g + id="g24" + clip-path="url(#clipPath3045)"> +</g> +<g + id="g26" + clip-path="url(#clipPath3041)"> +</g> +<g + id="g28" + clip-path="url(#clipPath3037)"> +</g> +<g + id="g30" + clip-path="url(#clipPath3033)"> +</g> +<g + id="g32" + clip-path="url(#clipPath3029)"> +</g> +<g + id="g34" + clip-path="url(#clipPath3025)"> +</g> +<g + id="g36" + clip-path="url(#clipPath3021)"> +</g> +</svg> \ No newline at end of file diff --git a/moose-gui/icons/reset.png b/moose-gui/icons/reset.png new file mode 100644 index 0000000000000000000000000000000000000000..ceae2b262abb685092d7e2e56fd0dc094fad2405 Binary files /dev/null and b/moose-gui/icons/reset.png differ diff --git a/moose-gui/icons/run.png b/moose-gui/icons/run.png new file mode 100644 index 0000000000000000000000000000000000000000..0823989b07778d81665e789cb59e4adf46e1c098 Binary files /dev/null and b/moose-gui/icons/run.png differ diff --git a/moose-gui/icons/runtime.png b/moose-gui/icons/runtime.png new file mode 100644 index 0000000000000000000000000000000000000000..b70ffd0de7add3e761db8e1e7fe0cad2ea8ab6ea Binary files /dev/null and b/moose-gui/icons/runtime.png differ diff --git a/moose-gui/icons/squid.png b/moose-gui/icons/squid.png new file mode 100644 index 0000000000000000000000000000000000000000..16b24013cef56329aeb50007649e9879fbae350e Binary files /dev/null and b/moose-gui/icons/squid.png differ diff --git a/moose-gui/icons/stop.png b/moose-gui/icons/stop.png new file mode 100644 index 0000000000000000000000000000000000000000..c794e86f1f92345cbe10596fd64a70a02d94137b Binary files /dev/null and b/moose-gui/icons/stop.png differ diff --git a/moose-gui/icons/straight_connector_with_filled_circles.png b/moose-gui/icons/straight_connector_with_filled_circles.png new file mode 100644 index 0000000000000000000000000000000000000000..a2b17bc95345beeea291bd72769ec112eaaca2bd Binary files /dev/null and b/moose-gui/icons/straight_connector_with_filled_circles.png differ diff --git a/moose-gui/icons/wrench.png b/moose-gui/icons/wrench.png new file mode 100644 index 0000000000000000000000000000000000000000..585c5bdb9de355a66fc3b6e322c392928c3501de Binary files /dev/null and b/moose-gui/icons/wrench.png differ diff --git a/moose-gui/loaderdialog.py b/moose-gui/loaderdialog.py new file mode 100644 index 0000000000000000000000000000000000000000..d49e1cee40f75c812043e4ff8b9997e83c9cd7b3 --- /dev/null +++ b/moose-gui/loaderdialog.py @@ -0,0 +1,112 @@ +# fileloader.py --- +# +# Filename: fileloader.py +# Description: +# Author: +# Maintainer: +# Created: Mon Feb 25 15:59:54 2013 (+0530) +# Version: +# Last-Updated: Wed May 22 12:30:14 2013 (+0530) +# By: subha +# Update #: 106 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# Dialog for loading model files +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: + +import sys +from PyQt4 import QtGui,QtCore,Qt +import moose +import os +import posixpath + +class LoaderDialog(QtGui.QFileDialog): + # Update ftypes to include new file types + ftypes='All Supported Files (*.cspace *.g *.xml *.p);; CSPACE (*.cspace);; GENESIS (*.g);; GENESIS Prototype (*.p);; NeuroML/SBML (*.xml)' + target_default = '' # The default target when loading a model + def __init__(self, *args): + self.modelpath = None + super(LoaderDialog, self).__init__(*args) + self.setNameFilter(self.tr(self.ftypes)) + self.setNameFilterDetailsVisible(True) + self.setReadOnly(True) + self.setFileMode(self.ExistingFile) + # self.targetPanel = QtGui.QFrame() + # self.targetLabel = QtGui.QLabel('Model name') + # self.targetText = QtGui.QLineEdit(self.target_default) + # form = QtGui.QFormLayout() + # form.addRow(self.targetLabel, self.targetText) + # self.modelChoiceBox = QtGui.QGroupBox('Model name') + # self.replaceExistingButton = QtGui.QRadioButton('&Replace current model') + # self.mergeExistingButton = QtGui.QRadioButton('&Keep current model') + # self.replaceExistingButton.setChecked(True) + # vbox = QtGui.QVBoxLayout() + # vbox.addWidget(self.replaceExistingButton) + # vbox.addWidget(self.mergeExistingButton) + # self.modelChoiceBox.setLayout(vbox) + # self.targetPanel.setLayout(form) + # self.layout().addWidget(self.targetPanel) + # self.layout().addWidget(self.modelChoiceBox) + self.fileSelected.connect(self.fileSelectedSlot) + + def fileSelectedSlot(self, fpath): + """On selecting a file, this function will cause the target location to change to: + + /model/filename_minus_extension + + """ + self.modelpath = os.path.splitext(os.path.basename(str(fpath)))[0] + + # def isReplace(self): + # return self.replaceExistingButton.isChecked() + + # def isMerge(self): + # return self.mergeExistingButton.isChecked() + + def getTargetPath(self): + return self.modelpath + + +if __name__ == '__main__': + app = QtGui.QApplication(sys.argv) + QtGui.qApp = app + mw = LoaderDialog() + mw.show() + # mw.exec_() + sys.exit(app.exec_()) + + + +# +# fileloader.py ends here diff --git a/moose-gui/mexception.py b/moose-gui/mexception.py new file mode 100644 index 0000000000000000000000000000000000000000..53a728b101329be0082d2b9759cb71163b0a5299 --- /dev/null +++ b/moose-gui/mexception.py @@ -0,0 +1,73 @@ +# mexception.py --- +# +# Filename: mexception.py +# Description: Implements some custom exceptions +# Author: Subhasis Ray +# Maintainer: +# Created: Fri Apr 19 14:34:51 2013 (+0530) +# Version: +# Last-Updated: Wed May 22 14:25:18 2013 (+0530) +# By: subha +# Update #: 22 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: +"""Exception for MOOSE. All error-level exceptions must be derived +from MooseError. Otherwise they will not be handled by system error +handler which displays a message box. + +""" +class MooseInfo(Exception): + def __init__(self, *args, **kwargs): + Exception.__init__(self, *args, **kwargs) + +class MooseWarning(Warning): + def __init__(self, *args, **kwargs): + Warning.__init__(self, *args, **kwargs) + +class MooseError(StandardError): + def __init__(self, *args, **kwargs): + StandardError.__init__(self, *args, **kwargs) + +class FileLoadError(MooseError): + def __init__(self, *args, **kwargs): + StandardError.__init__(self, *args, **kwargs) + +class ElementNameError(MooseError): + def __init__(self, *args, **kwargs): + StandardError.__init__(self, *args, **kwargs) + +# +# mexception.py ends here diff --git a/moose-gui/mgui.py b/moose-gui/mgui.py new file mode 100644 index 0000000000000000000000000000000000000000..9627137b617bca3198a90b7d659fad467b6380be --- /dev/null +++ b/moose-gui/mgui.py @@ -0,0 +1,1197 @@ +# mgui.py --- +# +# Filename: mgui.py +# Description: +# Author: +# Maintainer: +# Created: Mon Nov 12 09:38:09 2012 (+0530) +# Version: +# Last-Updated: Fri Oct 30 11:54:33 2015 (+0530) +# By: Harsha +# Update #: 1338 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# The gui driver +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: +import imp +import inspect +import code +import traceback +import sys +sys.path.append('../python') +#sys.path.append('utils') +import os +from collections import defaultdict +import posixpath # We use this to create MOOSE paths +from PyQt4 import QtGui, QtCore, Qt +import config +import mplugin +import moose +import mexception +from moose import utils +from mload import loadFile +from loaderdialog import LoaderDialog +from shell import get_shell_class +from objectedit import ObjectEditDockWidget +from newmodeldialog import DialogWidget +import re +from biomodelsclient import BioModelsClientWidget +from PyQt4 import Qt, QtCore, QtGui +from PyQt4.QtGui import * +from MdiArea import MdiArea +import os +from setsolver import * +from defines import * +from collections import OrderedDict + +__author__ = 'Subhasis Ray , HarshaRani, Aviral Goel, NCBS' + +# This maps model subtypes to corresponding plugin names. Should be +# moved to a separate property file perhaps +subtype_plugin_map = { 'genesis/kkit': 'kkit' + , 'cspace/': 'kkit' + , 'xml/sbml': 'kkit' + , 'xml/neuroml': 'NeuroKit' + } + +#APPLICATION_ICON_PATH = os.path.join( os.path.dirname(os.path.realpath(__file__)) +# , "icons/moose_icon.png" +# ) + + +def busyCursor(): + app = QtGui.qApp + app.setOverrideCursor(QtGui.QCursor(Qt.Qt.BusyCursor)) #shows a hourglass - or a busy/working arrow + +def freeCursor(): + app = QtGui.qApp + app.restoreOverrideCursor() + + + +class MWindow(QtGui.QMainWindow): + """The main window for MOOSE GUI. + + This is the driver class that uses the mplugin API. mplugin based + classes will provide the toolbar, plugin specific menu items and a + set of panes to be displayed on the docks. + + 1. Setting a plugin + + When a plugin is set as the current plugin, the view and the + menus are updated. + + 1.a) Updating menus: + + the plugin can provide its own list of menus by implementing the + function getMenus(). + + the view of the plugin can also provide its own list of + menus by implementing the function getMenus(). + + the currentView provides a set of toolbars that are added to the + main window. + + 1.b) Updating views + + central widget is set to the currentView (a ViewBase instance) of + the plugin. + + the currentView provides a set of panes that are inserted in the + right dock area one by one. + + """ + def __init__(self, *args): + QtGui.QMainWindow.__init__(self, *args) + self.setWindowTitle('MOOSE') + self.pluginNames = None + self.plugin = None + self.fileMenu = None + self.editMenu = None + self.helpMenu = None + self.helpActions = None + self.viewActions = None + self.editActions = None + self.connectMenu = None + + self.toolBars = [] + self._loadedPlugins = {} + self._plugins = {} + self._loadedModels = [] + self.setUnifiedTitleAndToolBarOnMac(True) + self.setDockOptions(self.AnimatedDocks and self.AllowNestedDocks and self.AllowTabbedDocks) + self.mdiArea = MdiArea() + + self.quitAction = QtGui.QAction('&Quit', self) + self.connect(self.quitAction, QtCore.SIGNAL('triggered()'), self.quit) + self.quitAction.setShortcut(QtGui.QApplication.translate("MainWindow", "Ctrl+Q", None, QtGui.QApplication.UnicodeUTF8)) + self.getMyDockWidgets() + self.setCentralWidget(self.mdiArea) + #self.setWindowIcon(QIcon(APPLICATION_ICON_PATH)) + + # pixmap = QPixmap("icons/moose_icon.png") + + # pixmap = pixmap.scaled(self.mdiArea.size()) + # self.mdiArea.setStyleSheet("QMdiArea { background-image: url(icons/moose_icon_large.png); }") + # palette = QPalette() + # palette.setBrush(QPalette.Background, QBrush(pixmap)) + # self.setPalette(palette) + + + # self.mdiArea.setStyleSheet("border-image: url(icons/moose_icon_large.png)") + # self.mdiArea.setBackground(QBrush(pixmap)) + + self.mdiArea.setViewMode(QtGui.QMdiArea.TabbedView) + self.mdiArea.subWindowActivated.connect(self.switchSubwindowSlot) + self.setPlugin('default', '/') + self.plugin.getEditorView().getCentralWidget().parent().close() + self.popup = None + self.createPopup() + + def createPopup(self): + self.popup = dialog = QDialog(self) + #dialog.setWindowFlags(Qt.Qt.Dialog | Qt.Qt.FramelessWindowHint) + dialog.setWindowFlags(Qt.Qt.Dialog | Qt.Qt.CustomizeWindowHint) + #dialog.setStyleSheet("border:1px solid rgb(0, 0, 0); ") + qapp = QApplication.desktop().screenGeometry(); + dialog.setGeometry((qapp.bottomLeft().x()+100),(qapp.bottomLeft().y()-250),100,100) + #dialog.move(qapp.bottomLeft().x()+10,qapp.bottomLeft().y()-10) + layout = QGridLayout() + self.setStyleSheet("QPushButton{border-radius: 5px; border-color: rgb(0,0,0); border-width: 2px; border-style: outset; padding-top: 2px; padding-bottom: 5px; padding-left: 5px; padding-right: 5px}") + #self.setStyleSheet("QToolTip{border-radius: 5px; border-width: 2px; border-style: outset; padding-top: 2px; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; color: black}") + createKineticModelButton = QPushButton("Create Kinetic Model") + loadKineticModelButton = QPushButton("Load Model") + loadNeuronalModelButton = QPushButton("Load Neuronal Model") + layout.setContentsMargins(QtCore.QMargins(20,20,20,20)) + + self.menuitems = OrderedDict([("Fig2C" , "../moose-examples/paper-2015/Fig2_elecModels/Fig2C.py"), + ("Fig2D (35s)", "../moose-examples/paper-2015/Fig2_elecModels/Fig2D.py"), + ("Fig2E" , "../moose-examples/paper-2015/Fig2_elecModels/Fig2E.py"), + ("Fig3B_Gssa", "../moose-examples/paper-2015/Fig3_chemModels/Fig3ABC.g"), + ("Fig3C_Gsl", "../moose-examples/paper-2015/Fig3_chemModels/Fig3ABC.g"), + ("Fig3D", "../moose-examples/paper-2015/Fig3_chemModels/Fig3D.py"), + ("Fig4B", "../moose-examples/paper-2015/Fig4_ReacDiff/Fig4B.py" ), + ("Fig4K", "../moose-examples/paper-2015/Fig4_ReacDiff/rxdSpineSize.py"), + ("Fig5A (20s)", "../moose-examples/paper-2015/Fig5_CellMultiscale/Fig5A.py"), + ("Fig5BCD (240s)" , "../moose-examples/paper-2015/Fig5_CellMultiscale/Fig5BCD.py"), + ("Fig6A (60s)", "../moose-examples/paper-2015/Fig6_NetMultiscale/Fig6A.py" ), + ("Reduced6 (200s)", "../moose-examples/paper-2015/Fig6_NetMultiscale/ReducedModel.py"), + ("Squid" , "../moose-examples/squid/squid_demo.py") + ]) + layout.setContentsMargins(QtCore.QMargins(20,20,20,20)) + layout1 = QHBoxLayout() + layout1.addWidget(createKineticModelButton) + layout1.addWidget(loadKineticModelButton) + layout2 = QHBoxLayout() + layout3 = QHBoxLayout() + layout4 = QHBoxLayout() + layout5 = QHBoxLayout() + layout6 = QHBoxLayout() + layout7 = QHBoxLayout() + listofButtons = {} + for i in range(0,len(self.menuitems)): + k = self.menuitems.popitem(0) + t = k[0] + button = QPushButton(k[0]) + if k[0] == "Fig2E": + button.setToolTip("<span style=\"color:black;\">Illustrates loading a model from an SWC file, inserting channels, and running it</span>") + elif k[0] == "Fig2D (35s)": + button.setToolTip("<span style=\"color:black;\">Illustrates loading a model from an SWC file, inserting spines, and running it</span>") + elif k[0] == "Fig2C": + button.setToolTip("<span style=\"color:black;\">Illustrates building a panel of multiscale models to test neuronal plasticity in different contexts</span>") + elif k[0] == "Fig3B_Gssa": + button.setToolTip("<span style=\"color:black;\">Loades Repressilator model into Gui with Gssa solver and runs the model</span>") + elif k[0] == "Fig3C_Gsl": + button.setToolTip("<span style=\"color:black;\">Loades Repressilator model into Gui with Gsl solver and runs the model</span>") + elif k[0] == "Fig3D": + button.setToolTip("<span style=\"color:black;\">This example implements a reaction-diffusion like system which is bistable and propagates losslessly</span>") + elif k[0] == "Fig4B": + button.setToolTip("<span style=\"color:black;\">This program builds a multiscale model with a few spines inserted into a simplified cellular morphology. Each spine has a signaling model in it too. The program doesn't run the model, it just displays it in 3D</span>") + elif k[0] == "Fig4K": + button.setToolTip("<span style=\"color:black;\">Builds a cell with spines and a propagating reaction wave</span>") + elif k[0] == "Fig5A (20s)": + button.setToolTip("<span style=\"color:black;\">Illustrates building a panel of multiscale models to test neuronal plasticity in different contexts</span>") + elif k[0] == "Fig5BCD (240s)": + button.setToolTip("<span style=\"color:black;\">Illustrates building a panel of multiscale models to test neuronal plasticity in different contexts</span>") + elif k[0] == "Fig6A (60s)": + button.setToolTip("<span style=\"color:black;\">This LIF network with Ca plasticity is based on: Memory Maintenance in Synapses with Calcium-Based Plasticity in the Presence of Background Activity PLOS Computational Biology, 2014</span>") + elif k[0] == "Reduced6 (200s)": + button.setToolTip("<span style=\"color:black;\">This is the Reduced version of LIF network with Ca plasticity model based on: Memory Maintenance in Synapses with Calcium-Based Plasticity in the Presence of Background Activity PLOS Computational Biology, 2014</span>") + elif k[0] == "Squid": + button.setToolTip("<span style=\"color:black;\">squid Demo</span>") + if k[0] in ["Fig2E","Fig2D (35s)","Fig2C"]: + layout2.addWidget(button) + elif k[0] in ["Fig3B_Gssa","Fig3C_Gsl","Fig3D"]: + layout3.addWidget(button) + elif k[0] in ["Fig4B","Fig4K"]: + layout4.addWidget(button) + elif k[0] in ["Fig5A (20s)","Fig5BCD (240s)"]: + layout5.addWidget(button) + elif k[0] in ["Fig6A (60s)","Reduced6 (200s)"]: + layout6.addWidget(button) + elif k[0] in ["Squid"]: + layout7.addWidget(button) + + if k[0] == "Fig3C_Gsl": + button.clicked.connect(lambda x, script = k[1]: self.run_genesis_script(script,"gsl")) + elif k[0] == "Fig3B_Gssa": + button.clicked.connect(lambda x, script = k[1]: self.run_genesis_script(script,"gssa")) + else: + button.clicked.connect(lambda x, script = k[1]: self.run_python_script(script)) + + layout.addLayout(layout1,0,0) + layout.addLayout(layout2,1,0) + layout.addLayout(layout3,2,0) + layout.addLayout(layout4,3,0) + layout.addLayout(layout5,4,0) + layout.addLayout(layout6,5,0) + layout.addLayout(layout7,6,0) + dialog.setStyleSheet("border:1px solid rgb(0, 0, 0); ") + dialog.setLayout(layout) + + createKineticModelButton.clicked.connect(self.newModelDialogSlot) + loadKineticModelButton.clicked.connect(self.loadModelDialogSlot) + loadNeuronalModelButton.clicked.connect(self.loadModelDialogSlot) + + dialog.show() + freeCursor() + return dialog + + def run_genesis_script(self,filepath,solver): + self.popup.hide() + abspath = os.path.abspath(filepath) + directory, modulename = os.path.split(abspath) + modelName = os.path.splitext(modulename)[0] + ret = loadFile(str(abspath),'%s' %(modelName),solver,merge=False) + self.setPlugin("kkit", ret["model"].path) + self.setCurrentView("run") + widget = self.plugin.view.getSchedulingDockWidget().widget() + widget.runSimulation() + + def run_python_script(self, filepath): + busyCursor() + import subprocess, shlex + t = os.path.abspath(filepath) + directory, filename = os.path.split(t) + p = subprocess.Popen(["python", filename], cwd=directory) + p.wait() + freeCursor() + + def quit(self): + QtGui.qApp.closeAllWindows() + + def handleException(self, t, v, s): + """This handler will show warning messages for error exceptions. Show + info at status bar for non-error exceptions. It will replace + sys.excepthook and has the same signature (except being bound + to this object). + + t : exception type + + v : exception value + + s: traceback object. + + """ + traceback.print_exception(t, v, s) + title = ''.join(traceback.format_exception_only(t, v)) + trace = ''.join(traceback.format_exception(t, v, s)) + if isinstance(v, mexception.MooseInfo): + self.statusBar().showMessage(title, 5000) + elif isinstance(v, mexception.MooseWarning): + QtGui.QMessageBox.warning(self, title, '\n'.join((title, trace))) + else: + QtGui.QMessageBox.critical(self, title, '\n'.join((title, trace))) + + def getPluginNames(self): + """Return pluginNames attribute or create it by retrieving + available plugin names from plugin/list.txt file. + + """ + if self.pluginNames is None: + with open(os.path.join(config.MOOSE_GUI_DIR, + 'plugins', + 'list.txt')) as lfile: + self.pluginNames = [line.strip() for line in lfile] + self.pluginNames = [name for name in self.pluginNames if name] + + return self.pluginNames + + def loadPluginModule(self, name, re=False): + """Load a plugin module by name. + + First check if the plugin is already loaded. If so return the + existing one. Otherwise, search load the plugin as a python + module from {MOOSE_GUI_DIRECTORY}/plugins directory. + + If re is True, the plugin is reloaded. + """ + if (not re) and name in sys.modules: + return sys.modules[name] + fp, pathname, description = imp.find_module(name, [config.MOOSE_PLUGIN_DIR]) + try: + module = imp.load_module(name, fp, pathname, description) + finally: + if fp: + fp.close() + return module + + def getMyDockWidgets(self): + """Return a list of dockwidgets that belong to the top + level. This is needed to keep them separate from those + provided by the plugins. + + Currently we only have shell for this.""" + if not hasattr(self, 'dockWidgets') or self.dockWidgets is None: + self.dockWidgets = {} + dockWidget = QtGui.QDockWidget('Python') + dockWidget.setWidget(self.getShellWidget()) + self.dockWidgets[dockWidget] = True + self.addDockWidget(Qt.Qt.BottomDockWidgetArea, dockWidget) + dockWidget.setVisible(False) + dockWidget = ObjectEditDockWidget('/') + self.dockWidgets[dockWidget] = True + self.objectEditDockWidget = dockWidget + self.addDockWidget(Qt.Qt.RightDockWidgetArea, dockWidget) + dockWidget.setVisible(False) + return self.dockWidgets.keys() + + def getShellWidget(self): + """Create an instance of shell widget. This can be either a + QSciQScintialla widget or a PyCute widget (extends QTextArea) + if the first is not available""" + if not hasattr(self, 'shellWidget') or self.shellWidget is None: + self.shellWidget = get_shell_class()( code.InteractiveInterpreter() + , message='MOOSE version %s' % (moose._moose.__version__) + ) + self.shellWidget.interpreter.runsource('from moose import *') + self.shellWidget.setVisible(False) + return self.shellWidget + + def loadPluginClass(self, name, re=False): + """Load the plugin class from a plugin module. + + A plugin module should have only one subclass of + MoosePluginBase. Otherwise the first such class found will be + loaded. + """ + try: + return self._loadedPlugins[name] + except KeyError: + pluginModule = self.loadPluginModule(name, re=re) + for classname, classobj in inspect.getmembers(pluginModule, inspect.isclass): + if issubclass(classobj, mplugin.MoosePluginBase): + self._loadedPlugins[name] = classobj + # classobj.getEditorView().getCentralWidget().editObject.connect(self.objectEditSlot) + return self._loadedPlugins[name] + raise Exception('No plugin with name: %s' % (name)) + + def setPlugin(self, name, root='/'): + """Set the current plugin to use. + + This - + + 1. sets the `plugin` attribute. + + 2. updates menus by clearing and reinstating menus including + anything provided by the plugin. + + 3. sets the current view to the plugins editor view. + + """ + busyCursor() + for model in self._loadedModels: + if model[0] != root: + self.disableModel(model[0]) + for i in range(0, len(self._loadedModels)): + if self._loadedModels[i][0]== root: + c = moose.Clock('/clock') + compts = moose.wildcardFind(root+'/##[ISA=ChemCompt]') + for simdt in CHEMICAL_SIMULATION_DT_CLOCKS: + c.tickDt[simdt] = self._loadedModels[i][3] + for plotdt in CHEMICAL_PLOT_UPDATE_INTERVAL_CLOCKS: + c.tickDt[plotdt] = self._loadedModels[i][4] + + if compts: + #setCompartmentSolver(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] + neurons = moose.wildcardFind(root + "/model/cells/##[ISA=Neuron]") + for neuron in neurons: + solver = moose.element(neuron.path + "/hsolve") + solver.tick = 7 + for x in moose.wildcardFind( root+'/data/graph#/#' ): + x.tick = 8 + break + + self.plugin = self.loadPluginClass(str(name))(str(root), self) + moose.reinit() + + self.updateMenus() + for action in self.pluginsMenu.actions(): + if str(action.text()) == str(name): + action.setChecked(True) + elif action.isChecked(): + action.setChecked(False) + for subwin in self.mdiArea.subWindowList(): + subwin.close() + + if name != "default" : + self.setCurrentView('editor') + self.setCurrentView('run') + + if name == 'kkit': + self.objectEditDockWidget.objectNameChanged.connect(self.plugin.getEditorView().getCentralWidget().updateItemSlot) + self.objectEditDockWidget.colorChanged.connect(self.plugin.getEditorView().getCentralWidget().updateColorSlot) + + self.setCurrentView('editor') + freeCursor() + return self.plugin + + def updateExistingMenu(self, menu): + """Check if a menu with same title + already exists. If so, update the same and return + True. Otherwise return False. + """ + if not isinstance(menu, QtGui.QMenu): + return False + for action in self.menuBar().actions(): + if menu.title() == action.text(): + # if not action.menu().isEmpty(): + # action.menu().addSeparator() + action.menu().addActions(menu.actions()) + return True + return False + + def updateMenus(self): + """Clear the menubar and reinstate the basic menus. Go + through the menus provided by current plugin and add those to + menubar. + + If a menu provided by a plugin has same name as one of the + core menus, the menu items provided by the plugin are appended + to the existing menu after a separator. + + """ + self.menuBar().clear() + self.getPluginsMenu() + menus = [self.getFileMenu(), + self.getEditMenu(), + self.getViewMenu(), + #self.getRunMenu(), + #self.getConnectMenu(), + self.getHelpMenu()] + for menu in menus: + self.menuBar().addMenu(menu) + + for menu in self.plugin.getMenus(): + if not self.updateExistingMenu(menu): + if not self.menuBar().isEmpty(): + action.menu().addSeparator() + self.menuBar().addMenu(menu) + menus[0].addSeparator() + menus[0].addAction(self.quitAction) + + def updateToolbars(self): + for toolbar in self.toolBars: + self.removeToolBar(toolbar) + self.toolBars = [] + self.toolBars.extend(self.getMyToolBars()) + self.toolBars.extend(self.plugin.getToolBars()) + self.toolBars.extend(self.plugin.getCurrentView().getToolBars()) + if len(self.toolBars): + for toolbar in self.toolBars: + self.addToolBar(toolbar) + toolbar.setVisible(True) + + def switchSubwindowSlot(self, window): + """Change view based on what subwindow `window` is activated.""" + if not window: + return + view = str(window.windowTitle()).partition(':')[0] + self.setCurrentView(view) + + def setCurrentView(self, view): + """Set current view to a particular one: options are 'editor', + 'plot', 'run'. A plugin can provide more views if necessary. + """ + self.plugin.setCurrentView(view) + if view =='run': + #Harsha: This will clear out object editor's objectpath and make it invisible + self.objectEditSlot('/',False) + + targetView = None + newSubWindow = True + widget = self.plugin.getCurrentView().getCentralWidget() + current = self.mdiArea.activeSubWindow() + subwin = None + for subwin in self.mdiArea.subWindowList(): + if subwin.widget() == widget: + newSubWindow = False + break + if newSubWindow: + subwin = self.mdiArea.addSubWindow(widget) + title = widget.modelRoot+'/model' + #subwin.setWindowTitle('%s: %s' % (view, widget.modelRoot)) + subwin.setWindowTitle('%s: %s' % (view, title)) + subwin.setSizePolicy(QtGui.QSizePolicy.Minimum | + QtGui.QSizePolicy.Expanding, + QtGui.QSizePolicy.Minimum | + QtGui.QSizePolicy.Expanding) + subwin.resize(600, 400) + # Make dockwidgets from other views invisible and make those + # from current view visible or add them if not already part of + # main window. + dockWidgets = set([dockWidget for dockWidget in self.findChildren(QtGui.QDockWidget)]) + for dockWidget in dockWidgets: + if dockWidget not in self.dockWidgets: + dockWidget.setVisible(False) + for dockWidget in self.plugin.getCurrentView().getToolPanes(): + if dockWidget not in dockWidgets: + if view == "run": + if dockWidget.windowTitle() == "Scheduling": + self.addDockWidget(Qt.Qt.TopDockWidgetArea, dockWidget) + else: + self.addDockWidget(Qt.Qt.RightDockWidgetArea, dockWidget) + dockWidget.setVisible(True) + subwin.setVisible(True) + self.mdiArea.setActiveSubWindow(subwin) + self.updateMenus() + for menu in self.plugin.getCurrentView().getMenus(): + if not self.updateExistingMenu(menu): + self.menuBar().addMenu(menu) + self.updateToolbars() + return subwin + + def getMyToolBars(self): + self._toolBars = [] + ''' + #Harsha: removing the toolbars (plot,run,edit) from the Gui + if not hasattr(self, 'viewToolBar'): + self.viewToolBar = QtGui.QToolBar('View') + #Harsha:removing plotView from the ToolBar + for t in self.getViewActions(): + if t.text() != "&Plot view": + self.viewToolBar.addAction(t) + #self.viewToolBar.addActions(self.getViewActions()) + #return [self.viewToolBar] + ''' + return self._toolBars + + def getFileMenu(self): + if self.fileMenu is None: + self.fileMenu = QtGui.QMenu('&File') + else: + self.fileMenu.clear() + + if not hasattr(self, 'newModelAction'): + self.newModelAction = QtGui.QAction('New', self) + self.newModelAction.setShortcut(QtGui.QApplication.translate("MainWindow", "Ctrl+N", None, QtGui.QApplication.UnicodeUTF8)) + self.connect(self.newModelAction, QtCore.SIGNAL('triggered()'), self.newModelDialogSlot) + self.fileMenu.addAction(self.newModelAction) + if not hasattr(self, 'loadModelAction'): + self.loadModelAction = QtGui.QAction('L&oad model', self) + self.loadModelAction.setShortcut(QtGui.QApplication.translate("MainWindow", "Ctrl+O", None, QtGui.QApplication.UnicodeUTF8)) + self.connect(self.loadModelAction, QtCore.SIGNAL('triggered()'), self.loadModelDialogSlot) + self.fileMenu.addAction(self.loadModelAction) + + if not hasattr(self, 'Paper_2015'): + self.menuitems = OrderedDict([ + ("Fig2C (6s)" , "../moose-examples/paper-2015/Fig2_elecModels/Fig2C.py"), + ("Fig2D (35s)", "../moose-examples/paper-2015/Fig2_elecModels/Fig2D.py"), + ("Fig2E (5s)" , "../moose-examples/paper-2015/Fig2_elecModels/Fig2E.py"), + ("Fig3B_Gssa (2s)", "../moose-examples/paper-2015/Fig3_chemModels/Fig3ABC.g"), + ("Fig3C_Gsl (2s)", "../moose-examples/paper-2015/Fig3_chemModels/Fig3ABC.g"), + ("Fig3D (1s)", "../moose-examples/paper-2015/Fig3_chemModels/Fig3D.py"), + ("Fig4B (10s)", "../moose-examples/paper-2015/Fig4_ReacDiff/Fig4B.py" ), + ("Fig4K", "../moose-examples/paper-2015/Fig4_ReacDiff/rxdSpineSize.py"), + ("Fig5A (20s)", "../moose-examples/paper-2015/Fig5_CellMultiscale/Fig5A.py"), + ("Fig5BCD (240s)" , "../moose-examples/paper-2015/Fig5_CellMultiscale/Fig5BCD.py"), + ("Fig6A (60s)", "../moose-examples/paper-2015/Fig6_NetMultiscale/Fig6A.py" ), + ("Reduced6 (200s)", "../moose-examples/paper-2015/Fig6_NetMultiscale/ReducedModel.py"), + ("Squid" , "../moose-examples/squid/squid_demo.py") + ]) + self.subMenu = QtGui.QMenu('Paper_2015_Demos') + for i in range(0,len(self.menuitems)): + k = self.menuitems.popitem(0) + t = "self."+k[0]+"Action" + t = QtGui.QAction(k[0],self) + self.subMenu.addAction(t) + if k[0] == "Fig3C_Gsl (2s)": + t.connect(t,QtCore.SIGNAL('triggered()'),lambda script = k[1]: self.run_genesis_script(script,"gsl")) + elif k[0] == "Fig3B_Gssa (2s)": + t.connect(t,QtCore.SIGNAL('triggered()'),lambda script = k[1]: self.run_genesis_script(script,"gssa")) + else: + t.connect(t,QtCore.SIGNAL('triggered()'),lambda : self.run_python_script(k[1])) + self.subMenu.addAction(t) + self.fileMenu.addMenu(self.subMenu) + + if not hasattr(self,'loadedModels'): + self.loadedModelAction = QtGui.QAction('Recently Loaded Models',self) + self.loadedModelAction.setCheckable(False) + #self.fileMenu.addAction(QtGui.QAction(self.loadedModelAction,checkable=True)) + if bool(self._loadedModels): + self.fileMenu.addSeparator() + self.fileMenu.addAction(self.loadedModelAction) + self.loadedModelAction.setEnabled(False) + for (model, modeltype, action,simdt,plotdt) in reversed(self._loadedModels): + self.fileMenu.addAction(action) + self.fileMenu.addSeparator() + + if not hasattr(self,'connectBioModelAction'): + self.connectBioModelAction = QtGui.QAction('&Connect BioModels', self) + self.connectBioModelAction.setShortcut(QtGui.QApplication.translate("MainWindow", "Ctrl+B", None, QtGui.QApplication.UnicodeUTF8)) + self.connect(self.connectBioModelAction, QtCore.SIGNAL('triggered()'), self.connectBioModel) + self.fileMenu.addAction(self.connectBioModelAction) + return self.fileMenu + + def getEditMenu(self): + if self.editMenu is None: + self.editMenu = QtGui.QMenu('&Edit') + else: + self.editMenu.clear() + #self.editMenu.addActions(self.getEditActions()) + return self.editMenu + + def getPluginsMenu(self): + """Populate plugins menu if it does not exist already.""" + if (not hasattr(self, 'pluginsMenu')) or (self.pluginsMenu is None): + self.pluginsMenu = QtGui.QMenu('&Plugins') + mapper = QtCore.QSignalMapper(self) + pluginsGroup = QtGui.QActionGroup(self) + pluginsGroup.setExclusive(True) + for pluginName in self.getPluginNames(): + action = QtGui.QAction(pluginName, self) + action.setObjectName(pluginName) + action.setCheckable(True) + mapper.setMapping(action, QtCore.QString(pluginName)) + self.connect(action, QtCore.SIGNAL('triggered()'), mapper, QtCore.SLOT('map()')) + self.pluginsMenu.addAction(action) + pluginsGroup.addAction(action) + self.connect(mapper, QtCore.SIGNAL('mapped(const QString &)'), self.setPlugin) + #self.pluginsMenu.addMenu(self.defaultPluginMenu) + #self.pluginsMenu.addMenu(self.kkitPluginMenu) + #self.pluginsMenu.addMenu(self.neurokitPluginMenu) + #openRootAction = self.defaultPluginMenu.addAction("/") + #openRootAction.triggered.connect(lambda : self.setPlugin("default", "/") ) + # if (not hasattr(self, 'loadedModelAction')) or (self.loadedModelAction is None) : + # self.loadedModelAction = QtGui.QAction("kkit",self) + # self.loadedModelAction.addMenu('test') + # self.pluginsMenu.addAction(self.loadedModelAction) + # self.pluginsMenu.addMenu(self.insertkkitMenu) + # self.insertMapperkkit = QtCore.QSignalMapper(self) + #insertMapperkkit,actions = self.getInsertkkitActions(self.loadedModels) + # ignored_bases = ['ZPool', 'Msg', 'Panel', 'SolverBase', 'none'] + # ignored_classes = ['ZPool','ZReac','ZMMenz','ZEnz','CplxEnzBase'] + # classlist = [ch[0].name for ch in moose.element('/classes').children + # if (ch[0].baseClass not in ignored_bases) + # and (ch[0].name not in (ignored_bases + ignored_classes)) + # and not ch[0].name.startswith('Zombie') + # and not ch[0].name.endswith('Base') + # ] + # insertMapper, actions = self.getInsertActions(classlist) + # for action in actions: + # self.insertMenu.addAction(action) + # self.connect(insertMapper, QtCore.SIGNAL('mapped(const QString&)'), self.tree.insertElementSlot) + # self.editAction = QtGui.QAction('Edit', self.treeMenu) + # self.editAction.triggered.connect(self.editCurrentObjectSlot) + # self.tree.elementInserted.connect(self.elementInsertedSlot) + # self.treeMenu.addAction(self.editAction) + return self.pluginsMenu + + def getHelpMenu(self): + if self.helpMenu is None: + self.helpMenu = QtGui.QMenu('&Help') + else: + self.helpMenu.clear() + self.helpMenu.addActions(self.getHelpActions()) + return self.helpMenu + ''' + def getConnectMenu(self): + if self.connectMenu is None: + self.connectMenu = QtGui.QMenu('&Connect') + else: + self.connectMenu.clear() + self.connectMenu.addActions(self.getConnectActions()) + return self.connectMenu + ''' + def getViewMenu(self): + if (not hasattr(self, 'viewMenu')) or (self.viewMenu is None): + self.viewMenu = QtGui.QMenu('&View') + else: + self.viewMenu.clear() + self.viewMenu.addActions(self.getViewActions()) + self.docksMenu = self.viewMenu.addMenu('&Dock widgets') + self.docksMenu.addActions(self.getDockWidgetsToggleActions()) + self.subWindowMenu = self.viewMenu.addMenu('&Subwindows') + self.subWindowMenu.addActions(self.getSubWindowActions()) + return self.viewMenu + + # def getSubWindowVisibilityActions(self): + # if not hasattr(self, 'subwindowToToggles'): + # self.subWindowToToggle = QtGui.QSignalMapper() + # self.toggleToSubWindow = QtGui.QSignalMapper() + # for subwindow in self.mdiArea.subWindowList(): + # if self.subWindowToToggle.mapping(subwindow) is None: + # action = QtGui.QAction('Show: %s' % (subwindow.windowTitle), self) + # self.toggleToSubWindow.setMapping(action, subwindow) + # self.connect(action, QtCore.SIGNAL('triggered()'), + # self.toggleToSubWindow, + # QtCore.SLOT('mapped(QWidget*)')) + # self.subWindowToToggle.setMapping(subwindow, action) + # self.connect(subwindow, QtCore.SIGNAL('closed()') + + # self.subWindowVisibilityMenu = QtGui.Q + # for subwin in self.mdiArea.subWindowList(): + + # Removed from the menu + # def getRunMenu(self): + # if (not hasattr(self, 'runMenu')) or (self.runMenu is None): + # self.runMenu = QtGui.QMenu('&Run') + # else: + # self.runMenu.clear() + # self.runMenu.addActions(self.getRunActions()) + # return self.runMenu + + def getEditActions(self): + + # self.editActions = [] + # if (not hasattr(self, 'editActions')) or (self.editActions is None): + # self.setModelRootAction = QtGui.QAction('&Set model root', self) + # self.setModelRootAction.triggered.connect(self.showSetModelRootDialog) + # self.setDataRootAction = QtGui.QAction('Set &data root', self) + # self.setDataRootAction.triggered.connect(self.showSetDataRootDialog) + # self.editActions = [self.setModelRootAction, self.setDataRootAction] + # return self.editActions + return None + + def showSetModelRootDialog(self): + root, ok = QtGui.QInputDialog.getText(self, 'Model Root', 'Enter the model root path:', text=moose.element(self.plugin.modelRoot).path) + if not ok: + return + root = str(root) #convert from QString to python str + self.plugin.setModelRoot(root) + for subwin in self.mdiArea.subWindowList(): + if hasattr(subwin.widget(), 'modelRoot'): + subwin.setWindowTitle(root) + + def showSetDataRootDialog(self): + root, ok = QtGui.QInputDialog.getText(self, 'Data Root', 'Enter the data root path:', text=moose.element(self.plugin.dataRoot).path) + if not ok: + return + root = str(root) #convert from QString to python str + self.plugin.setDataRoot(root) + for subwin in self.mdiArea.subWindowList(): + if hasattr(subwin.widget(), 'dataRoot'): + subwin.setWindowTitle(root) + + def getViewActions(self): + if (not hasattr(self, 'viewActions')) or (self.viewActions is None): + self.editorViewAction = QtGui.QAction('&Editor view', self) + self.editorViewAction.triggered.connect(self.openEditorView) + #self.plotViewAction = QtGui.QAction('&Plot view', self) + #self.plotViewAction.triggered.connect(self.openPlotView) + self.runViewAction = QtGui.QAction('&Run view', self) + self.runViewAction.triggered.connect(self.openRunView) + #self.viewActions = [self.editorViewAction, self.plotViewAction, self.runViewAction] + self.viewActions = [self.editorViewAction, self.runViewAction] + return self.viewActions + + def setTabbedView(self): + self.mdiArea.setViewMode(QtGui.QMdiArea.TabbedView) + + def setSubWindowView(self): + self.mdiArea.setViewMode(QtGui.QMdiArea.SubWindowView) + + def getSubWindowActions(self): + if not hasattr(self, 'subWindowActions') or self.subWindowActions is None: + self.tabbedViewAction = QtGui.QAction('&Tabbed view', self) + self.tabbedViewAction.triggered.connect(self.setTabbedView) + self.subWindowViewAction = QtGui.QAction('&SubWindow view', self) + self.subWindowViewAction.triggered.connect(self.setSubWindowView) + self.tileSubWindowsAction = QtGui.QAction('Ti&le subwindows', self) + self.tileSubWindowsAction.triggered.connect(self.mdiArea.tileSubWindows) + self.cascadeSubWindowsAction = QtGui.QAction('&Cascade subwindows', self) + self.cascadeSubWindowsAction.triggered.connect(self.mdiArea.cascadeSubWindows) + self.subWindowActions = [self.tabbedViewAction, + self.subWindowViewAction, + self.tileSubWindowsAction, + self.cascadeSubWindowsAction] + return self.subWindowActions + + def getDockWidgetsToggleActions(self): + """Get a list of actions for toggling visibility of dock + widgets + + """ + return [widget.toggleViewAction() for widget in self.findChildren(QtGui.QDockWidget)] + # Removed form the menu item + # def getRunActions(self): + # if (not hasattr(self, 'runActions')) or \ + # (self.runActions is None): + # self.startAction = QtGui.QAction('Start', self) + # self.startAction.triggered.connect(self.resetAndStartSimulation) + # self.pauseAction = QtGui.QAction('Pause', self) + # self.pauseAction.triggered.connect(self.pauseSimulation) + # self.continueAction = QtGui.QAction('Continue', self) + # self.continueAction.triggered.connect(self.continueSimulation) + # self.runActions = [self.startAction, self.pauseAction, self.continueAction] + # return self.runActions + + def getHelpActions(self): + if (not hasattr(self, 'helpActions')) or (self.helpActions is None): + self.actionAbout = QtGui.QAction('About MOOSE', self) + self.connect(self.actionAbout, QtCore.SIGNAL('triggered()'), self.showAboutMoose) + self.actionBuiltInDocumentation = QtGui.QAction('Built-in documentation', self) + self.connect(self.actionBuiltInDocumentation, QtCore.SIGNAL('triggered()'), self.showBuiltInDocumentation) + self.actionGuiBug = QtGui.QAction('Report gui bug', self) + self.connect(self.actionGuiBug, QtCore.SIGNAL('triggered()'), self.reportGuiBug) + self.actionCoreBug = QtGui.QAction('Report core bug', self) + self.connect(self.actionCoreBug, QtCore.SIGNAL('triggered()'), self.reportCoreBug) + self.helpActions = [self.actionAbout, self.actionBuiltInDocumentation, self.actionCoreBug,self.actionGuiBug] + return self.helpActions + # Removed from the main menu item replace with File menu + # def getConnectActions(self): + # if(not hasattr(self,'connectActions')) or(self.connectActions is None): + # self.actionBioModel = QtGui.QAction('BioModels',self) + # self.connect(self.actionBioModel, QtCore.SIGNAL('triggered()'), self.connectBioModel) + # self.connectActions = [self.actionBioModel] + # return self.connectActions + + def connectBioModel(self): + connecttoBioModel = BioModelsClientWidget() + if connecttoBioModel.exec_(): + pass + filepath = connecttoBioModel.filePath + if filepath: + head, fileName = os.path.split(filepath) + modelName = os.path.splitext(fileName)[0] + pwe = moose.getCwe() + ret = loadFile(str(filepath), '/model/%s' % (modelName), 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._loadedModels.append([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()) + self.loadedModelsAction(ret['model'].path,pluginName) + self.setPlugin(pluginName, ret['model'].path) + + + def showAboutMoose(self): + with open(config.MOOSE_ABOUT_FILE, 'r') as aboutfile: + QtGui.QMessageBox.about(self, 'About MOOSE', ''.join(aboutfile.readlines())) + + def showDocumentation(self, source): + QtGui.QDesktopServices.openUrl(QtCore.QUrl(config.MOOSE_DOC_URL)) + ''' + if not hasattr(self, 'documentationViewer'): + self.documentationViewer = QtGui.QTextBrowser() + self.documentationViewer.setOpenLinks(True) + self.documentationViewer.setOpenExternalLinks(True) + #print " path ",config.settings[config.KEY_DOCS_DIR], os.path.join(config.settings[config.KEY_DOCS_DIR], 'html'), os.path.join(config.settings[config.KEY_DOCS_DIR], 'images') + self.documentationViewer.setSearchPaths([config.settings[config.KEY_DOCS_DIR], + os.path.join(config.settings[config.KEY_DOCS_DIR], 'html'), + os.path.join(config.settings[config.KEY_DOCS_DIR], 'images')]) + self.documentationViewer.setMinimumSize(800, 480) + self.documentationViewer.setSource(QtCore.QUrl(source)) + result = self.documentationViewer.loadResource(QtGui.QTextDocument.HtmlResource, self.documentationViewer.source()) + if not result.isValid(): + QtGui.QMessageBox.warning(self, 'Could not access documentation', 'The link %s could not be accessed' % (source)) + return + self.documentationViewer.setWindowTitle(source) + self.documentationViewer.reload() + self.documentationViewer.setVisible(True) + ''' + def reportGuiBug(self): + QtGui.QDesktopServices.openUrl(QtCore.QUrl(config.MOOSE_GUI_BUG_URL)) + 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 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_(): + 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) + #Harsha: This will clear out object editor's objectpath and make it invisible + self.objectEditSlot('/',False) + + # Harsha: 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' + print 'Loaded model', ret['model'].path + # 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()) + 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)) + + 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 diff --git a/moose-gui/mload.py b/moose-gui/mload.py new file mode 100644 index 0000000000000000000000000000000000000000..fc6432501d023e00f74c2fc68b7b363afb54877f --- /dev/null +++ b/moose-gui/mload.py @@ -0,0 +1,208 @@ +# mload.py --- +# +# Filename: mload.py +# Description: +# Author: +# Maintainer: +# Created: Fri Feb 8 09:38:40 2013 (+0530) +# Version: +# Last-Updated: Wed May 22 12:16:35 2013 (+0530) +# By: subha +# Update #: 213 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# Utility to load models and detect filetype. +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: + +import moose +from moose import neuroml +import mtypes +from mexception import FileLoadError +import posixpath +from os.path import basename +from os.path import splitext +from PyQt4 import QtGui, QtCore, Qt +from plugins.setsolver import * + +def loadGenCsp(target,filename,solver="gsl"): + path = '/'+target + #Harsha: Moving the model under /modelname/model and graphs under /model/graphs. + #This is passed while loading-time which will be easy for setting the stoich path + mpath = '/'+target+'/'+"model" + if moose.exists(mpath): + moose.delete(mpath) + + modelpath1 = moose.Neutral('%s' %(target)) + modelpath = moose.Neutral('%s/%s' %(modelpath1.path,"model")) + model = moose.loadModel(filename, modelpath.path,solver) + + if not moose.exists(modelpath1.path+'/data'): + graphspath = moose.Neutral('%s/%s' %(modelpath1.path,"data")) + dataPath = moose.element(modelpath1.path+'/data') + i =0 + nGraphs = moose.wildcardFind(modelpath.path+'/graphs/##[TYPE=Table2]') + for graphs in nGraphs: + if not moose.exists(dataPath.path+'/graph_'+str(i)): + graphspath = moose.Neutral('%s/%s' %(dataPath.path,"graph_"+str(i))) + else: + graphspath = moose.element(dataPath.path+'/graph_'+str(i)) + moose.move(graphs.path,graphspath) + + if len(nGraphs) > 0: + i = i+1 + + for moregraphs in moose.wildcardFind(modelpath.path+'/moregraphs/##[TYPE=Table2]'): + if not moose.exists(dataPath.path+'/graph_'+str(i)): + graphspath = moose.Neutral('%s/%s' %(dataPath.path,"graph_"+str(i))) + else: + graphspath = moose.element(dataPath.path+'/graph_'+str(i)) + moose.move(moregraphs.path,graphspath) + if moose.exists(modelpath.path+'/info'): + AnnotatorOld = moose.element(modelpath.path+'/info') + AnnotatorNew = moose.Annotator(modelpath1.path+'/info') + AnnotatorNew.runtime = AnnotatorOld.runtime + AnnotatorNew.solver = AnnotatorOld.solver + moose.delete(AnnotatorOld) + moose.delete(modelpath.path+'/graphs') + moose.delete(modelpath.path+'/moregraphs') + return(modelpath1,modelpath1.path) + +def loadFile(filename, target, solver="gsl", merge=True): + print " solver @ loadFile",solver + """Try to load a model from specified `filename` under the element + `target`. + + if `merge` is True, the contents are just loaded at target. If + false, everything is deleted from the parent of target unless the + parent is root. + + Returns + ------- + a dict containing at least these three entries: + + modeltype: type of the loaded model. + + subtype: subtype of the loaded model, None if no specific subtype + + modelroot: root element of the model, None if could not be located - as is the case with Python scripts + """ + num = 1 + newTarget = target + while moose.exists(newTarget): + newTarget = target + "-" + str(num) + num = num + 1 + target = newTarget + istext = True + with open(filename, 'rb') as infile: + istext = mtypes.istextfile(infile) + if not istext: + print 'Cannot handle any binary formats yet' + return None + parent, child = posixpath.split(target) + p = moose.Neutral(parent) + if not merge and p.path != '/': + for ch in p.children: + moose.delete(ch) + try: + modeltype = mtypes.getType(filename) + subtype = mtypes.getSubtype(filename, modeltype) + except KeyError: + raise FileLoadError('Do not know how to handle this filetype: %s' % (filename)) + pwe = moose.getCwe() + #self.statusBar.showMessage('Loading model, please wait') + # app = QtGui.qApp + # app.setOverrideCursor(QtGui.QCursor(Qt.Qt.BusyCursor)) #shows a hourglass - or a busy/working arrow + if modeltype == 'genesis': + if subtype == 'kkit' or subtype == 'prototype': + model,modelpath = loadGenCsp(target,filename,solver) + if moose.exists(moose.element(modelpath).path): + moose.Annotator(moose.element(modelpath).path+'/info').modeltype = "kkit" + else: + print " path doesn't exists" + moose.le(modelpath) + else: + print 'Only kkit and prototype files can be loaded.' + + elif modeltype == 'cspace': + model,modelpath = loadGenCsp(target,filename) + if moose.exists(modelpath): + moose.Annotator((moose.element(modelpath).path+'/info')).modeltype = "cspace" + addSolver(modelpath,'gsl') + + elif modeltype == 'xml': + if subtype == 'neuroml': + popdict, projdict = neuroml.loadNeuroML_L123(filename) + # Circus to get the container of populations from loaded neuroml + for popinfo in popdict.values(): + for cell in popinfo[1].values(): + solver = moose.HSolve(cell.path + "/hsolve") + solver.target = cell.path + # model = cell.parent + # break + # break + + + # Moving model to a new location under the model name + # model name is the filename without extension + + model = moose.Neutral("/" + splitext(basename(filename))[0]) + element = moose.Neutral(model.path + "/model") + if(moose.exists("/cells")) : moose.move("/cells" , element.path) + if(moose.exists("/elec")) : moose.move("/elec" , model.path) + if(moose.exists("/library")): moose.move("/library", model.path) + + # moose.move("cells/", cell.path) + elif subtype == 'sbml': + if target != '/': + if moose.exists(target): + moose.delete(target) + model = moose.readSBML(filename,target,'gsl') + if moose.exists(moose.element(model).path): + moose.Annotator(moose.element(model).path+'/info').modeltype = "sbml" + addSolver(target,'gsl') + else: + raise FileLoadError('Do not know how to handle this filetype: %s' % (filename)) + moose.setCwe(pwe) # The MOOSE loadModel changes the current working element to newly loaded model. We revert that behaviour + + # TODO: check with Aditya how to specify the target for + # neuroml reader + # app.restoreOverrideCursor() + return {'modeltype': modeltype, + 'subtype': subtype, + 'model': model} + + + +# +# mload.py ends here diff --git a/moose-gui/mplot.py b/moose-gui/mplot.py new file mode 100644 index 0000000000000000000000000000000000000000..f198c4b7402e438f4d1b5fa8686bf1e8d09b50af --- /dev/null +++ b/moose-gui/mplot.py @@ -0,0 +1,244 @@ +# mplot.py --- +# +# Filename: mplot.py +# Description: +# Author: +# Maintainer: +# Created: Mon Mar 11 20:24:26 2013 (+0530) +# Version: +# Last-Updated: Wed Jul 3 10:32:35 2013 (+0530) +# By: subha +# Update #: 309 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# Moose plot widget default implementation. This should be rich enough +# to suffice for most purposes. +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: +""" + *TODO* + + 1) Option for default colors, markers, etc. + + 2) Option for configuring number of rows and columns of + subplots. (I think matplotlib grids will be a bit too much to + implement). Problem is this has to be done before actual axes are + created (as far as I know). Idea: can we do something like movable + widgets example in Qt? + + 3) Option for selecting any line or set of lines and change its + configuration (as in dataviz). + + 4) Association between plots and the data source. + + 5) Lots and lots of scipy/numpy/scikits/statsmodels utilities can be added. To + start with, we should have + a)digital filters + b) fft + c) curve fitting + + 6) For (5), think of another layer of plugins. Think of this as a + standalone program. All these facilities should again be + pluggable. We do not want to overwhelm novice users with fancy + machine-learning stuff. They should be made available only on + request. + - There is a proposal for data analysis library by Andrew Davison ... + +""" + + +__author__ = "Subhasis Ray" +import sys +import numpy as np +from PyQt4 import QtGui, QtCore +from PyQt4.Qt import Qt +from matplotlib import mlab +from matplotlib.figure import Figure +from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas +from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar +#from moose import utils +import moose +from PyQt4.QtCore import * + +class CanvasWidget(FigureCanvas): + """Widget to draw plots on. + + This class keep track of all the axes in a dictionary. The key for + an axis is its index number in sequence of creation. + + next_id: The key for the next axis. + + current_id: Key for current axis (anu plotting will happen on + this). + + """ + updateSignal = pyqtSignal() + + def __init__(self, model, graph, index, *args, **kwargs): + self.model = model + self.graph = graph + self.index = index + # QColor(243, 239, 238, 255) + self.figure = Figure(facecolor = '#F3EFEE')#figsize=(1,1)) + FigureCanvas.__init__(self, self.figure, *args, **kwargs) + self.figure.set_canvas(self) + # self.set_xlabel('Time (s)') + # self.set_ylabel('Concentration (mM)') + if len(args) > 0 and isinstance(args[0], QtGui.QWidget): + self.reparent(args[0]) + elif (kwargs is not None) and ('parent' in kwargs): + self.reparent(kwargs['parent']) + #self.setAcceptDrops(True) + # self.setMaximumSize(100, 100) + FigureCanvas.updateGeometry(self) + self.axes = {} + self.next_id = 0 + self.current_id = -1 + tabList = [] + self.addTabletoPlot = '' + self.setAcceptDrops(True) + self.gridMode = False + + def dragEnterEvent(self, event): + if event.mimeData().hasFormat('text/plain'): + event.acceptProposedAction() + + def dragMoveEvent(self, event): + if event.mimeData().hasFormat('text/plain'): + event.acceptProposedAction() + + def eventFilter(self, source, event): + if (event.type() == QtCore.QEvent.Drop): + pass + + def dropEvent(self, event): + """Insert an element of the specified class in drop location""" + + if not event.mimeData().hasFormat('text/plain'): + return + # print " active window ", self.isActiveWindow() + # print "Mouse : ", self.mouse + + # pos = self.mapFromGlobal(QCursor.pos()) + # print "Mouse Position : ", pos + modelRoot, element = event.mimeData().data + if isinstance (element,moose.PoolBase): + tablePath = moose.utils.create_table_path(self.model, self.graph, element, "Conc") + table = moose.utils.create_table(tablePath, element, "Conc","Table2") + # moose.connect(table, 'requestOut', element, 'getConc') + self.updateSignal.emit() + elif isinstance(element, moose.CompartmentBase): + tablePath = moose.utils.create_table_path(self.model, self.graph, element, "Vm") + table = moose.utils.create_table(tablePath, element, "Vm","Table") + self.updateSignal.emit() + else: + QtGui.QMessageBox.question(self, 'Message',"This element's properties cannot be plotted.", QtGui.QMessageBox.Ok) + + def addSubplot(self, rows, cols): + """Add a subplot to figure and set it as current axes.""" + assert(self.next_id <= rows * cols) + axes = self.figure.add_subplot(rows, cols, self.next_id+1) + axes.set_xlabel("Time (s)") + axes.set_ylabel("Concentration (mM)") + axes.set_xlim(left=0.0) + axes.set_ylim(bottom=0.0) + self.axes[self.next_id] = axes + axes.set_title("Graph " + str(self.index + 1)) + self.current_id = self.next_id + self.next_id += 1 + labelList = [] + axes.legend(loc='upper center') + return axes + + def plot(self, *args, **kwargs): + #self.callAxesFn('legend',loc='lower center',bbox_to_anchor=(0.5, -0.03),fancybox=True, shadow=True, ncol=3) + return self.callAxesFn('plot', *args, **kwargs) + + def callAxesFn(self, fname, *args, **kwargs): + """Call any arbitrary function of current axes object.""" + if self.current_id < 0: + self.addSubplot(1,1) + fn = eval('self.axes[self.current_id].%s' % (fname)) + + return fn(*args, **kwargs) + + def resize_event(self, event): + print("Resize event called ", event) + + def toggleGrid(self): + self.gridMode = not self.gridMode + for key in self.axes: + self.axes[key].grid(self.gridMode) + self.draw() + + def setXLimit(self, minX, maxX): + for key in self.axes: + self.axes[key].set_xlim([minX, maxX]) + self.draw() + + +import sys +import os +import config +import unittest + +from PyQt4.QtTest import QTest + +class CanvasWidgetTests(unittest.TestCase): + def setUp(self): + self.app = QtGui.QApplication([]) + QtGui.qApp = self.app + icon = QtGui.QIcon(os.path.join(config.KEY_ICON_DIR,'moose_icon.png')) + self.app.setWindowIcon(icon) + self.window = QtGui.QMainWindow() + self.cwidget = CanvasWidget() + self.window.setCentralWidget(self.cwidget) + self.window.show() + + def testPlot(self): + """Test plot function""" + self.cwidget.addSubplot(1,1) + self.cwidget.plot(np.arange(1000), mlab.normpdf(np.arange(1000), 500, 150)) + + def testCallAxesFn(self): + self.cwidget.addSubplot(1,1) + self.cwidget.callAxesFn('scatter', np.random.randint(0, 100, 100), np.random.randint(0, 100,100)) + + def tearDown(self): + self.app.exec_() + +if __name__ == '__main__': + unittest.main() + +# +# mplot.py ends here diff --git a/moose-gui/mplugin.py b/moose-gui/mplugin.py new file mode 100644 index 0000000000000000000000000000000000000000..c4ea6d054b5df1ffe3591f0233898c5dd8bbbcb1 --- /dev/null +++ b/moose-gui/mplugin.py @@ -0,0 +1,354 @@ +# mplugin.py --- +# +# Filename: mplugin.py +# Description: +# Author: +# Maintainer: +# Created: Tue Oct 2 17:25:41 2012 (+0530) +# Version: +# Last-Updated: Thu Jul 18 10:51:48 2013 (+0530) +# By: subha +# Update #: 297 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# This is to be the base class for all MOOSE GUI plugins. +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: + +from PyQt4 import QtGui,QtCore,Qt +import moose + +class MoosePluginBase(QtCore.QObject): + """Moose GUI plugin base class. + + A GUI plugin for MOOSE should extend MoosePlugin class. It has to + implement the methods described here. + + We keep _toolBars, _menus and _views as protected member + variables. Derived classes should populate/update these according + to their needs. The idea is that if a base class is populating any + of these, those entries are generic enough for the derived classes + to use. So a derived class should append their specific entries to + these lists in stead of overriding the getToolBars(), getMenus() + and getViews() functions. + + """ + modelRootChanged = QtCore.pyqtSignal(object, name='modelRootChanged') + dataRootChanged = QtCore.pyqtSignal(object, name='dataRootChanged') + def __init__(self, root='/', mainwindow=None): + """Create a plugin object whose model is the tree rooted at + `root` and whose widgets will be displayed in `mainwindow`. + + """ + QtCore.QObject.__init__(self, mainwindow) + self._views = [] + self._menus = [] + self._toolBars = [] + self.mainWindow = mainwindow + self.modelRoot = root + self.dataRoot = moose.Neutral('/data').path + + def getPreviousPlugin(self): + """Returns the plugin object that the gui is supposed to + switch to when going to a smaller scale.""" + raise NotImplementedError('method must be reimplemented in subclass') + + def getNextPlugin(self): + """Returns the plugin object that the gui is supposed to + switch to when going to a larger scale.""" + raise NotImplementedError('method must be reimplemented in subclass') + + def getAdjacentPlugins(self): + """Return a list of plugins that are valid transitions from this plugin""" + raise NotImplementedError('method must be reimplemented in subclass') + + def getViews(self): + """Return the view widgets available from this plugin.""" + raise NotImplementedError('method must be reimplemented in subclass') + + def getCurrentView(self): + """Return the current view of this plugin.""" + raise NotImplementedError('method must be reimplemented in subclass') + + def setCurrentView(self, view): + """Set current view (e.g., editor/plot/run). + + Return true if successful, otherwise return False. + """ + if view == 'editor': + self.currentView = self.getEditorView() + elif view == 'plot': + self.currentView = self.getPlotView() + elif view == 'run': + self.currentView = self.getRunView() + else: + return False + return True + + def getMenus(self): + return self._menus + + def getToolBars(self): + return self._toolBars + + # def close(self): + # for view in self._views: + # view.close() + + def getEditorView(self): + raise NotImplementedError('method must be implemented in derived class') + + def getPlotView(self): + raise NotImplementedError('method must be implemented in derived class') + + def getRunView(self): + raise NotImplementedError('method must be implemented in derived class') + + def setModelRoot(self, root): + #print("Default setModelRoot called.") + self.modelRoot = moose.element(root).path + self.getEditorView().getCentralWidget().setModelRoot(self.modelRoot) + self.getPlotView().getCentralWidget().setModelRoot(self.modelRoot) + self.modelRootChanged.emit(self.modelRoot) + + def setDataRoot(self, root): + self.dataRoot = moose.Neutral(root).path + self.getPlotView().setDataRoot(self.dataRoot) + self.dataRootChanged.emit(self.dataRoot) + + +class ViewBase(QtCore.QObject): + """Base class for each view: Editor, Plot, Run. + + A view is a mode in a of a plugin. Each view provides + + a list of toolbars to be displayed on top. + + a list of widgets to be docked on the sides. + + a list of menus to be added to the menubar. + + a central widget to be displayed at the centre of the main window. + + """ + def __init__(self, plugin): + QtCore.QObject.__init__(self, plugin) + self._menus = [] + self._toolPanes = [] + self._toolBars = [] + self._centralWidget = None + self.plugin = plugin + + def getToolPanes(self): + """Return a list of widgets to be displayed as dock widgets.""" + raise NotImplementedError('method must be reimplemented in subclass') + + def getToolBars(self): + """Return list of toolbars for this view.""" + return self._toolBars + + def getMenus(self): + """Return the menus for this view.""" + return self._menus + + def getPreferences(self): + """Return a widget for setting preferences""" + raise NotImplementedError('method must be reimplemented in subclass') + + def getCentralWidget(self): + """Return a widget for central widget of mainwindow.""" + raise NotImplementedError('method must be reimplemented in subclass') + + +class EditorBase(ViewBase): + """Base class for editor view. + + This is the default view of a plugin. It should essentially + display a loaded model in an appropriate visual form. + + It is ultimately intended to allow editing of the model, but that + is not a strict requirement. + + """ + def __init__(self, plugin): + ViewBase.__init__(self, plugin) + + def getToolPanes(self): + return self._toolPanes + + def getLibraryPane(self): + """TODO: display everything under library as a tree""" + raise NotImplementedError('method must be reimplemented in subclass') + + def getSelectionPane(self): + """TODO: provide a widget to apply selection rules""" + raise NotImplementedError('method must be reimplemented in subclass') + + def getOperationsPane(self): + """TODO: provide a widget to apply operations on selected + elements.""" + raise NotImplementedError('method must be reimplemented in subclass') + + +class PlotBase(ViewBase): + """Base class for plot configuration view. + + In each plugin, this should provide utility to setup the plotting + of object fields. This is supposed to be used by intermediate + users. + """ + def __init__(self, *args): + ViewBase.__init__(self, *args) + + def getSelectionPane(self): + """TODO: provide a widget to apply selection rules""" + raise NotImplementedError('method must be reimplemented in subclass') + + def getOperationsPane(self): + """TODO: provide a widget to apply operations on selected + elements.""" + raise NotImplementedError('method must be reimplemented in subclass') + + +class RunBase(ViewBase): + """Base class for runtime view. + + When the simulation runs, this view displays the runtime + visualization and controls for the simulation. + """ + def __init__(self, plugin, *args): + super(RunBase, self).__init__(plugin) + + +class EditorWidgetBase(QtGui.QWidget): + """Base class for central widget displayed in editor view. + + The widget should display the model components in the tree rooted + at `modelRoot` in appropriate visual representation. + + `updateModelView` function should do the actual creation and laying + out of the visual objects. + + Signals: editObject - emitted + with currently selected element's path as argument. Should be + connected to whatever slot is responsible for firing the object + editor in top level. + + + """ + editObject = QtCore.pyqtSignal('PyQt_PyObject') + def __init__(self, *args): + QtGui.QWidget.__init__(self, *args) + self.modelRoot = '/' + self._menus = [] + self._toolBars = [] + self._insertActions = [] + self._insertMapper = None + + def getInsertActions(self, classlist): + """Create actions to be used in menus/toolbars for inserting class + instances. This function needs to be called only once. This + also creates the signal mapping from the insert actions. + + Returns: (mapper, actions) + + mapper is a QSignalMapper and actions is a list of QAction + objects. The triggering of any action in `actions` list causes + the `mapper` to emit a mapped(action-name) signal. This can be + connected to a slot in the editor's slot for inserting + elements. For MooseTreeWidget, this is the insertElement slot + (see default.py and mtree.py). + + """ + if len(self._insertActions) == 0: + self._insertMapper = QtCore.QSignalMapper(self) + for classname in classlist: + action = QtGui.QAction(classname, self) + self._insertMapper.setMapping(action, QtCore.QString(classname)) + self.connect(action, + QtCore.SIGNAL('triggered()'), + self._insertMapper, + QtCore.SLOT('map()')) + doc = moose.element('/classes/%s' % (classname)).docs + doc = doc.split('Description:')[-1].split('Name:')[0].strip() + action.setToolTip(doc) + self._insertActions.append(action) + return self._insertMapper, self._insertActions + + def setModelRoot(self, path): + """Set the root of the model tree to be displayed. + + This calls `updateModelView` which should update the scene to + represent current model tree. + + This function can be a slot for connecting actions that should + cause a change in modelRoot. + + """ + self.modelRoot = path + self.updateModelView() + + def updateModelView(self): + """Update view by going through the model. + + When model root is changed, this function is called. It should + update the scene to represent the current model tree rooted at + modelRoot. + + """ + raise NotImplementedError('must be implemented in derived class.') + + def getMenus(self): + return self._menus + + def getToolBars(self): + return self._toolBars + + def elementInsertedSlot(self, mobj): + self.editObject.emit(mobj.path) + + def objectEditSlot(self, mobj): + """Emits an `editObject(str)` signal with moose element path of currently selected tree item as + argument""" + self.editObject.emit(moose.element(mobj).path) + + def sizeHint(self): + return self.size() + + def getCurrentMobj(self): + raise NotImplementedError('should be reimplemented in subclass') + + + +# +# mplugin.py ends here diff --git a/moose-gui/msearch.py b/moose-gui/msearch.py new file mode 100644 index 0000000000000000000000000000000000000000..63fa809fb396f246f67d2409a325adedc8bd9896 --- /dev/null +++ b/moose-gui/msearch.py @@ -0,0 +1,202 @@ +# msearch.py --- +# +# Filename: msearch.py +# Description: +# Author: +# Maintainer: +# Created: Tue Jun 4 15:10:16 2013 (+0530) +# Version: +# Last-Updated: Thu Jun 6 18:26:02 2013 (+0530) +# By: subha +# Update #: 181 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: +""" +Widget giving access to wildcardFind function in MOOSE + +""" +import sys + +from PyQt4 import QtGui, QtCore +from PyQt4.Qt import Qt + +import moose + +class SearchWidget(QtGui.QWidget): + """Widget to search MOOSE model tree using wildcards. + + SIGNALS: + + executed(list of elements matching search criterion). + + """ + executed = QtCore.pyqtSignal(list, name='executed') + + def __init__(self, *args): + QtGui.QWidget.__init__(self, *args) + layout = QtGui.QVBoxLayout() + self.modeCombo = QtGui.QComboBox() + self.modeCombo.addItem('Basic', QtCore.QVariant(QtCore.QString('basic'))) + self.modeCombo.addItem('Advanced', QtCore.QVariant(QtCore.QString('advanced'))) + self.modeCombo.setCurrentIndex(0) + self.setLayout(layout) + layout.addWidget(self.modeCombo) + layout.addWidget(self.getBasicPanel()) + layout.addWidget(self.getAdvancedPanel()) + self.connect(self.modeCombo, QtCore.SIGNAL('currentIndexChanged(const QString &)'), self.switchModeSlot) + self.switchModeSlot('basic') + self.searchButton = QtGui.QPushButton('Search') + self.searchButton.clicked.connect(self.searchSlot) + layout.addWidget(self.searchButton) + self.__results = [] + + def switchModeSlot(self, text): + basic = (str(text).lower() == 'basic') + self.getBasicPanel().setVisible(basic) + self.getAdvancedPanel().setVisible(not basic) + + def getBasicPanel(self): + """Create a widget for basic level usage.""" + if not hasattr(self, '_basicPanel'): + self._basicPanel = QtGui.QWidget() + self.searchRootEdit = QtGui.QLineEdit() + self.searchRootEdit.returnPressed.connect(self.searchSlot) + self.searchRootLabel = QtGui.QLabel('Search under') + self.typeEdit = QtGui.QLineEdit() + self.typeEdit.returnPressed.connect(self.searchSlot) + self.typeLabel = QtGui.QLabel('for elements of type') + self.fieldEdit = QtGui.QLineEdit() + self.fieldEdit.returnPressed.connect(self.searchSlot) + self.fieldLabel = QtGui.QLabel('or elements with field') + self.comparisonCombo = QtGui.QComboBox() + self.comparisonCombo.addItem('=', QtCore.QVariant(QtCore.QString('='))) + self.comparisonCombo.addItem('<', QtCore.QVariant(QtCore.QString('<'))) + self.comparisonCombo.addItem('>', QtCore.QVariant(QtCore.QString('>'))) + self.comparisonCombo.addItem('<=', QtCore.QVariant(QtCore.QString('<='))) + self.comparisonCombo.addItem('>=', QtCore.QVariant(QtCore.QString('>='))) + self.comparisonCombo.addItem('!=', QtCore.QVariant(QtCore.QString('!='))) + self.valueEdit = QtGui.QLineEdit() + self.valueEdit.returnPressed.connect(self.searchSlot) + self.recurseButton = QtGui.QRadioButton('Search inside children recursively') + self.recurseButton.setChecked(True) + layout = QtGui.QGridLayout() + # layout.setVerticalSpacing(2) + self._basicPanel.setLayout(layout) + layout.addWidget(self.searchRootLabel, 0, 0, 1, 1) + layout.addWidget(self.searchRootEdit, 0, 1, 1, 4) + layout.addWidget(self.typeLabel, 1, 0, 1, 1) + layout.addWidget(self.typeEdit, 1, 1, 1, 4) + layout.addWidget(self.fieldLabel, 2, 0, 1, 1) + layout.addWidget(self.fieldEdit, 2, 1, 1, 1) + layout.addWidget(self.comparisonCombo, 2, 2, 1, 1) + layout.addWidget(self.valueEdit, 2, 3, 1, 2) + layout.addWidget(self.recurseButton, 3, 0, 1, 1) + # layout.addItem(QtGui.QSpacerItem(1,1), 3, 0, 1, 7) + return self._basicPanel + + def getAdvancedPanel(self): + """Create a panel for advanced users who can enter the search string + directly.""" + if not hasattr(self, '_advancedPanel'): + self._advancedPanel = QtGui.QWidget(self) + self._searchEdit = QtGui.QLineEdit() + self._searchEdit.returnPressed.connect(self.searchSlot) + self._searchLabel = QtGui.QLabel('Search string:') + layout = QtGui.QHBoxLayout() + self._advancedPanel.setLayout(layout) + layout.addWidget(self._searchLabel) + layout.addWidget(self._searchEdit) + return self._advancedPanel + + def searchSlot(self): + """Do the search and store the paths of the id's found. The results + can be obtained later with getResults()""" + search_str = '' + if str(self.modeCombo.currentText()).lower() == 'basic': + root = str(self.searchRootEdit.text()).strip() + if len(root) == 0: + root = '/' + search_str += root + if not search_str.endswith('/'): + search_str += '/' + if self.recurseButton.isChecked(): + search_str += '##' + else: + search_str += '#' + type_ = str(self.typeEdit.text()).strip() + if len(type_) > 0: + search_str += '[ISA=%s]' % (type_) + field = str(self.fieldEdit.text()).strip() + if len(field) > 0: + search_str += '[FIELD(%s)' + operator = str(self.comparisonCombo.currentText()) + value = str(self.valueEdit.text()) + search_str += '%s%s]' % (operator, value) + else: + search_str = str(self._searchEdit.text()).strip() + ids = moose.wildcardFind(search_str) + self.__results = [el.path for el in ids] + self.executed.emit(list(self.__results)) + + def getResults(self): + return list(self.__results) + + def setSearchRoot(self, root): + self.searchRootEdit.setText(moose.element(root).path) + +def main(): + """Test main""" + model = moose.Neutral('/model') + moose.loadModel('../Demos/Genesis_files/Kholodenko.g', '/model/Kholodenko') + # tab = moose.element('/model/Kholodenko/graphs/conc1/MAPK_PP.Co') + # print tab + # for t in tab.children: + # print t + app = QtGui.QApplication(sys.argv) + mainwin = QtGui.QMainWindow() + mainwin.setWindowTitle('Model tree test') + wildcardWidget = SearchWidget() + mainwin.setCentralWidget(wildcardWidget) + mainwin.show() + sys.exit(app.exec_()) + + +if __name__ == '__main__': + main() + + +# +# msearch.py ends here diff --git a/moose-gui/mtoolbutton.py b/moose-gui/mtoolbutton.py new file mode 100644 index 0000000000000000000000000000000000000000..c4d72edb31a23050851edf38c5b0fe8696396ad2 --- /dev/null +++ b/moose-gui/mtoolbutton.py @@ -0,0 +1,125 @@ +# mtoolbutton.py --- +# +# Filename: mtoolbutton.py +# Description: Subclass of QToolButton to allow drag and drop +# Author: +# Maintainer: +# Created: Fri Jun 14 14:24:11 2013 (+0530) +# Version: +# Last-Updated: Fri Jun 14 16:28:51 2013 (+0530) +# By: subha +# Update #: 89 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: +import sys +from PyQt4 import QtGui, QtCore +from PyQt4.Qt import Qt + +class MToolButton(QtGui.QToolButton): + """QToolButton subclass with dragEvent reimplemented. It sends the + text of the ToolButton as the mimedata. + + """ + def __init__(self, *args): + QtGui.QToolButton.__init__(self, *args) + self.dragStartPosition = QtCore.QPoint(0,0) + + def mousePressEvent(self, event): + if event.buttons() & Qt.LeftButton: + self.dragStartPosition = event.pos() + + def mouseMoveEvent(self, event): + if not (event.buttons() & Qt.LeftButton): + return + if (event.pos() - self.dragStartPosition).manhattanLength() < QtGui.QApplication.startDragDistance(): + return + drag = QtGui.QDrag(self) + mimeData = QtCore.QMimeData() + mimeData.setText(self.text()) + drag.setMimeData(mimeData) + # print '1111', mimeData.text() + dropAction = drag.exec_(Qt.CopyAction) + + +class MyWidget(QtGui.QTextBrowser): + """Class for testing the drag and drop ability of MToolButton""" + def __init__(self, *args): + QtGui.QTextBrowser.__init__(self, *args) + self.dropCount = 0 + self.setPlainText('Drops: %d' % (self.dropCount)) + self.setAcceptDrops(True) + + + def dragEnterEvent(self, event): + print '2222', event.mimeData().text() + if event.mimeData().hasFormat('text/plain'): + event.acceptProposedAction() + print '3333 accepted ' + + def dragMoveEvent(self, event): + """This must be reimplemented to accept the event in case of + QTextBrowser. Not needed in QWidgets in general.""" + print '4444' + event.acceptProposedAction() + + def dropEvent(self, event): + print '5555', event.mimeData().text() + self.dropCount += 1 + self.setPlainText('`%s` dropped: %d times' % (event.mimeData().text(), self.dropCount)) + event.acceptProposedAction() + QtGui.QTextBrowser.dropEvent(self, event) + +def test_main(): + """Test main: see if drag and drop is working""" + app = QtGui.QApplication(sys.argv) + mainwin = QtGui.QMainWindow() + mainwin.setWindowTitle('MTooButton') + toolbar = QtGui.QToolBar() + mainwin.addToolBar(toolbar) + button = MToolButton() + button.setText('test') + toolbar.addWidget(button) + browser = MyWidget(mainwin) + print browser.acceptDrops() + mainwin.setCentralWidget(browser) + mainwin.show() + sys.exit(app.exec_()) + +if __name__ == '__main__': + test_main() + +# +# mtoolbutton.py ends here diff --git a/moose-gui/mtree.py b/moose-gui/mtree.py new file mode 100644 index 0000000000000000000000000000000000000000..a95a7768e88ca7436b98e93d2d76f5dc3640852c --- /dev/null +++ b/moose-gui/mtree.py @@ -0,0 +1,277 @@ +# mtree.py --- +# +# Filename: mtree.py +# Description: +# Author: Subhasis Ray +# Maintainer: +# Created: Tue May 14 11:51:35 2013 (+0530) +# Version: +# Last-Updated: Fri Jun 14 16:13:08 2013 (+0530) +# By: subha +# Update #: 154 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# Implementation of moose tree widget. This can be used by multiple +# components in the moose gui. +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: + +import sys +from PyQt4 import QtGui, QtCore +from PyQt4.Qt import Qt +import moose + + +class MooseTreeModel(QtCore.QAbstractItemModel): + """Tree model for the MOOSE element tree. + + This is not going to work as the MOOSE tree nodes are + inhomogeneous. The parent of a node is an melement, but the + children of an melement are vec objects. + + Qt can handle only homogeneous tere nodes. + """ + def __init__(self, *args): + super(MooseTreeModel, self).__init__(*args) + self.rootItem = moose.element('/') + + def index(self, row, column, parent): + if not self.hasIndex(row, column, parent): + return QtCore.QModelIndex() + if not parent.isValid(): + parentItem = self.rootItem + else: + parentItem = parent.internalPointer() + childItem = parentItem.children[row] + if childItem.path == '/': + return QtCore.QModelIndex() + return self.createIndex(row, column, childItem) + + def parent(self, index): + if not index.isValid(): + return QtCore.QModelIndex() + childItem = index.internalPointer() + parentItem = childItem.parent() + if parentItem == self.rootItem: + return QtCore.QModelIndex() + return self.createIndex(parentItem.parent.children.index(parentItem), parentItem.getDataIndex(), parentItem) + + def rowCount(self, parent): + if not parent.isValid(): + parentItem = self.rootItem + else: + parentItem = parent.internalPointer() + ret = len(parentItem.children) + return ret + + def columnCount(self, parent): + if parent.isValid(): + return len(parent.internalPointer()) + ret = len(self.rootItem) + return ret + + def data(self, index, role): + if not index.isValid(): + return None + item = index.internalPointer() + return QtCore.QVariant(item[index.column()].name) + + def headerData(self, section, orientation, role=Qt.DisplayRole): + if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: + return QtCore.QVariant('Model Tree') + return None + + def flags(self, index): + if not index.isValid(): + return QtCore.Qt.NoItemFlags + return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable + + +class MooseTreeItem(QtGui.QTreeWidgetItem): + def __init__(self, *args): + QtGui.QTreeWidgetItem.__init__(self, *args) + self.mobj = None + + def setObject(self, element): + self.mobj = moose.element(element) + self.setText(0, QtCore.QString(self.mobj.path.rpartition('/')[-1])) + self.setText(1, QtCore.QString(self.mobj.className)) + #self.setToolTip(0, QtCore.QString('class:' + self.mooseObj_.className)) + + def updateSlot(self): + self.setText(0, QtCore.QString(self.mobj.name)) + + +class MooseTreeWidget(QtGui.QTreeWidget): + """Widget for displaying MOOSE model tree. + + """ + # Author: subhasis ray + # + # Created: Tue Jun 23 18:54:14 2009 (+0530) + # + # Updated for moose 2 and multiscale GUI: 2012-12-06 + # Further updated for pymoose2: Tue May 14 14:35:35 IST 2013 + + # Ignored are elements to be ignored when building the tree + ignored = ['/Msgs', '/classes'] + elementInserted = QtCore.pyqtSignal('PyQt_PyObject') + def __init__(self, *args): + """A tree widget to display model tree in MOOSE. + + Members: + + rootElement: melement + root element for the tree. + + SIGNAL: + + elementInserted(melement) emitted when a new element is inserted. + + """ + QtGui.QTreeWidget.__init__(self, *args) + self.header().hide() + self.rootElement = moose.element('/') + self.odict = {} + self.recreateTree() + + def setupTree(self, obj, parent, odict): + """Recursively setup the tree items. + + Parameters + ---------- + obj: melement + object to be associated with the tree item created. + + parent: MooseTreeItem + parent item of the current tree item + + odict: dict + dictionary to store melement to tree widget item mapping. + + """ + for ii in MooseTreeWidget.ignored: + if obj.path.startswith(ii): + return None + item = MooseTreeItem(parent) + item.setObject(obj) + odict[obj] = item + # TODO: check and verify that this still works with synapses - + # there have been change in API. - Subha, Fri Sep 19 19:04:35 IST 2014 + + for child in obj.children: + ch = child + if child.name in obj.getFieldNames('fieldElementFinfo'): + ch = obj.getField(child.name) + for elm in ch: + self.setupTree(moose.element(elm), item, odict) + return item + + def recreateTree(self, root=None): + """Clears the current tree and recreates the tree. If root is not + specified it uses the current `root` otherwise replaces the + rootElement with specified root element. + + Parameter + --------- + root: str or melement or vec + New root element of the tree. Use current rootElement if `None` + """ + self.clear() + self.odict.clear() + if root is not None: + self.rootElement = moose.element(root) + self.setupTree(self.rootElement, self, self.odict) + self.setCurrentItem(self.rootElement) + self.expandToDepth(0) + + def insertElementSlot(self, class_name): + """Creates an instance of the class class_name and inserts it + under currently selected element in the model tree.""" + # print 'Inserting element ...', class_name + current = self.currentItem() + print 'CLASS NAME:', class_name + self.insertChildElement(current, class_name) + + def insertChildElement(self, item, class_name, name=''): + if len(name) == 0: + name = class_name + path = '%s/%s' % (item.mobj.path, str(name)) + mclassname = 'moose.%s' % (str(class_name)) + mclass = eval(mclassname) + obj = mclass(path) + newitem = MooseTreeItem(item) + newitem.setObject(obj) + item.addChild(newitem) + self.odict[obj] = newitem + self.elementInserted.emit(obj) + + + def setCurrentItem(self, item): + """Overloaded version of QTreeWidget.setCurrentItem + + - adds ability to set item by corresponding moose object. + """ + if isinstance(item, QtGui.QTreeWidgetItem): + QtGui.QTreeWidget.setCurrentItem(self, item) + return + mobj = moose.element(item) + QtGui.QTreeWidget.setCurrentItem(self, self.odict[mobj]) + + def updateItemSlot(self, element): + self.odict[element].updateSlot() + +def main(): + """Test main: load a model and display the tree for it""" + model = moose.Neutral('/model') + moose.loadModel('../Demos/Genesis_files/Kholodenko.g', '/model/Kholodenko') + # tab = moose.element('/model/Kholodenko/graphs/conc1/MAPK_PP.Co') + # print tab + # for t in tab.children: + # print t + app = QtGui.QApplication(sys.argv) + mainwin = QtGui.QMainWindow() + mainwin.setWindowTitle('Model tree test') + tree = MooseTreeWidget() + tree.recreateTree(root='/model/') + mainwin.setCentralWidget(tree) + mainwin.show() + sys.exit(app.exec_()) + + +if __name__ == "__main__": + main() + + +# +# mtree.py ends here diff --git a/moose-gui/mtypes.py b/moose-gui/mtypes.py new file mode 100644 index 0000000000000000000000000000000000000000..9d04c5a2456ada2275dad39ed5fb2574d26abce4 --- /dev/null +++ b/moose-gui/mtypes.py @@ -0,0 +1,245 @@ +# mtypes.py --- +# +# Filename: mtypes.py +# Description: +# Author: +# Maintainer: +# Created: Fri Feb 8 11:29:36 2013 (+0530) +# Version: +# Last-Updated: Tue Mar 1 02:52:35 2016 (-0500) +# By: subha +# Update #: 182 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# Utility to detect the model type in a file +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: + +from __future__ import print_function +import re +import moose + +##!!!!!!!!!!!!!!!!!!!!!!!!!!!! +## !! This was stolen from +## http://eli.thegreenplace.net/2011/10/19/perls-guess-if-file-is-text-or-binary-implemented-in-python/#id2 + +import sys +PY3 = sys.version_info[0] >= 3 + +# A function that takes an integer in the 8-bit range and returns +# a single-character byte object in py3 / a single-character string +# in py2. +# +int2byte = (lambda x: bytes((x,))) if PY3 else chr + +_text_characters = ( + b''.join(int2byte(i) for i in range(32, 127)) + + b'\n\r\t\f\b') + +def istextfile(fileobj, blocksize=512): + """ Uses heuristics to guess whether the given file is text or binary, + by reading a single block of bytes from the file. + If more than 30% of the chars in the block are non-text, or there + are NUL ('\x00') bytes in the block, assume this is a binary file. + + - Originally written by Eli Bendersky from the algorithm used + in Perl: + http://eli.thegreenplace.net/2011/10/19/perls-guess-if-file-is-text-or-binary-implemented-in-python/#id2 + """ + block = fileobj.read(blocksize) + if b'\x00' in block: + # Files with null bytes are binary + return False + elif not block: + # An empty file is considered a valid text file + return True + + # Use translate's 'deletechars' argument to efficiently remove all + # occurrences of _text_characters from the block + nontext = block.translate(None, _text_characters) + return float(len(nontext)) / len(block) <= 0.30 + +## Eli Bendersky till here !! +##!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + +def getType(filename, mode='t'): + """Returns the type of the model in file `filename`. Returns None + if type is not known. + + mode: 'b' for binary, 't' for text. Not used currently. + + """ + mtype = None + msubtype = None + if mode == 't': + for typename, typefunc in list(typeChecks.items()): + if typefunc(filename): + return typename + return None + +def getSubtype(filename, typename): + """Returns what subtype of the specified `typename` is the model file. + None if could not resolve the subtype. + """ + for subtype in subtypes[typename]: + subtypeFunc = subtypeChecks['%s/%s' % (typename, subtype)] + if subtypeFunc(filename): + return subtype + return '' + +# Dictionary of model description types and functions to detect them. +# +# Fri Feb 8 11:07:41 IST 2013 - as of now we only recognize GENESIS .g +# XML .xml extensions +# +# Fri Feb 22 16:29:43 IST 2013 - added .cspace + + + +isCSPACE = lambda x: x.lower().endswith('.cspace') +isGENESIS = lambda x: x.lower().endswith('.g') or x.endswith('.p') +isXML = lambda x: x.lower().endswith('.xml') + +isProto = lambda x: x.lower().endswith('.p') + +import xml.dom.minidom as md + +def isNeuroML(filename): + """Check if a model is in neuroml format. An xml document is + considered a neuroml if the top level element is either + 'networkml', morphml', 'channelml' or 'neuroml'. + + """ + doc = md.parse(filename) + for child in doc.childNodes: + print(child.nodeName, child.nodeType == child.ELEMENT_NODE) + if child.nodeType == child.ELEMENT_NODE and \ + (child.nodeName == 'networkml' or \ + child.nodeName == 'morphml' or \ + child.nodeName == 'channelml'or \ + child.nodeName == 'neuroml'): + return True + return False + +def isSBML(filename): + """Check model in `filename` is in SBML format.""" + doc = md.parse(filename) + for child in doc.childNodes: + if child.nodeType == child.ELEMENT_NODE and \ + child.nodeName == 'sbml': + return True + return False + +def isKKIT(filename): + """Check if `filename` is a GENESIS/KINETIKIT file. + + """ + pattern = re.compile('include\s+kkit') # KKIT files must have "include kkit" statement somewhere + with open(filename, 'r') as infile: + while True: + sentence = '' + contd = False # Flags if we are inside a multi-line entry + line = infile.readline() + if not line: # End of file + return False + line = line.strip() + # print 'read:', line + if line.find('//') == 0: # skip c++ style comment lines + # print 'c++ comment' + continue + # Skip C style multi-line comments + comment_start = line.find('/*') + if comment_start >= 0: + sentence = line[:comment_start] + # print 'cstart', comment_start, sentence + while comment_start >= 0 and line: + # print '#', line + comment_end = line.find('*/') + if comment_end >= 0: + comment_start = -1; + line = line[comment_end+2:] # keep the rest of the line + break + line = infile.readline() + if line: + line = line.strip() + # Keep extending the sentence with next line if current + # line ends with continuation token '\' + if line: + contd = line.endswith('\\') + while line and contd: + sentence += ' ' + line[:-1] + line = infile.readline() + if line: + line = line.strip() + contd = line.endswith('\\') + # if contd turned false, the last line came out of the + # while loop unprocessed + if line: + sentence += ' ' + line + # print '>', sentence + if re.search(pattern, sentence): + return True + return False + +# Mapping model types to functions to check them. These functions +# should take the filename as the single argument and return True or +# False. Define new functions for new model type checks and add them +# here. +typeChecks = { + 'cspace': isCSPACE, + 'genesis': isGENESIS, + 'xml': isXML, +} + +# These are "type/subtype": function maps for checking model subtype +# New model types with subtypes should be added here with +# corresponding checker function. +subtypeChecks = { + 'genesis/kkit': isKKIT, + 'genesis/proto': isProto, + 'xml/neuroml': isNeuroML, + 'xml/sbml': isSBML, +} + +# Mapping types to list of subtypes. +subtypes = { + 'cspace': [], + 'genesis': ['kkit', 'proto'], + 'xml': ['neuroml', 'sbml'], +} + + + +# +# mtypes.py ends here diff --git a/moose-gui/neuroextractor.py b/moose-gui/neuroextractor.py new file mode 100644 index 0000000000000000000000000000000000000000..137a4f3bc81cbe1272a6e1ee24f6e52f46f2851e --- /dev/null +++ b/moose-gui/neuroextractor.py @@ -0,0 +1,59 @@ +import moose + +def model(element): + """Given model root element, extracts morphology + information about all neurons and compartments belonging + to that model + """ + if element.path.endswith("/") : + return morphology(moose.element(element.path + "cells")) + else: + return morphology(moose.element(element.path + "/cells")) + +def morphology(element): + """Given the element containing all neurons, extracts + morphology information from all child elements. + """ + return { "name" : element.name + , "id" : element.path + , "type" : etype(element) + , "neurons" : recurse(element, neuron, moose.Neuron) + } + +def neuron(element): + """Given a neuron element, extracts morphology + information from all child compartment elements. + """ + return element.path, { "name" : element.name + , "id" : element.path + , "object" : element + , "type" : etype(element) + , "compartments" : recurse(element, compartment, moose.CompartmentBase) + } + +def compartment(element): + return element.path, { "name" : element.name + , "object" : element + , "id" : element.path + , "type" : etype(element) + , "proximal" : { "x" : element.x0 + , "y" : element.y0 + , "z" : element.z0 + } + , "distal" : { "x" : element.x + , "y" : element.y + , "z" : element.z + } + , "diameter" : element.diameter + } + +def etype(element): + element_type = element.name.rpartition("_")[0] + if element_type == '': return element.name + return element_type + +def recurse(element, func, classType): + return dict( [ func(child[0]) for child in element.children + if isinstance(child, classType) + ] + ) diff --git a/moose-gui/newmodeldialog.py b/moose-gui/newmodeldialog.py new file mode 100644 index 0000000000000000000000000000000000000000..6b5bf80c61de010528e12983219354ab8815e3e9 --- /dev/null +++ b/moose-gui/newmodeldialog.py @@ -0,0 +1,71 @@ +import os +from PyQt4 import QtGui, QtCore,Qt +import config +from mplugin import MoosePluginBase, EditorBase, EditorWidgetBase, PlotBase, RunBase +import re + +class DialogWidget(QtGui.QDialog): + def __init__(self,parent=None): + QtGui.QWidget.__init__(self, parent) + self.warning = None + self._currentRadioButton ="kkit" + self.layout = QtGui.QGridLayout() + self.modelPathLabel = QtGui.QLabel('Model Name') + self.modelPathEdit = QtGui.QLineEdit('') + self.layout.addWidget(self.modelPathLabel, 0, 0) + self.layout.addWidget(self.modelPathEdit, 0, 1,1,1) + # self.defaultRadio = QtGui.QRadioButton('default') + # #self.defaultRadio.setChecked(True); + # self.kkitRadio = QtGui.QRadioButton('kkit') + # self.kkitRadio.setChecked(True) + # self.defaultRadio.toggled.connect(lambda : self.setcurrentRadioButton('default')) + # self.kkitRadio.toggled.connect(lambda : self.setcurrentRadioButton('kkit')) + # layout.addWidget(self.defaultRadio,2,1) + # layout.addWidget(self.kkitRadio,2,0) + self.hbox = QtGui.QHBoxLayout() + self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok) + self.connect(self.buttonBox, QtCore.SIGNAL('accepted()'), self.validateAccept) + self.hbox.addWidget(self.buttonBox,1) + + self.buttonBox1 = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Cancel) + self.connect(self.buttonBox1, QtCore.SIGNAL('rejected()'), self.Cancel) + self.hbox.addWidget(self.buttonBox1,0) + #self.hbox.setBackgroundColor(Blue) + #self.modelPathEdit.returnPressed.connect(self.validateAccept) + # self.connect(self.buttonBox, QtCore.SIGNAL('rejected()'), self.reject) + #self.hbox.addStretch(1) + self.layout.addLayout(self.hbox,1,1) + self.setLayout(self.layout) + + def Cancel (self): + self.close() + + def validateAccept(self): + text = str(self.modelPathEdit.text()) + self.layout.removeWidget(self.warning) + #replace / to _ + text = text.replace('/','_') + + #print(self.layout.widgets()) + if len(text) == 0: + self.warning = QtGui.QLabel("Model name cannot be empty!") + self.layout.addWidget(self.warning, 1, 0, 1, -1) + elif not re.match("^[a-zA-Z]+.*",text): + self.warning = QtGui.QLabel("Start special characters not allowed!") + self.layout.addWidget(self.warning, 1, 0, 1, -1) + else: + self.accept() + return False + + def getcurrentRadioButton(self): + return self._currentRadioButton + +if __name__ == '__main__': + app =QtGui.QApplication([]) + widget = DialogWidget() + widget.setWindowTitle('New Model') + widget.setMinimumSize(400, 200) + widget.show() + app.exec_() + + diff --git a/moose-gui/objectedit.py b/moose-gui/objectedit.py new file mode 100644 index 0000000000000000000000000000000000000000..4e72565e999b1944accdd3a3b9408bf856419945 --- /dev/null +++ b/moose-gui/objectedit.py @@ -0,0 +1,495 @@ +# objectedit.py --- +# +# Filename: objectedit.py +# Description: +# Author: Subhasis Ray +# Maintainer: +# Created: Wed Jun 30 11:18:34 2010 (+0530) +# Version: +# Last-Updated: Wed Mar 28 14:26:59 2014 (+0530) +# By: Harsha +# Update #: 917 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# This code is for a widget to edit MOOSE objects. We can now track if +# a field is a Value field and make it editable accordingly. There +# seems to be no clean way of determining whether the field is worth +# plotting (without a knowledge of the model/biology there is no way +# we can tell this). But we can of course check if the field is a +# numeric one. +# +# + +# Change log: +# +# Wed Jun 30 11:18:34 2010 (+0530) - Originally created by Subhasis +# Ray, the model and the view +# +# Modified/adapted to dh_branch by Chaitanya/Harsharani +# +# Thu Apr 18 18:37:31 IST 2013 - Reintroduced into multiscale GUI by +# Subhasis +# +# Fri Apr 19 15:05:53 IST 2013 - Subhasis added undo redo +# feature. Create ObjectEditModel as part of ObjectEditView. +# + +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: +import PyQt4 +from PyQt4 import QtCore +from PyQt4 import QtGui +from PyQt4.QtGui import QTextEdit +from PyQt4.QtGui import QWidget +from PyQt4.QtGui import QGridLayout +from PyQt4.QtGui import QVBoxLayout +from PyQt4.QtGui import QSizePolicy +from PyQt4.QtCore import QMargins +from PyQt4.QtGui import QSplitter +import sys +from collections import deque +import traceback + +sys.path.append('../python') +import moose +import defaults +import config +from plugins.kkitUtil import getColor +#these fields will be ignored +extra_fields = ['this', + 'me', + 'parent', + 'path', + 'children', + 'linearSize', + 'objectDimensions', + 'lastDimension', + 'localNumField', + 'pathIndices', + 'msgOut', + 'msgIn', + 'diffConst', + 'speciesId', + 'Coordinates', + 'neighbors', + 'DiffusionArea', + 'DiffusionScaling', + 'x', + 'x0', + 'x1', + 'dx', + 'nx', + 'y', + 'y0', + 'y1', + 'dy', + 'ny', + 'z', + 'z0', + 'z1', + 'dz', + 'nz', + 'coords', + 'isToroid', + 'preserveNumEntries', + # 'numKm', + 'numSubstrates', + 'concK1', + 'meshToSpace', + 'spaceToMesh', + 'surface', + 'method', + 'alwaysDiffuse', + 'numData', + 'numField', + 'valueFields', + 'sourceFields', + 'motorConst', + 'destFields', + 'dt', + 'tick', + 'idValue', + 'index', + 'fieldIndex' + ] + + +class ObjectEditModel(QtCore.QAbstractTableModel): + """Model class for editing MOOSE elements. This is not to be used + directly, except that its undo and redo slots should be connected + to by the GUI actions for the same. + + SIGNALS: + + objectNameChanged(PyQt_PyObject): when a moose object's name is + changed, this signal is emitted with the object as argument. This + can be captured by widgets that display the object name. + + dataChanged: emitted when any data is changed in the moose object + + """ + objectNameChanged = QtCore.pyqtSignal('PyQt_PyObject') + # dataChanged = QtCore.pyqtSignal('PyQt_PyObject') + def __init__(self, datain, headerdata=['Field','Value'], undolen=100, parent=None, *args): + QtCore.QAbstractTableModel.__init__(self, parent, *args) + self.fieldFlags = {} + self.fields = [] + self.mooseObject = datain + self.headerdata = headerdata + self.undoStack = deque(maxlen=undolen) + self.redoStack = deque(maxlen=undolen) + self.checkState_ = False + + for fieldName in self.mooseObject.getFieldNames('valueFinfo'): + if fieldName in extra_fields : + continue + + value = self.mooseObject.getField(fieldName) + self.fields.append(fieldName) + #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.ReacBase) + or isinstance(self.mooseObject,moose.EnzBase) ) : + self.fields.append("Color") + # self.fields.append("Notes") + flag = QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable + self.fieldFlags[fieldName] = flag + + def rowCount(self, parent): + return len(self.fields) + + def columnCount(self, parent): + return len(self.headerdata) + + def setData(self, index, value, role=QtCore.Qt.EditRole): + if not index.isValid() or index.row () >= len(self.fields) or index.column() != 1: + return False + print(value) + field = self.fields[index.row()] + if (role == QtCore.Qt.CheckStateRole): + if (index.column() == 1): + self.checkState_ = value + return True + + else: + value = str(value.toString()).strip() # convert Qt datastructure to Python string + if len(value) == 0: + return False + if field == "Notes": + field = "notes" + ann = moose.Annotator(self.mooseObject.path+'/info') + oldValue = ann.getField(field) + value = type(oldValue)(value) + ann.setField(field,value) + self.undoStack.append((index,oldValue)) + else: + oldValue = self.mooseObject.getField(field) + value = type(oldValue)(value) + self.mooseObject.setField(field, value) + self.undoStack.append((index, oldValue)) + if field == 'name': + self.emit(QtCore.SIGNAL('objectNameChanged(PyQt_PyObject)'), self.mooseObject) + return True + + self.dataChanged.emit(index, index) + return True + + def undo(self): + print 'Undo' + if len(self.undoStack) == 0: + raise Info('No more undo information') + index, oldvalue, = self.undoStack.pop() + field = self.fields[index.row()] + currentvalue = self.mooseObject.getField(field) + oldvalue = type(currentvalue)(oldvalue) + self.redoStack.append((index, str(currentvalue))) + self.mooseObject.setField(field, oldvalue) + if field == 'name': + self.objectNameChanged.emit(self.mooseObject) + self.emit(QtCore.SIGNAL('dataChanged(const QModelIndex&, const QModelIndex&)'), index, index) + + def redo(self): + if len(self.redoStack) ==0: + raise Info('No more redo information') + index, oldvalue, = self.redoStack.pop() + currentvalue = self.mooseObject.getField(self.fields[index.row()]) + self.undoStack.append((index, str(currentvalue))) + self.mooseObject.setField(self.fields[index.row()], type(currentvalue)(oldvalue)) + if field == 'name': + self.emit(QtCore.SIGNAL('objectNameChanged(PyQt_PyObject)'), self.mooseObject) + self.emit(QtCore.SIGNAL('dataChanged(const QModelIndex&, const QModelIndex&)'), index, index) + + def flags(self, index): + flag = QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable + #flag = QtCore.Qt.NoItemFlags + if not index.isValid(): + return None + # Replacing the `outrageous` up stuff with something sensible + field = self.fields[index.row()] + newstr = field[0] + newstr = newstr.upper() + field_string = newstr + field[1:] + setter = 'set%s' %(field_string) + #setter = 'set_%s' % (self.fields[index.row()]) + #print " from Object setter",setter, "object",self.mooseObject, " ",self.mooseObject.getFieldNames('destFinfo'); + if index.column() == 1: + # if field == "Color": + # flag = QtCore.Qt.ItemIsEnabled + if field == "Notes": + ann = moose.Annotator(self.mooseObject.path+'/info') + if setter in ann.getFieldNames('destFinfo'): + flag |= QtCore.Qt.ItemIsEditable + + if isinstance(self.mooseObject, moose.PoolBase) or isinstance(self.mooseObject,moose.Function): + if field == 'volume':# or field == 'expr': + pass + elif setter in self.mooseObject.getFieldNames('destFinfo'): + flag |= QtCore.Qt.ItemIsEditable + else: + if setter in self.mooseObject.getFieldNames('destFinfo'): + flag |= QtCore.Qt.ItemIsEditable + + #if field == "Notes": + # flag |= QtCore.Qt.ItemIsEditable + + # !! Replaced till here + + return flag + + def data(self, index, role): + ret = None + field = self.fields[index.row()] + if index.column() == 0 and role == QtCore.Qt.DisplayRole: + try: + ret = QtCore.QVariant(QtCore.QString(field)+' ('+defaults.FIELD_UNITS[field]+')') + except KeyError: + ret = QtCore.QVariant(QtCore.QString(field)) + elif index.column() == 1: + if role==QtCore.Qt.CheckStateRole: + if ((str(field) == "plot Conc") or (str(field) == "plot n") ): + # print index.data(QtCore.Qt. ), str(field) + return self.checkState_ + elif (role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole): + try: + if (str(field) =="Color" ): + return QtGui.QPushButton("Press Me!") + if ( (str(field) != "Notes") and (str(field) != "className")): + ret = self.mooseObject.getField(str(field)) + ret = QtCore.QVariant(QtCore.QString(str(ret))) + elif(str(field) == "className"): + ret = self.mooseObject.getField(str(field)) + if 'Zombie' in ret: + ret = ret.split('Zombie')[1] + ret = QtCore.QVariant(QtCore.QString(str(ret))) + elif(str(field) == "Notes"): + astr = self.mooseObject.path+'/info' + mastr = moose.Annotator(astr) + ret = (mastr).getField(str('notes')) + ret = QtCore.QVariant(QtCore.QString(str(ret))) + except ValueError: + ret = None + return ret + + def headerData(self, col, orientation, role): + if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: + return QtCore.QVariant(self.headerdata[col]) + return QtCore.QVariant() + +class ObjectEditView(QtGui.QTableView): + """View class for object editor. + + This class creates an instance of ObjectEditModel using the moose + element passed as its first argument. + + undolen - specifies the size of the undo stack. By default set to + OBJECT_EDIT_UNDO_LENGTH constant in defaults.py. Specify something smaller if + large number of objects are likely to be edited. + + To enable undo/redo conect the corresponding actions from the gui + to view.model().undo and view.model().redo slots. + """ + def __init__(self, mobject, undolen=defaults.OBJECT_EDIT_UNDO_LENGTH, parent=None): + QtGui.QTableView.__init__(self, parent) + #self.setEditTriggers(self.DoubleClicked | self.SelectedClicked | self.EditKeyPressed) + vh = self.verticalHeader() + vh.setVisible(False) + hh = self.horizontalHeader() + hh.setStretchLastSection(True) + self.setAlternatingRowColors(True) + self.resizeColumnsToContents() + self.setModel(ObjectEditModel(mobject, undolen=undolen)) + self.colorButton = QtGui.QPushButton() + self.colorDialog = QtGui.QColorDialog() + self.textEdit = QTextEdit() + try: + notesIndex = self.model().fields.index("Notes") + self.setIndexWidget(self.model().index(notesIndex,1), self.textEdit) + info = moose.Annotator(self.model().mooseObject.path+'/info') + self.textEdit.setText(QtCore.QString(info.getField('notes'))) + self.setRowHeight(notesIndex, self.rowHeight(notesIndex) * 3) + + # self.colorDialog.colorSelected.connect( + # lambda color: + # + # self.setColor(getColor(self.model().mooseObject.path+'/info')[1]) + except: + pass + + + try: + colorIndex = self.model().fields.index("Color") + self.colorButton.clicked.connect(self.colorDialog.show) + self.colorButton.setFocusPolicy(PyQt4.QtCore.Qt.NoFocus) + self.colorDialog.colorSelected.connect( + lambda color: self.colorButton.setStyleSheet( + "QPushButton {" + + "background-color: {0}; color: {0};".format(color.name()) + + "}" + ) + ) + self.setIndexWidget(self.model().index(colorIndex,1), self.colorButton) + # self.colorDialog.colorSelected.connect( + # lambda color: + # + self.setColor(getColor(self.model().mooseObject.path+'/info')[1]) + except: + pass + print 'Created view with', mobject + + def setColor(self, color): + self.colorButton.setStyleSheet( + "QPushButton {" + + "background-color: {0}; color: {0};".format(color.name()) + + "}" + ) + self.colorDialog.setCurrentColor(color) + + def dataChanged(self, tl, br): + QtGui.QTableView.dataChanged(self, tl, br) + self.viewport().update() + + + +class ObjectEditDockWidget(QtGui.QDockWidget): + """A dock widget whose title is set by the current moose + object. Allows switching the moose object. It stores the created + view in a dict for future use. + + TODO possible performance issue: storing the views (along with + their models) ensures the undo history for each object is + retained. But without a limit on the number of views stored, it + will be wasteful on memory. + + """ + objectNameChanged = QtCore.pyqtSignal('PyQt_PyObject') + colorChanged = QtCore.pyqtSignal(object, object) + def __init__(self, mobj='/', parent=None, flags=None): + QtGui.QDockWidget.__init__(self, parent=parent) + mobj = moose.element(mobj) + #self.view = view = ObjectEditView(mobj) + self.view = view = ObjectEditView(mobj) + self.view_dict = {mobj: view} + base = QWidget() + layout = QVBoxLayout() + base.setLayout(layout) + layout.addWidget(self.view) + layout.addWidget(QTextEdit()) + self.setWidget(base) + self.setWindowTitle('Edit: %s' % (mobj.path)) + # self.view.colorDialog.colorSelected.connect(self.colorChangedEmit) + + + + def setObject(self, mobj): + element = moose.element(mobj) + try: + view = self.view_dict[element] + except KeyError: + view = ObjectEditView(element) + self.view_dict[element] = view + view.model().objectNameChanged.connect(self.emitObjectNameChanged) + view.colorDialog.colorSelected.connect(lambda color: self.colorChanged.emit(element, color)) + textEdit = QTextEdit() + view.setSizePolicy( QSizePolicy.Ignored + , QSizePolicy.Ignored + ) + textEdit.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) + base = QSplitter() + base.setOrientation(PyQt4.QtCore.Qt.Vertical) + layout = QVBoxLayout() + layout.addWidget(view)#, 0, 0) + + if ( isinstance(mobj, moose.PoolBase) + or isinstance(mobj,moose.ReacBase) + or isinstance(mobj,moose.EnzBase) + ) : + info = moose.Annotator(mobj.path +'/info') + textEdit.setText(QtCore.QString(info.getField('notes'))) + textEdit.textChanged.connect(lambda : info.setField('notes', str(textEdit.toPlainText()))) + layout.addWidget(textEdit)#,1,0) + + # self.setRowHeight(notesIndex, self.rowHeight(notesIndex) * 3) + base.setLayout(layout) + # base.setSizes( [ view.height() + # , base.height() - view.height() + # ] + # ) + # print("a =>", view.height()) + # print("b =>", base.height()) + + + # layout.setStretch(0,3) + # layout.setStretch(1,1) + # layout.setContentsMargins(QMargins(0,0,0,0)) + self.setWidget(base) + self.setWindowTitle('Edit: %s' % (element.path)) + view.update() + + def emitObjectNameChanged(self, mobj): + self.objectNameChanged.emit(mobj) + +def main(): + app = QtGui.QApplication(sys.argv) + mainwin = QtGui.QMainWindow() + c = moose.Compartment("test") + view = ObjectEditView(c, undolen=3) + mainwin.setCentralWidget(view) + action = QtGui.QAction('Undo', mainwin) + action.setShortcut('Ctrl+z') + action.triggered.connect(view.model().undo) + mainwin.menuBar().addAction(action) + action = QtGui.QAction('Redo', mainwin) + action.setShortcut('Ctrl+y') + action.triggered.connect(view.model().redo) + mainwin.menuBar().addAction(action) + mainwin.show() + sys.exit(app.exec_()) + + +if __name__ == "__main__": + main() +# ojectedit.py ends here diff --git a/moose-gui/plugins/NeuroKit.py b/moose-gui/plugins/NeuroKit.py new file mode 100644 index 0000000000000000000000000000000000000000..a1fe476c0b11683264cbf68510b747ca62e72d86 --- /dev/null +++ b/moose-gui/plugins/NeuroKit.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +NeuroKit plugin for MOOSE. +""" + +__author__ = "Aviral Goel" +__credits__ = ["Upi Lab"] +__license__ = "GPL3" +__version__ = "1.0.0" +__maintainer__ = "Aviral Goel" +__email__ = "goel.aviral@gmail.com" +__status__ = "Development" + +# import sys +# import config +# import pickle +# import os +# from collections import defaultdict +# import numpy as np +# import re +# from PyQt4 import QtGui, QtCore +# from PyQt4.Qt import Qt +# from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar + +# import moose +# from moose import utils +# import mtree +# from mtoolbutton import MToolButton +# from msearch import SearchWidget +# from checkcombobox import CheckComboBox +import sys +import default +import NeuroKitEditor +import NeuroKitRunner +import mplugin +import moose +from PyQt4.QtGui import QWidget +# import NeuroKitPlotter +# import NeuroKitRunner + +#from defaultToolPanel import DefaultToolPanel + + +class NeuroKit(mplugin.MoosePluginBase): + + """Neurokit plugin for MOOSE GUI""" + + def __init__(self, root, mainwindow): + super(NeuroKit, self).__init__(root, mainwindow) + self._editor = NeuroKitEditor.NeuroKitEditor(self, root) + # self._plotter = NeuroKitPlotter.NeuroKitPlotter(self) + self._runner = NeuroKitRunner.NeuroKitRunner(root, self) + self._current = self._editor + self._views = [ self._editor + , self._runner + # , self._plotter + ] + self._menus = [] + + 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): + return self._editor + + def getPlotView(self): + return self._plotter + + def getRunView(self): + return self._runner + + def getMenus(self): + """Create a custom set of menus.""" + return self._menus diff --git a/moose-gui/plugins/NeuroKitEditor.py b/moose-gui/plugins/NeuroKitEditor.py new file mode 100644 index 0000000000000000000000000000000000000000..a29b3edb025ecfdf632fd49219e83348e9384d85 --- /dev/null +++ b/moose-gui/plugins/NeuroKitEditor.py @@ -0,0 +1,284 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +NeuroKitEditor for NeuroKit plugin. +""" + +__author__ = "Aviral Goel" +__credits__ = ["Upi Lab"] +__license__ = "GPL3" +__version__ = "1.0.0" +__maintainer__ = "Aviral Goel" +__email__ = "goel.aviral@gmail.com" +__status__ = "Development" + +import mplugin +import moose +import pprint +# import NeuroKitEditorWidget +import default + +from PyQt4 import QtGui +from PyQt4 import QtCore +from PyQt4 import Qt +from PyQt4.QtGui import QPushButton +from PyQt4.QtGui import QWidget +from PyQt4.QtGui import QHBoxLayout +from PyQt4.QtGui import QGridLayout +from PyQt4.QtGui import QDialog +from PyQt4.QtGui import QTableWidget +from PyQt4.QtGui import QTableWidgetItem +from PyQt4.QtGui import QCheckBox +from PyQt4.QtGui import QComboBox + +from default import * +from mplugin import * +import moose +import neuroextractor +import moogli +import numpy as np +from global_constants import preferences +from NeuroKitVisualizer import MorphologyEditor + +class NeuroKitEditor(mplugin.EditorBase): + + """ + NeuroKitEditor + """ + + def __init__(self, plugin, modelRoot): + super(NeuroKitEditor, self).__init__(plugin) + self._centralWidget = None #default.DefaultEditorWidget(None) + self.modelRoot = modelRoot + # self._centralWidget = NeuroKitEditorWidget.NeuroKitEditorWidget(modelRoot) + self._menus = [] + # self._propertyTable = MorphologyProperyTable() + self._propertyTable = QWidget() + self.__initMenus() + self.__initToolBars() + self.setModelRoot(modelRoot) + # if hasattr(self._centralWidget, 'init'): + # self._centralWidget.init() + # self._centralWidget.setModelRoot(self.plugin.modelRoot) + # return self._centralWidget + + def __initMenus(self): + return self._menus + # editMenu = QtGui.QMenu('&Edit') + # for menu in self.getCentralWidget().getMenus(): + # editMenu.addMenu(menu) + # self._menus.append(detailsButton) + + def __initToolBars(self): + return self._toolBars + + # for toolbar in self.getCentralWidget().getToolBars(): + # self._toolBars.append(toolbar) + + def getToolPanes(self): + return super(NeuroKitEditor, self).getToolPanes() + + def getLibraryPane(self): + return super(NeuroKitEditor, self).getLibraryPane() + + def getOperationsWidget(self): + return super(NeuroKitEditor, self).getOperationsPane() + + # def getCentralWidget(self): + # """Retrieve or initialize the central widget. + + # Note that we call the widget's setModelRoot() function + # explicitly with the plugin's modelRoot as the argument. This + # enforces an update of the widget display with the current + # modelRoot. + + # This function should be overridden by any derived class as it + # has the editor widget class hard coded into it. + # """ + # self._centralWidget.setModelRoot(self.plugin.modelRoot) + # return self._centralWidget + + def updateModelView(self): + pass + + def setModelRoot(self, path): + self.modelRoot = path + self.updateModelView() + + def setBaseColor(self, color): + self.morphology.set_initial_color( color[0] / 255.0 + , color[1] / 255.0 + , color[2] / 255.0 + , color[3] / 255.0 + ) + + def setPeakColor(self, color): + self.morphology.set_final_color( color[0] / 255.0 + , color[1] / 255.0 + , color[2] / 255.0 + , color[3] / 255.0 + ) + + def setBackgroundColor(self, color): + self.visualizer.set_background_color( color[0] / 255.0 + , color[1] / 255.0 + , color[2] / 255.0 + , color[3] / 255.0 + ) + + def setBaseVm(self, vm): + self.morphology.set_base_membrane_voltage(vm) + + def setPeakVm(self, vm): + self.morphology.set_peak_membrane_voltage(vm) + + + def createCentralWidget(self): + self._centralWidget = default.EditorWidgetBase()#self.modelRoot) + self._centralWidget.setLayout(QHBoxLayout()) + # self.plotWidgetContainer = PlotWidgetContainer(self.modelRoot) + self.geometry = neuroextractor.model(moose.element(self.modelRoot + "/model")) + self.morphology = self.createMorphology(self.geometry) + + self.morphology.set_compartment_order( + map(lambda x : x.path, self.compartmentOrder) + ) + + self.vms = np.empty(len(self.compartmentOrder), dtype=np.float, order='C') + self.ims = np.empty(len(self.compartmentOrder), dtype=np.float, order='C') + # self.visualizer.insertPlainText(pprint.pformat(self.geometry, indent = 4)) + # self.visualizer = QTextEdit()#NeuroKitVisualizer(self.modelRoot) + desktop = QtGui.QApplication.desktop() + # print("**********************") + # print(desktop.screenGeometry()) + # print("***********************") + + self.visualizer = MorphologyEditor( self.morphology + , desktop.screenGeometry().width() + , desktop.screenGeometry().height() + , self.plugin + ) + # self.scheduler = self.getSchedulingDockWidget().widget() + # self._centralWidget.setChildWidget(self.scheduler, False, 0,0,1,-1) + self.visualizer.setGeometry( 0, 0, 1200, 400 ) + self.visualizer.show() + # self.visualizer.start() + self._centralWidget.layout().addWidget(self.visualizer) + # self._centralWidget.setChildWidget(self.visualizer, False, 0, 0,-1,1) + # self._centralWidget.setChildWidget(self.plotWidgetContainer, False, 0, 1,-1,1) + # self._centralWidget.setPlotWidgetContainer(self.plotWidgetContainer) + # label = QLabel("Aviral Goel") + # self._centralWidget.setChildWidget(label, False, 0, 0) + # self._centralWidget.setWindowTitle("Aviral Goel") + # self.scheduler = self.getSchedulingDockWidget().widget() + # self.scheduler.runner.update.connect(self.kkitRunView.getCentralWidget().changeBgSize) + # self.scheduler.runner.resetAndRun.connect(self.kkitRunView.getCentralWidget().resetColor) + + ######################################################## + + # self.schedular = self.getSchedulingDockWidget().widget() + # self.schedular.runner.simulationProgressed.connect(self.update) + # self.schedular.runner.simulationReset.connect(self.reset) + preferences.getView().setCurrentIndex(1) + preferences.getView().electricalBaseColorDialog.colorSelected.connect(lambda x: self.reset()) + preferences.getView().electricalPeakColorDialog.colorSelected.connect(lambda x: self.reset()) + preferences.getView().electricalBackgroundColorDialog.colorSelected.connect(lambda x: self.reset()) + preferences.getView().electricalPeakMembraneVoltage.editingFinished.connect(self.reset) + preferences.getView().electricalBaseMembraneVoltage.editingFinished.connect(self.reset) + + + # print("getting central widget") + # self._centralWidget.show() + # print(self.schedular.runner._updateInterval) + self.reset() + return self._centralWidget + + def update(self, time): + # print("Update called => ", time) + # print("Update called") + # for neuron_id in self.geometry["neurons"]: + # neuron = self.geometry["neurons"][neuron_id] + # for compartment_id in neuron["compartments"]: + # voltage = neuron["compartments"][compartment_id]["object"].Vm + # print(compartment_id + " => " + str(voltage)) + + # self.visualizer. + self.updateVms() + # self.updateIms() + # self.visualizer.next() + # print(self.vms) + + def updateVms(self): + for i in range(0, len(self.compartmentOrder)): + self.vms[i] = self.compartmentOrder[i].Vm + self.morphology.set_membrane_voltages(self.vms) + + def updateIms(self): + for i in range(0, len(self.compartmentOrder)): + self.ims[i] = self.compartmentOrder[i].Im + + def reset(self): + # print(" => reset called") + prefs = preferences.getElectricalPreferences() + self.setPeakColor(prefs["visualization"]["peak-color"]) + self.setBaseColor(prefs["visualization"]["base-color"]) + self.setBackgroundColor(prefs["visualization"]["background-color"]) + self.setBaseVm(prefs["visualization"]["base-membrane-voltage"]) + self.setPeakVm(prefs["visualization"]["peak-membrane-voltage"]) + self.updateVms() + # self.visualizer.next() + # self.updateIms() + # self.ims[i] = self.compartmentOrder[i].Im + # print(self.vms) + # self.morphology.resetVms(self.vms) + # self.morphology.resetIms(self.ims) + + + def createMorphology(self, geometry): + # import json + # f = open("/home/aviral/purkinje.json", "w") + # f.write(json.dumps(geometry, indent=4)) + # f.close() + # morphology = moogli.Morphology("morph") + # morphology.add_compartment( "a" + # , "b", 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0) + # morphology.add_compartment( "c" + # , "b" + # , 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0) + morphology = moogli.Morphology("morph", 1) + self.compartmentOrder = [] + for neuron_id in geometry["neurons"]: + neuron = geometry["neurons"][neuron_id] + for compartment_id in neuron["compartments"]: + compartment = neuron["compartments"][compartment_id] + # print( compartment_id + # , neuron_id + # , compartment["proximal"]["x"] + # , compartment["proximal"]["y"] + # , compartment["proximal"]["z"] + # , compartment["diameter"] + # , compartment["distal"]["x"] + # , compartment["distal"]["y"] + # , compartment["distal"]["z"] + # , compartment["diameter"] + # ) + self.compartmentOrder.append(compartment["object"]) + morphology.add_compartment( compartment_id + , neuron_id + , compartment["proximal"]["x"] * 10000000 + , compartment["proximal"]["y"] * 10000000 + , compartment["proximal"]["z"] * 10000000 + , compartment["diameter"] * 10000000 + , compartment["distal"]["x"] * 10000000 + , compartment["distal"]["y"] * 10000000 + , compartment["distal"]["z"] * 10000000 + , compartment["diameter"] * 10000000 + ) + return morphology + + def getCentralWidget(self): + if self._centralWidget is None: + self.createCentralWidget() + # self._centralWidget.show() + return self._centralWidget diff --git a/moose-gui/plugins/NeuroKitRunner.py b/moose-gui/plugins/NeuroKitRunner.py new file mode 100644 index 0000000000000000000000000000000000000000..9e7f57c7420bf931ed632fa9f26bac4ebd3fb43d --- /dev/null +++ b/moose-gui/plugins/NeuroKitRunner.py @@ -0,0 +1,203 @@ +from mplugin import RunBase +############################################################ +# +# View for running a simulation and runtime visualization +# +############################################################ + + +from mplot import CanvasWidget +import RunWidget +from PlotWidgetContainer import PlotWidgetContainer +from NeuroKitVisualizer import MorphologySimulator +from PyQt4 import QtGui, Qt +from PyQt4.QtGui import QLabel +from PyQt4.QtGui import QWidget +from PyQt4.QtGui import QToolBar +from PyQt4.QtGui import QPushButton +from PyQt4.QtGui import QGridLayout +from PyQt4.QtGui import QTextEdit +import pprint +# from PyQt4.QtGui import QToolBa +from default import * +import moose +import neuroextractor +import moogli +import numpy as np +from global_constants import preferences + + +class NeuroKitRunner(RunView): + + def __init__(self, modelRoot, plugin,*args): + # super(NeuroKitRunner, self).__init__(self, moose.element(modelRoot), plugin, *args) + RunView.__init__(self, modelRoot, plugin, *args) + # RunBase.__init__(self, plugin) + self.modelRoot = modelRoot + self.plugin = plugin + # self.geometry = None + # self.morphology = None + self.schedular = self.getSchedulingDockWidget().widget() + + def setBaseColor(self, color): + self.morphology.set_initial_color( color[0] / 255.0 + , color[1] / 255.0 + , color[2] / 255.0 + , color[3] / 255.0 + ) + + def setPeakColor(self, color): + self.morphology.set_final_color( color[0] / 255.0 + , color[1] / 255.0 + , color[2] / 255.0 + , color[3] / 255.0 + ) + + def setBackgroundColor(self, color): + self.visualizer.set_background_color( color[0] / 255.0 + , color[1] / 255.0 + , color[2] / 255.0 + , color[3] / 255.0 + ) + + def setBaseVm(self, vm): + self.morphology.set_base_membrane_voltage(vm) + + def setPeakVm(self, vm): + self.morphology.set_peak_membrane_voltage(vm) + + + def createCentralWidget(self): + self._centralWidget = RunWidget.RunWidget(self.modelRoot) + self.plotWidgetContainer = PlotWidgetContainer(self.modelRoot) + self.geometry = neuroextractor.model(moose.element(self.modelRoot + "/model")) + self.morphology = self.createMorphology(self.geometry) + + self.morphology.set_compartment_order( + map(lambda x : x.path, self.compartmentOrder) + ) + + self.vms = np.empty(len(self.compartmentOrder), dtype=np.float, order='C') + self.ims = np.empty(len(self.compartmentOrder), dtype=np.float, order='C') + # self.visualizer.insertPlainText(pprint.pformat(self.geometry, indent = 4)) + # self.visualizer = QTextEdit()#NeuroKitVisualizer(self.modelRoot) + self.visualizer = MorphologySimulator(self.morphology, 1000, 1000, self.plugin) + # self.scheduler = self.getSchedulingDockWidget().widget() + # self._centralWidget.setChildWidget(self.scheduler, False, 0,0,1,-1) + self.visualizer.setGeometry( 0, 0, 800, 600 ) + self.visualizer.show() + # self.visualizer.start() + self._centralWidget.setChildWidget(self.visualizer, False, 0, 0,-1,1) + self._centralWidget.setChildWidget(self.plotWidgetContainer, False, 0, 1,-1,1) + self._centralWidget.setPlotWidgetContainer(self.plotWidgetContainer) + # label = QLabel("Aviral Goel") + # self._centralWidget.setChildWidget(label, False, 0, 0) + # self._centralWidget.setWindowTitle("Aviral Goel") + # self.scheduler = self.getSchedulingDockWidget().widget() + # self.scheduler.runner.update.connect(self.kkitRunView.getCentralWidget().changeBgSize) + # self.scheduler.runner.resetAndRun.connect(self.kkitRunView.getCentralWidget().resetColor) + self.schedular = self.getSchedulingDockWidget().widget() + self.schedular.runner.simulationProgressed.connect(self.update) + self.schedular.runner.simulationReset.connect(self.reset) + self.schedular.preferences.getView().setCurrentIndex(1) + self.schedular.preferences.getView().electricalBaseColorDialog.colorSelected.connect(lambda x: self.reset()) + self.schedular.preferences.getView().electricalPeakColorDialog.colorSelected.connect(lambda x: self.reset()) + self.schedular.preferences.getView().electricalBackgroundColorDialog.colorSelected.connect(lambda x: self.reset()) + self.schedular.preferences.getView().electricalPeakMembraneVoltage.editingFinished.connect(self.reset) + self.schedular.preferences.getView().electricalBaseMembraneVoltage.editingFinished.connect(self.reset) + + + # print("getting central widget") + # self._centralWidget.show() + # print(self.schedular.runner._updateInterval) + self.reset() + return self._centralWidget + + def update(self, time): + # print("Update called => ", time) + # print("Update called") + # for neuron_id in self.geometry["neurons"]: + # neuron = self.geometry["neurons"][neuron_id] + # for compartment_id in neuron["compartments"]: + # voltage = neuron["compartments"][compartment_id]["object"].Vm + # print(compartment_id + " => " + str(voltage)) + + # self.visualizer. + self.updateVms() + # self.updateIms() + # self.visualizer.next() + # print(self.vms) + + def updateVms(self): + for i in range(0, len(self.compartmentOrder)): + self.vms[i] = self.compartmentOrder[i].Vm + self.morphology.set_membrane_voltages(self.vms) + + def updateIms(self): + for i in range(0, len(self.compartmentOrder)): + self.ims[i] = self.compartmentOrder[i].Im + + def reset(self): + # print(" => reset called") + prefs = preferences.getElectricalPreferences() + self.setPeakColor(prefs["visualization"]["peak-color"]) + self.setBaseColor(prefs["visualization"]["base-color"]) + self.setBackgroundColor(prefs["visualization"]["background-color"]) + self.setBaseVm(prefs["visualization"]["base-membrane-voltage"]) + self.setPeakVm(prefs["visualization"]["peak-membrane-voltage"]) + self.updateVms() + # self.visualizer.next() + # self.updateIms() + # self.ims[i] = self.compartmentOrder[i].Im + # print(self.vms) + # self.morphology.resetVms(self.vms) + # self.morphology.resetIms(self.ims) + + + def createMorphology(self, geometry): + # import json + # f = open("/home/aviral/purkinje.json", "w") + # f.write(json.dumps(geometry, indent=4)) + # f.close() + # morphology = moogli.Morphology("morph") + # morphology.add_compartment( "a" + # , "b", 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0) + # morphology.add_compartment( "c" + # , "b" + # , 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0) + morphology = moogli.Morphology("morph", 1) + self.compartmentOrder = [] + for neuron_id in geometry["neurons"]: + neuron = geometry["neurons"][neuron_id] + for compartment_id in neuron["compartments"]: + compartment = neuron["compartments"][compartment_id] + # print( compartment_id + # , neuron_id + # , compartment["proximal"]["x"] + # , compartment["proximal"]["y"] + # , compartment["proximal"]["z"] + # , compartment["diameter"] + # , compartment["distal"]["x"] + # , compartment["distal"]["y"] + # , compartment["distal"]["z"] + # , compartment["diameter"] + # ) + self.compartmentOrder.append(compartment["object"]) + morphology.add_compartment( compartment_id + , neuron_id + , compartment["proximal"]["x"] * 10000000 + , compartment["proximal"]["y"] * 10000000 + , compartment["proximal"]["z"] * 10000000 + , compartment["diameter"] * 10000000 + , compartment["distal"]["x"] * 10000000 + , compartment["distal"]["y"] * 10000000 + , compartment["distal"]["z"] * 10000000 + , compartment["diameter"] * 10000000 + ) + return morphology + + def getCentralWidget(self): + if self._centralWidget is None: + self.createCentralWidget() + # self._centralWidget.show() + return self._centralWidget diff --git a/moose-gui/plugins/NeuroKitVisualizer.py b/moose-gui/plugins/NeuroKitVisualizer.py new file mode 100644 index 0000000000000000000000000000000000000000..046df19dba0beb2538f3f3346c7b56fb2acfd517 --- /dev/null +++ b/moose-gui/plugins/NeuroKitVisualizer.py @@ -0,0 +1,161 @@ +from PyQt4 import QtGui, Qt, QtCore +from PyQt4.QtGui import QLabel +from PyQt4.QtGui import QWidget +from PyQt4.QtGui import QToolBar +from PyQt4.QtGui import QPushButton +from PyQt4.QtGui import QGridLayout +from PyQt4.QtGui import QTextEdit +from PyQt4.QtCore import QMimeData +from PyQt4.QtGui import QDrag +from PyQt4.QtGui import QPixmap +from PyQt4.QtGui import QPainter +from PyQt4.QtGui import QFont +from PyQt4.QtCore import QPoint +import moose +import default +import moogli + +class MorphologyEditor(moogli.MorphologyViewer): + + def __init__(self, morphology, width, height, plugin): + super(MorphologyEditor, self).__init__( morphology + , width + , height + ) + self._timer = QtCore.QTimer(self) + self.plugin = plugin + + def start(self): + self._timer.timeout.connect(self.next) + self._timer.start(0) + + @QtCore.pyqtSlot() + def show(self): + self._timer.timeout.connect(self.next) + super(MorphologyEditor, self).show() + self._timer.start(0) + + @QtCore.pyqtSlot() + def hide(self): + self._timer.stop() + super(MorphologyEditor, self).hide() + + def next(self): + self.frame() + info_id = self.select_info.get_id() + info_event = self.select_info.get_event_type() + if info_event == 1: + self.plugin.mainWindow.objectEditSlot(info_id) + self.select_info.set_event_type(0) + +class MorphologySimulator(moogli.MorphologyViewer): + + def __init__(self, morphology, width, height, plugin): + super(MorphologySimulator, self).__init__( morphology + , width + , height + ) + self._timer = QtCore.QTimer(self) + self.plugin = plugin + + def start(self): + self._timer.timeout.connect(self.next) + self._timer.start(0) + + @QtCore.pyqtSlot() + def show(self): + self._timer.timeout.connect(self.next) + super(MorphologySimulator, self).show() + self._timer.start(0) + + @QtCore.pyqtSlot() + def hide(self): + self._timer.stop() + super(MorphologySimulator, self).hide() + + def start_drag(self, info_id): + # pixmap = QPixmap() + # painter = QPainter( pixmap ) + # painter.setFont( QFont("Arial") ); + # painter.drawText( QPoint(100, 100), info_id ); + mimeData = QMimeData() + mimeData.data =("/" + info_id.partition("/")[2].partition("/")[0], moose.element(info_id)) + mimeData.setText(info_id) + drag = QDrag(self) + drag.setMimeData(mimeData) + pixmap = QPixmap("") + + drag.setPixmap(pixmap) + # drag.setHotSpot(e.pos() - self.rect().topLeft()) + dropAction = drag.start(QtCore.Qt.MoveAction) + print(" => ", dropAction) + self.select_info.set_event_type(0) + self._timer.start(0) + return + + def next(self): + self.frame() + info_id = self.select_info.get_id() + info_event = self.select_info.get_event_type() + # print("id => ", info_id) + # print("type => ", info_event) + if info_event == 2: + # self.select_info.set_event_type(-1) + self._timer.stop() + self.start_drag(info_id) + + + +class NeuroKitVisualizer(moogli.MorphologyViewer): + + def __init__(self, modelRoot): + super(NeuroKitVisualizer, self).__init__() + layout = QGridLayout() + self.toolbar = self.createToolbar() + self.textEdit = self.createTextEdit() + layout.addWidget(self.toolbar, 0, 0, 1, -1) + layout.addWidget(self.textEdit, 1, 0, -1, -1) + + def slot_showPointMorphology(self): + """ + This function is called on pressing the detailsButton. + This function will work iff it is invoked by a signal. + The sender() function returns None iff the function is + called explicitly. + """ + detailsButton = self.sender() + detailsButton.clicked.disconnect() # Disconnect all functions + detailsButton.setText("Detailed") + detailsButton.clicked.connect(self.slot_showDetailedMorphology) + print("Write code to show point morphology.") + + def slot_showDetailedMorphology(self): + """ + This function is called on pressing the detailsButton. + This function will work iff it is invoked by a signal. + The sender() function returns None iff the function is + called explicitly. + """ + detailsButton = self.sender() + detailsButton.clicked.disconnect() # Disconnect all functions + detailsButton.setText("Point") + detailsButton.clicked.connect(self.slot_showPointMorphology) + print("Write code to show detailed morphology.") + + + def createTextEdit(self): + textEdit = QTextEdit(self) + textEdit.insertPlainText("Aviral Goel") + + def createToolbar(self): + toolBar = QtGui.QToolBar('Model Settings') + + detailsButton = QPushButton("Detailed") + detailsButton.clicked.connect(self.slot_showDetailedMorphology) + + propertyButton = QPushButton("Property") + # propertyButton.clicked.connect(self._propertyTable.show) + + toolBar.addWidget(detailsButton) + toolBar.addWidget(propertyButton) + return toolBar diff --git a/moose-gui/plugins/PreferencesPresenter.py b/moose-gui/plugins/PreferencesPresenter.py new file mode 100644 index 0000000000000000000000000000000000000000..7b4a368e13b6de13fa024bd2e21c035737c32f22 --- /dev/null +++ b/moose-gui/plugins/PreferencesPresenter.py @@ -0,0 +1,448 @@ +from __future__ import print_function +import sys +from PyQt4 import Qt, QtGui, QtCore +from PyQt4.QtCore import QObject +from PyQt4.QtCore import pyqtSignal +from PyQt4.QtGui import QColor +from PyQt4.QtGui import QGroupBox +from PreferencesView import PreferencesView +import moose +from defines import * +import json +import os + +PREFERENCES_FILEPATH = os.path.join( os.path.dirname(os.path.abspath(__file__)) + , "datastore/preferences.json" + ) + +class PreferencesPresenter(QObject): + + electricalSimulationIntervalChanged = pyqtSignal(float) + electricalPlotUpdateIntervalChanged = pyqtSignal(float) + electricalDefaultSimulationRuntimeChanged = pyqtSignal(float) + electricalDiffusionIntervalChanged = pyqtSignal(float) + electricalGuiUpdateIntervalChanged = pyqtSignal(float) + electricalSolverChanged = None + + chemicalSimulationIntervalChanged = pyqtSignal(float) + chemicalPlotUpdateIntervalChanged = pyqtSignal(float) + chemicalDefaultSimulationRuntimeChanged = pyqtSignal(float) + chemicalDiffusionIntervalChanged = pyqtSignal(float) + chemicalGuiUpdateIntervalChanged = pyqtSignal(float) + chemicalSolverChanged = None + + applyChemicalSettings = pyqtSignal(object) + applyElectricalSettings = pyqtSignal(object) + + def __init__(self, source = PREFERENCES_FILEPATH): + super(PreferencesPresenter, self).__init__() + self.source = source + with open(self.source) as f: + self.preferences = json.loads(f.read()) + + self.view = self.createView() + self.initializeView() + # self.view.closed.connect(self.save) + # self.connectSignals() + # self.connectSlots() + # self.initializeClocks() + self.view.electricalSimulationApply.clicked.connect(self.applyElectricalSimulationSettings) + self.view.electricalSimulationCancel.clicked.connect(self.cancelElectricalSimulationSettings) + self.view.electricalVisualizationApply.clicked.connect(self.applyElectricalVisualizationSettings) + self.view.electricalVisualizationCancel.clicked.connect(self.cancelElectricalVisualizationSettings) + self.view.chemicalSimulationApply.clicked.connect(self.applyChemicalSimulationSettings) + self.view.chemicalSimulationCancel.clicked.connect(self.cancelChemicalSimulationSettings) + + def save(self): + self.getElectricalPreferences() + self.getChemicalPreferences() + # http://stackoverflow.com/questions/12309269/write-json-data-to-file-in-python + with open(self.source, "w") as f: + json.dump( self.preferences + , f + , sort_keys = True + , indent = 4 + , ensure_ascii=False + ) + + def getView(self): + return self.view + + def createView(self): + view = PreferencesView() + return view + + def initializeView(self): + self.setElectricalPreferences() + self.setChemicalPreferences() + + def setElectricalPreferences(self): + self.view.electricalSimulationDt.setText( + str(float(self.preferences["electrical"]["simulation"]["simulation-dt"])) + ) + + self.view.electricalPlotUpdateInterval.setText( + str(float(self.preferences["electrical"]["simulation"]["plot-update-interval"])) + ) + + self.view.electricalDefaultSimulationRuntime.setText( + str(float(self.preferences["electrical"]["simulation"]["default-runtime"])) + ) + + self.view.electricalGuiUpdateInterval.setText( + str(float(self.preferences["electrical"]["simulation"]["gui-update-interval"])) + ) + + self.view.electricalSolvers[str(self.preferences["electrical"]["simulation"]["solver"])].setChecked(True) + + self.view.electricalPeakMembraneVoltage.setText( + str(float(self.preferences["electrical"]["visualization"]["peak-membrane-voltage"])) + ) + + self.view.electricalBaseMembraneVoltage.setText( + str(float(self.preferences["electrical"]["visualization"]["base-membrane-voltage"])) + ) + + (r, g, b, a) = self.preferences["electrical"]["visualization"]["base-color"] + # print((r,g,b,a)) + color = QColor(r, g, b, a) + # print(color.name()) + self.view.electricalBaseColorDialog.setCurrentColor(color) + self.view.electricalBaseColorButton.setStyleSheet( + "QPushButton {" + + "background-color: {0}; color: {0};".format(color.name()) + + "}" + ) + + + (r, g, b, a) = self.preferences["electrical"]["visualization"]["peak-color"] + # print((r,g,b,a)) + color = QColor(r, g, b, a) + # print(color.name()) + self.view.electricalPeakColorDialog.setCurrentColor(QColor(r, g, b, a)) + self.view.electricalPeakColorButton.setStyleSheet( + "QPushButton {" + + "background-color: {0}; color: {0};".format(color.name()) + + "}" + ) + + + (r, g, b, a) = self.preferences["electrical"]["visualization"]["background-color"] + # print((r,g,b,a)) + color = QColor(r, g, b, a) + # print(color.name()) + self.view.electricalBackgroundColorDialog.setCurrentColor(QColor(r, g, b, a)) + self.view.electricalBackgroundColorButton.setStyleSheet( + "QPushButton {" + + "background-color: {0}; color: {0};".format(color.name()) + + "}" + ) + + def setChemicalPreferences(self): + self.view.chemicalSimulationDt.setText( + str(float(self.preferences["chemical"]["simulation"]["simulation-dt"])) + ) + + self.view.chemicalPlotUpdateInterval.setText( + str(float(self.preferences["chemical"]["simulation"]["plot-update-interval"])) + ) + + self.view.chemicalDefaultSimulationRuntime.setText( + str(float(self.preferences["chemical"]["simulation"]["default-runtime"])) + ) + + self.view.chemicalDiffusionDt.setText( + str(float(self.preferences["chemical"]["simulation"]["diffusion-dt"])) + ) + + self.view.chemicalGuiUpdateInterval.setText( + str(float(self.preferences["chemical"]["simulation"]["gui-update-interval"])) + ) + + self.view.chemicalSolvers[str(self.preferences["chemical"]["simulation"]["solver"])].setChecked(True) + + + def connectSignals(self): + self.connectElectricalSignals() + self.connectChemicalSignals() + + def connectElectricalSignals(self): + self.connectIntervalEditorToSignal( self.view.electricalSimulationInterval + , self.electricalSimulationIntervalChanged + ) + + self.connectIntervalEditorToSignal( self.view.electricalPlotUpdateInterval + , self.electricalPlotUpdateIntervalChanged + ) + + self.connectIntervalEditorToSignal( self.view.electricalDefaultSimulationRuntime + , self.electricalDefaultSimulationRuntimeChanged + ) + + self.connectIntervalEditorToSignal( self.view.electricalDiffusionInterval + , self.electricalDiffusionIntervalChanged + ) + + self.connectIntervalEditorToSignal( self.view.electricalGuiUpdateInterval + , self.electricalGuiUpdateIntervalChanged + ) + self.electricalSolverChanged = self.view.electricalSolver.currentIndexChanged + + + def connectChemicalSignals(self): + self.connectFloatinEditorToSignal( self.view.chemicalSimulationInterval + , self.chemicalSimulationIntervalChanged + ) + + self.connectIntervalEditorToSignal( self.view.chemicalPlotUpdateInterval + , self.chemicalPlotUpdateIntervalChanged + ) + + self.connectIntervalEditorToSignal( self.view.chemicalDefaultSimulationRuntime + , self.chemicalDefaultSimulationRuntimeChanged + ) + + self.connectIntervalEditorToSignal( self.view.chemicalDiffusionInterval + , self.chemicalDiffusionIntervalChanged + ) + + self.connectIntervalEditorToSignal( self.view.chemicalGuiUpdateInterval + , self.chemicalGuiUpdateIntervalChanged + ) + + self.chemicalSolverChanged = self.view.chemicalSolver.currentIndexChanged + # self.view.electricalVisualizationApply.connect(self.applyElectricalVisualizationSettings) + # self.view.electricalVisualizationCancel.connect(self.cancelElectricalVisualizationSettings) + + + + def connectIntervalEditorToSignal(self, intervalEditor, signal): + intervalEditor.returnPressed.connect( + lambda: signal.emit(float(intervalEditor.text()))) + intervalEditor.editingFinished.connect( + lambda : signal.emit(float(intervalEditor.text()))) + + def setClocks(self, clocks, dt): + return + for clock in clocks: + moose.setClock(clock, dt) + + def setElectricalSolver(self, solver): + self.view.electricalSolvers[solver].setChecked(True) + + def setChemicalSolver(self, solver): + self.view.chemicalSolvers[solver].setChecked(True) + + def getElectricalPreferences(self): + self.preferences["electrical"]["simulation"]["simulation-dt"] = float(self.view.electricalSimulationDt.text()) + self.preferences["electrical"]["simulation"]["plot-update-interval"] = float(self.view.electricalPlotUpdateInterval.text()) + self.preferences["electrical"]["simulation"]["gui-update-interval"] = float(self.view.electricalGuiUpdateInterval.text()) + self.preferences["electrical"]["simulation"]["default-runtime"] = float(self.view.electricalDefaultSimulationRuntime.text()) + self.preferences["electrical"]["simulation"]["solver"] = str(self.view.electricalSolver.checkedButton().text()) + self.preferences["electrical"]["visualization"]["peak-membrane-voltage"]= float(self.view.electricalPeakMembraneVoltage.text()) + self.preferences["electrical"]["visualization"]["base-membrane-voltage"]= float(self.view.electricalBaseMembraneVoltage.text()) + self.preferences["electrical"]["visualization"]["base-color"] = [ self.view.electricalBaseColorDialog.currentColor().red() + , self.view.electricalBaseColorDialog.currentColor().green() + , self.view.electricalBaseColorDialog.currentColor().blue() + , self.view.electricalBaseColorDialog.currentColor().alpha() + ] + self.preferences["electrical"]["visualization"]["peak-color"] = [ self.view.electricalPeakColorDialog.currentColor().red() + , self.view.electricalPeakColorDialog.currentColor().green() + , self.view.electricalPeakColorDialog.currentColor().blue() + , self.view.electricalPeakColorDialog.currentColor().alpha() + ] + self.preferences["electrical"]["visualization"]["background-color"] = [ self.view.electricalBackgroundColorDialog.currentColor().red() + , self.view.electricalBackgroundColorDialog.currentColor().green() + , self.view.electricalBackgroundColorDialog.currentColor().blue() + , self.view.electricalBackgroundColorDialog.currentColor().alpha() + ] + return self.preferences["electrical"] + + def getChemicalPreferences(self): + self.preferences["chemical"]["simulation"]["simulation-dt"] = float(self.view.chemicalSimulationDt.text()) + self.preferences["chemical"]["simulation"]["diffusion-dt"] = float(self.view.chemicalDiffusionDt.text()) + self.preferences["chemical"]["simulation"]["plot-update-interval"] = float(self.view.chemicalPlotUpdateInterval.text()) + self.preferences["chemical"]["simulation"]["gui-update-interval"] = float(self.view.chemicalGuiUpdateInterval.text()) + self.preferences["chemical"]["simulation"]["default-runtime"] = float(self.view.chemicalDefaultSimulationRuntime.text()) + self.preferences["chemical"]["simulation"]["solver"] = str(self.view.chemicalSolver.checkedButton().text()) + return self.preferences["chemical"] + + # def setElectricalSolver(self): + # neurons = [ child[0] + # for child in moose.element(self.model.path + "/cells") + # if isinstance(child[0], moose.Neuron) + # ] + # for neuron in neurons: + # solver(neuron.path + "/solver") + + # def setChemicalSolver(self): + # pass + + + # def setElectricalClocks(self, dt): + # self.setClocks(1, 7, dt) + + # def setChemicalClocks(self, dt): + # self.setClocks(11, 17, dt) + + # def setDiffusionClocks(self, dt): + # self.setClocks(10, 10, dt) + + # def setClocks(self, dt): + # self.setClocks(10, 10, dt) + + def setChemicalClocks(self): + self.setClocks2(CHEMICAL_SIMULATION_DT_CLOCKS , self.preferences["chemical"]["simulation"]["simulation-dt"]) + self.setClocks2(CHEMICAL_PLOT_UPDATE_INTERVAL_CLOCKS, self.preferences["chemical"]["simulation"]["plot-update-interval"]) + # self.setClocks2(CHEMICAL_DIFFUSION_INTERVAL_CLOCKS, self.preferences["chemical"]["simulation"]["diffusion-dt"]) + + def setClocks2(self, clocks, dt): + for clock in clocks: + moose.setClock(clock, dt) + + def connectSlots(self): + self.connectElectricalSlots() + self.connectChemicalSlots() + + def connectElectricalSlots(self): + self.electricalSimulationIntervalChanged.connect( + lambda dt: self.setClocks(ELECTRICAL_SIMULATION_INTERVAL_CLOCKS, dt)) + self.electricalPlotUpdateIntervalChanged.connect( + lambda dt: self.setClocks(ELECTRICAL_PLOT_UPDATE_INTERVAL_CLOCKS, dt)) + self.electricalDiffusionIntervalChanged.connect( + lambda dt: self.setClocks(ELECTRICAL_DIFFUSION_INTERVAL_CLOCKS, dt)) + self.electricalSimulationIntervalChanged.connect( + lambda dt: self.setValue( self.electricalPreferences + , "simulationInterval" + , dt + )) + self.electricalPlotUpdateIntervalChanged.connect( + lambda dt: self.setValue( self.electricalPreferences + , "plotUpdateInterval" + , dt + )) + self.electricalDefaultSimulationRuntimeChanged.connect( + lambda dt: self.setValue( self.electricalPreferences + , "defaultSimulationRuntime" + , dt + )) + self.electricalDiffusionIntervalChanged.connect( + lambda dt: self.setValue( self.electricalPreferences + , "diffusionInterval" + , dt + )) + self.electricalGuiUpdateIntervalChanged.connect( + lambda dt: self.setValue( self.electricalPreferences + , "guiUpdateInterval" + , dt + )) + self.electricalSolverChanged.connect( + lambda x: self.setValue( self.electricalPreferences + , "solverIndex" + , self.view.electricalSolver.currentIndex() + )) + # self.view.electricalSimulationApply.connect( + # ) + + + def setValue(self, dictionary, key, value): + dictionary[key] = value + + def connectChemicalSlots(self): + self.chemicalSimulationIntervalChanged.connect( + lambda dt: self.setClocks(CHEMICAL_SIMULATION_INTERVAL_CLOCKS, dt)) + self.chemicalPlotUpdateIntervalChanged.connect( + lambda dt: self.setClocks(CHEMICAL_PLOT_UPDATE_INTERVAL_CLOCKS, dt)) + self.chemicalDiffusionIntervalChanged.connect( + lambda dt: self.setClocks(CHEMICAL_DIFFUSION_INTERVAL_CLOCKS, dt)) + self.chemicalSimulationIntervalChanged.connect( + lambda dt: self.setValue( self.chemicalPreferences + , "simulationInterval" + , dt + )) + self.chemicalPlotUpdateIntervalChanged.connect( + lambda dt: self.setValue( self.chemicalPreferences + , "plotUpdateInterval" + , dt + )) + self.chemicalDefaultSimulationRuntimeChanged.connect( + lambda dt: self.setValue( self.chemicalPreferences + , "defaultSimulationRuntime" + , dt + )) + self.chemicalDiffusionIntervalChanged.connect( + lambda dt: self.setValue( self.chemicalPreferences + , "diffusionInterval" + , dt + )) + self.chemicalGuiUpdateIntervalChanged.connect( + lambda dt: self.setValue( self.chemicalPreferences + , "guiUpdateInterval" + , dt + )) + self.chemicalSolverChanged.connect( + lambda dt: self.setValue( self.chemicalPreferences + , "solverIndex" + , self.view.chemicalSolver.currentIndex() + )) + + def initializeClocks(self): + self.initializeElectricalClocks() + self.initializeChemicalClocks() + + def initializeElectricalClocks(self): + self.setClocks( ELECTRICAL_SIMULATION_DT_CLOCKS + , self.preferences["electrical"]["simulation"]["simulation-dt"] + ) + self.setClocks( ELECTRICAL_PLOT_UPDATE_INTERVAL_CLOCKS + , self.preferences["electrical"]["simulation"]["plot-update-interval"] + ) + + def initializeChemicalClocks(self): + self.setClocks( CHEMICAL_SIMULATION_DT_CLOCKS + , self.preferences["chemical"]["simulation"]["simulation-dt"] + ) + self.setClocks( CHEMICAL_DIFFUSION_DT_CLOCKS + , self.preferences["chemical"]["simulation"]["diffusion-dt"] + ) + self.setClocks( CHEMICAL_PLOT_UPDATE_INTERVAL_CLOCKS + , self.preferences["chemical"]["simulation"]["plot-update-interval"] + ) + + def applyElectricalSimulationSettings(self): + self.getElectricalPreferences() + self.view.close() + self.applyElectricalSettings.emit(self.preferences["electrical"]) + + def cancelElectricalSimulationSettings(self): + self.setElectricalPreferences() + self.view.close() + + def applyChemicalSimulationSettings(self): + self.getChemicalPreferences() + self.setChemicalClocks() + self.view.close() + self.applyChemicalSettings.emit(self.preferences["chemical"]) + + def cancelChemicalSimulationSettings(self): + self.setChemicalPreferences() + self.view.close() + + def applyElectricalVisualizationSettings(self): + self.getElectricalPreferences() + self.applyElectricalSettings.emit(self.preferences["electrical"]) + self.view.close() + + def cancelElectricalVisualizationSettings(self): + self.setElectricalPreferences() + self.view.close() + + +def main(): + app = QtGui.QApplication(sys.argv) + preferences = PreferencesPresenter() + preferences.view.show() + sys.exit(app.exec_()) + +if __name__ == "__main__": + main() diff --git a/moose-gui/plugins/PreferencesView.py b/moose-gui/plugins/PreferencesView.py new file mode 100644 index 0000000000000000000000000000000000000000..1699c9ab23784c1228faf8a924ab1ebc9f9e825c --- /dev/null +++ b/moose-gui/plugins/PreferencesView.py @@ -0,0 +1,238 @@ +from __future__ import print_function +import PyQt4 +from PyQt4 import Qt, QtGui, QtCore +from PyQt4.QtCore import pyqtSignal +from PyQt4.QtGui import QWidget +from PyQt4.QtGui import QButtonGroup +from PyQt4.QtGui import QRadioButton +from PyQt4.QtGui import QVBoxLayout +from PyQt4.QtGui import QLabel +from PyQt4.QtGui import QGridLayout +from PyQt4.QtGui import QLineEdit +from PyQt4.QtGui import QDoubleValidator +from PyQt4.QtGui import QComboBox +from PyQt4.QtGui import QTabWidget +from PyQt4.QtGui import QPushButton +from PyQt4.QtGui import QColorDialog +from PyQt4.QtGui import QColor +from PyQt4.QtGui import QSizePolicy +import sys + +class PreferencesView(QTabWidget): + + closed = pyqtSignal() + + def __init__(self, parent = None): + super(PreferencesView, self).__init__(parent) + + self.setWindowTitle("Preferences") + # self.setFixedSize(self.maximumSize()) + # self.setMinimumSize(self.maximumSize()) + # self.setMaximumSize(self.maximumSize()) + + # self.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) + self.chemicalSimulationDt = self.createFloatingPointEditor() + self.chemicalDiffusionDt = self.createFloatingPointEditor() + self.chemicalPlotUpdateInterval = self.createFloatingPointEditor() + self.chemicalDefaultSimulationRuntime = self.createFloatingPointEditor() + self.chemicalGuiUpdateInterval = self.createFloatingPointEditor() + self.chemicalSolver = QButtonGroup() + self.chemicalSolvers = { "Exponential Euler" : QRadioButton("Exponential Euler") + , "Gillespie" : QRadioButton("Gillespie") + , "Runge Kutta" : QRadioButton("Runge Kutta") + } + self.chemicalSimulationApply = QPushButton("Apply") + self.chemicalSimulationCancel = QPushButton("Cancel") + self.electricalSimulationDt = self.createFloatingPointEditor() + self.electricalPlotUpdateInterval = self.createFloatingPointEditor() + self.electricalDefaultSimulationRuntime = self.createFloatingPointEditor() + self.electricalGuiUpdateInterval = self.createFloatingPointEditor() + self.electricalSolver = QButtonGroup() + self.electricalSolvers = { "Gillespie" : QRadioButton("Gillespie") + , "Runge Kutta" : QRadioButton("Runge Kutta") + } + self.electricalSimulationApply = QPushButton("Apply") + self.electricalSimulationCancel = QPushButton("Cancel") + self.electricalVisualizationApply = QPushButton("Apply") + self.electricalVisualizationCancel = QPushButton("Cancel") + self.electricalBaseColorButton = QPushButton() + self.electricalBaseColorDialog = QColorDialog() + self.electricalPeakColorButton = QPushButton() + self.electricalPeakColorDialog = QColorDialog() + self.electricalBackgroundColorButton = QPushButton() + self.electricalBackgroundColorDialog = QColorDialog() + self.electricalBaseMembraneVoltage = self.createFloatingPointEditor() + self.electricalPeakMembraneVoltage = self.createFloatingPointEditor() + + self.create() + + def closeEvent(self, event): + self.closed.emit() + + def create(self): + # Set up the column titles + self.setUsesScrollButtons(True) + self.setFocusPolicy(PyQt4.QtCore.Qt.NoFocus) + self.addTab( self.createChemicalSettingsTab(),"Chemical") + self.addTab( self.createElectricalSettingsTab(),"Electrical") + + def createChemicalSettingsTab(self): + chemicalSettingsTab = QWidget() + layout = QtGui.QGridLayout() + chemicalSettingsTab.setLayout(layout) + + layout.addWidget(QLabel('Simulation dt'), 0, 0) + layout.addWidget(self.chemicalSimulationDt, 0, 1) + + layout.addWidget(QLabel('Diffusion dt'), 1, 0) + layout.addWidget(self.chemicalDiffusionDt, 1, 1) + + layout.addWidget(QLabel('Plot Update Interval'), 2, 0) + layout.addWidget(self.chemicalPlotUpdateInterval, 2, 1) + + layout.addWidget(QLabel('GUI Update Interval'), 3, 0) + layout.addWidget(self.chemicalGuiUpdateInterval, 3, 1) + + # layout.addWidget(QLabel('Default Runtime'), 4, 0) + # layout.addWidget(self.chemicalDefaultSimulationRuntime, 4, 1) + + layout.addWidget(QLabel('Solver'), 5, 0) + + index = 0 + for solver in self.chemicalSolvers: + layout.addWidget(self.chemicalSolvers[solver], 5 + index, 1) + self.chemicalSolver.addButton(self.chemicalSolvers[solver], index) + self.chemicalSolvers[solver].setFocusPolicy(PyQt4.QtCore.Qt.NoFocus) + index += 1 + + self.chemicalSolver.setExclusive(True) + + buttonLayout = QGridLayout() + layout.addLayout(buttonLayout, 5 + index, 1) + buttonLayout.addWidget(self.chemicalSimulationCancel, 0, 0, Qt.Qt.AlignRight) + buttonLayout.addWidget(self.chemicalSimulationApply, 0, 1, Qt.Qt.AlignLeft) + + + return chemicalSettingsTab + + def createElectricalSettingsTab(self): + + electricalSettingsTab = QTabWidget() + electricalSettingsTab.addTab( self.createElectricalSimulationSettingsTab() + , "Simulation" + ) + electricalSettingsTab.addTab( self.createElectricalSimulationVisualizationTab() + , "Visualization" + ) + electricalSettingsTab.setTabPosition(QTabWidget.East) + electricalSettingsTab.setTabShape(QTabWidget.Triangular) + electricalSettingsTab.setDocumentMode(True) + electricalSettingsTab.setUsesScrollButtons(True) + electricalSettingsTab.setFocusPolicy(PyQt4.QtCore.Qt.NoFocus) + return electricalSettingsTab + + def createElectricalSimulationSettingsTab(self): + + widget = QWidget() + layout = QtGui.QGridLayout() + widget.setLayout(layout) + + layout.addWidget(QLabel('Simulation dt'), 0, 0) + layout.addWidget(self.electricalSimulationDt, 0, 1) + + layout.addWidget(QLabel('Plot Update Interval'), 2, 0) + layout.addWidget(self.electricalPlotUpdateInterval, 2, 1) + + layout.addWidget(QLabel('GUI Update Interval'), 3, 0) + layout.addWidget(self.electricalGuiUpdateInterval, 3, 1) + + # layout.addWidget(QLabel('Default Runtime'), 4, 0) + # layout.addWidget(self.electricalDefaultSimulationRuntime, 4, 1) + + # layout.addWidget(QLabel('Solver'), 5, 0) + + index = 0 + for solver in self.electricalSolvers: + # layout.addWidget(self.electricalSolvers[solver], 5 + index, 1) + self.electricalSolver.addButton(self.electricalSolvers[solver], index) + self.electricalSolvers[solver].setFocusPolicy(PyQt4.QtCore.Qt.NoFocus) + index += 1 + + self.electricalSolver.setExclusive(True) + buttonLayout = QGridLayout() + layout.addLayout(buttonLayout, 5 + index, 1) + buttonLayout.addWidget(self.electricalSimulationCancel, 0, 0, Qt.Qt.AlignRight) + buttonLayout.addWidget(self.electricalSimulationApply, 0, 1, Qt.Qt.AlignLeft) + + return widget + + def createElectricalSimulationVisualizationTab(self): + + widget = QWidget() + layout = QtGui.QGridLayout() + widget.setLayout(layout) + + layout.addWidget(QLabel('Base Membrane Voltage'), 1, 0) + layout.addWidget(self.electricalBaseMembraneVoltage, 1, 1) + + layout.addWidget(QLabel('Base Compartment Color'), 2, 0) + self.electricalBaseColorDialog.setOption(QColorDialog.ShowAlphaChannel, True) + layout.addWidget(self.electricalBaseColorButton, 2, 1) + self.electricalBaseColorButton.clicked.connect(self.electricalBaseColorDialog.show) + self.electricalBaseColorButton.setFocusPolicy(PyQt4.QtCore.Qt.NoFocus) + self.electricalBaseColorDialog.colorSelected.connect( + lambda color: self.electricalBaseColorButton.setStyleSheet( + "QPushButton {" + + "background-color: {0}; color: {0};".format(color.name()) + + "}" + ) + ) + + layout.addWidget(QLabel('Peak Membrane Voltage'), 3, 0) + layout.addWidget(self.electricalPeakMembraneVoltage, 3, 1) + + layout.addWidget(QLabel('Peak Compartment Color'), 4, 0) + self.electricalPeakColorDialog.setOption(QColorDialog.ShowAlphaChannel, True) + layout.addWidget(self.electricalPeakColorButton, 4, 1) + self.electricalPeakColorButton.clicked.connect(self.electricalPeakColorDialog.show) + self.electricalPeakColorButton.setFocusPolicy(PyQt4.QtCore.Qt.NoFocus) + self.electricalPeakColorDialog.colorSelected.connect( + lambda color: self.electricalPeakColorButton.setStyleSheet( + "QPushButton {" + + "background-color: {0}; color: {0};".format(color.name()) + + "}" + ) + ) + + layout.addWidget(QLabel('Background Color'), 5, 0) + self.electricalBackgroundColorDialog.setOption(QColorDialog.ShowAlphaChannel, True) + layout.addWidget(self.electricalBackgroundColorButton, 5, 1) + self.electricalBackgroundColorButton.clicked.connect(self.electricalBackgroundColorDialog.show) + self.electricalBackgroundColorButton.setFocusPolicy(PyQt4.QtCore.Qt.NoFocus) + self.electricalBackgroundColorDialog.colorSelected.connect( + lambda color: self.electricalBackgroundColorButton.setStyleSheet( + "QPushButton {" + + "background-color: {0}; color: {0};".format(color.name()) + + "}" + ) + ) + buttonLayout = QGridLayout() + layout.addLayout(buttonLayout, 6, 1) + buttonLayout.addWidget(self.electricalVisualizationCancel, 0, 0, Qt.Qt.AlignRight) + buttonLayout.addWidget(self.electricalVisualizationApply, 0, 1, Qt.Qt.AlignLeft) + + return widget + + def createFloatingPointEditor(self, value = 0.0, minValue = float("-inf"), maxValue = float("+inf"), decimals = 1000): + floatingPointEditor = QLineEdit(str(value)) + floatingPointEditor.setValidator(QDoubleValidator(minValue, maxValue, decimals)) + return floatingPointEditor + +def main(): + app = QtGui.QApplication(sys.argv) + widget = PreferencesView() + widget.show() + sys.exit(app.exec_()) + +if __name__ == "__main__": + main() diff --git a/moose-gui/plugins/README b/moose-gui/plugins/README new file mode 100644 index 0000000000000000000000000000000000000000..629e7cdc1c2395e15c0ec7312f21d45b974d9957 --- /dev/null +++ b/moose-gui/plugins/README @@ -0,0 +1 @@ +This directory will contain python scripts implementing moose plugins. diff --git a/moose-gui/plugins/Runner.py b/moose-gui/plugins/Runner.py new file mode 100644 index 0000000000000000000000000000000000000000..e2dd0aa114a12034f9b7e4bb66eae74544ed5f97 --- /dev/null +++ b/moose-gui/plugins/Runner.py @@ -0,0 +1,94 @@ +import math +import moose +from PyQt4 import Qt, QtGui, QtCore +from PyQt4.QtCore import QTimer +from PyQt4.QtCore import QObject +from PyQt4.QtCore import pyqtSignal + +class Runner(QObject): + """Helper class to control simulation execution + + See: http://doc.qt.digia.com/qq/qq27-responsive-guis.html : + 'Solving a Problem Step by Step' for design details. + """ + + simulationFinished = pyqtSignal(float) + simulationStarted = pyqtSignal(float) + simulationProgressed = pyqtSignal(float) + simulationReset = pyqtSignal() + simulationContinued = pyqtSignal(float) + + def __init__(self): + QtCore.QObject.__init__(self) + self.runTime = None + self.updateInterval = None + self.simulationInterval = None + self.runSequence = None + self.pause = None + self.clock = moose.element("/clock") + + def resetSimulation(self, runTime, updateInterval, simulationInterval): + self.runTime = runTime + self.updateInterval = updateInterval + self.simulationInterval = simulationInterval + self.pause = False + moose.reinit() + self.simulationReset.emit() + + def computeRunSequence(self, runTime, updateInterval, simulationInterval): + # http://sourceforge.net/p/moose/bugs/147/ + runSequence = [ runTime / 20.0 ] * 6 + runSequence.extend([runTime / 10.0] * 7) + # runSequence.append() + # frac, whole = math.modf(runTime / updateInterval) + # runSequence = [ updateInterval ] * int(whole) + # remaining = frac * updateInterval + # if remaining > simulationInterval: + # runSequence.append(remaining) + return runSequence + + def runSimulation(self, runTime): + self.runTime = runTime + self.runSequence = self.computeRunSequence( self.runTime + , self.updateInterval + , self.simulationInterval + ) + self.pause = False + # print(self.runTime) + # print(self.updateInterval) + # print(self.simulationInterval) + # print(self.runSequence) + self.simulationStarted.emit(self.clock.currentTime + self.runTime) + QTimer.singleShot(0, self.next) + + def next(self): + if self.pause: + return + if len(self.runSequence) == 0: + self.simulationFinished.emit(self.clock.currentTime) + return + moose.start(self.runSequence.pop(0)) + self.simulationProgressed.emit(self.clock.currentTime) + QTimer.singleShot(0, self.next) + + def pauseSimulation(self): + self.pause = True + + def unpauseSimulation(self): + self.pause = False + self.next() + + def togglePauseSimulation(self): + if self.pause : + self.pause = False + self.next() + else: + self.pause = True + + def resetAndRunSimulation( self + , runTime + , updateInterval + , simulationInterval + ): + self.resetSimulation(runTime, updateInterval, simulationInterval) + self.runSimulation() diff --git a/moose-gui/plugins/__init__.py b/moose-gui/plugins/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8b4dc1f93ab2966e99ebe3e994f5fa7c4933a999 --- /dev/null +++ b/moose-gui/plugins/__init__.py @@ -0,0 +1,51 @@ +# __init__.py --- +# +# Filename: __init__.py +# Description: +# Author: +# Maintainer: +# Created: Thu Nov 29 12:26:34 2012 (+0530) +# Version: +# Last-Updated: Mon May 13 16:14:32 2013 (+0530) +# By: subha +# Update #: 2 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: + +all = ['default', 'kkit'] + +# +# __init__.py ends here diff --git a/moose-gui/plugins/buildkkit.py b/moose-gui/plugins/buildkkit.py new file mode 100644 index 0000000000000000000000000000000000000000..6e85d60d987273b8b5691ec026a0545cea00f6ae --- /dev/null +++ b/moose-gui/plugins/buildkkit.py @@ -0,0 +1,586 @@ +import sys +import os +import math +import re +from PyQt4 import QtGui, QtCore, Qt +#import pygraphviz as pgv +import networkx as nx +#sys.path.insert(0, '/home/harsha/BuildQ/gui') +import numpy as np +import config +import pickle +from default import * +from moose import * +sys.path.append('plugins') +from mplugin import * +from kkitUtil import * +from kkitQGraphics import PoolItem, ReacItem,EnzItem,CplxItem,ComptItem +from kkitViewcontrol import * +from kkitCalcArrow import * +from kkitOrdinateUtil import * +import posixpath +from mtoolbutton import MToolButton + +class KkitPlugin(MoosePlugin): + """Default plugin for MOOSE GUI""" + def __init__(self, *args): + #print args + MoosePlugin.__init__(self, *args) + + 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.editorView.getCentralWidget().editObject.connect(self.mainWindow.objectEditSlot) + self.currentView = self.editorView + return self.editorView + + def getRunView(self): + view = MoosePlugin.getRunView(self) + view.setDataRoot(self.modelRoot) + view.getCentralWidget().setDataRoot(self.modelRoot) + return view + + +class KkitEditorView(MooseEditorView): + """Default editor. + + TODO: Implementation - display moose element tree as a tree or as + boxes inside boxes + + """ + def __init__(self, plugin): + MooseEditorView.__init__(self, plugin) + ''' + self.insertMenu = QtGui.QMenu('Insert') + sortList = ['CubeMesh','CylMesh','Pool','FuncPool','SumFunc','Reac','Enz','MMenz','StimulusTable','Table'] + for slist in sortList: + action = QtGui.QAction(moose.element('/classes/'+slist).name, self.insertMenu) + self._toolBars.append(action) + ''' + self.fileinsertMenu = QtGui.QMenu('&File') + if not hasattr(self,'SaveModelAction'): + self.saveModelAction = QtGui.QAction('SaveToSBMLFile', 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) + + def SaveModelDialogSlot(self): + type_sbml = 'SBML' + print " here in saveModelDialog" + 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': + print "here",filename," ",self.plugin.modelRoot + moose.writeSBML(str(filename),self.plugin.modelRoot) + 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 = EditorWidgetBase() + self._centralWidget = KineticsWidget() + #print "getCentrelWidget",self.plugin.modelRoot + self._centralWidget.setModelRoot(self.plugin.modelRoot) + return self._centralWidget + +class KineticsWidget(EditorWidgetBase): + def __init__(self, *args): + EditorWidgetBase.__init__(self, *args) + self.setAcceptDrops(True) + self.border = 10 + self.sceneContainer = QtGui.QGraphicsScene(self) + self.sceneContainer.setSceneRect(self.sceneContainer.itemsBoundingRect()) + self.sceneContainer.setBackgroundBrush(QtGui.QColor(230,220,219,120)) + + self.insertMenu = QtGui.QMenu('&Insert') + self._menus.append(self.insertMenu) + self.insertMapper = QtCore.QSignalMapper(self) + + classlist = ['CubeMesh','CylMesh','Pool','FuncPool','SumFunc','Reac','Enz','MMenz','StimulusTable','Table'] + insertMapper, actions = self.getInsertActions(classlist) + + for action in actions: + self.insertMenu.addAction(action) + + def getToolBars(self): + if not hasattr(self, '_insertToolBar'): + self._insertToolBar = QtGui.QToolBar('Insert') + self._toolBars.append(self._insertToolBar) + for action in self.insertMenu.actions(): + button = MToolButton() + button.setDefaultAction(action) + self._insertToolBar.addWidget(button) + return self._toolBars + + def sizeHint(self): + return QtCore.QSize(800,400) + + def updateModelView(self): + #print "update model view",self.modelRoot + if self.modelRoot == '/': + m = wildcardFind('/##[ISA=ChemCompt]') + else: + m = wildcardFind(self.modelRoot+'/##[ISA=ChemCompt]') + #print "111",self.modelRoot,m + if not m: + # 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.view = GraphicalView(self.sceneContainer,self.border,self) + self.layout().addWidget(self.view) + else: + # maxmium and minimum coordinates of the objects specified in kkit file. + self.xmin = 0.0 + self.xmax = 1.0 + self.ymin = 0.0 + self.ymax = 1.0 + self.autoCordinatepos = {} + self.sceneContainer.clear() + # TODO: size will be dummy at this point, but I need the availiable size from the Gui + self.size = QtCore.QSize(1024 ,768) + #self.size = QtCore.QSize(300,400) + self.autocoordinates = False + + # pickled the color map file """ + colormap_file = open(os.path.join(config.settings[config.KEY_COLORMAP_DIR], 'rainbow2.pkl'),'rb') + self.colorMap = pickle.load(colormap_file) + colormap_file.close() + + # Compartment and its members are setup """ + self.meshEntry,self.xmin,self.xmax,self.ymin,self.ymax,self.noPositionInfo = setupMeshObj(self.modelRoot) + # srcdesConnection dictonary will have connection information between src and des """ + + self.srcdesConnection = {} + setupItem(self.modelRoot,self.srcdesConnection) + if self.noPositionInfo: + self.autocoordinates = True + QtGui.QMessageBox.warning(self, + 'No coordinates found for the model', + '\n Automatic layouting will be done') + #raise Exception('Unsupported kkit version') + + + self.xmin,self.xmax,self.ymin,self.ymax,self.autoCordinatepos = autoCoordinates(self.meshEntry,self.srcdesConnection) + + # Scale factor to translate the x -y position to fit the Qt graphicalScene, scene width. """ + 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) + + #A map b/w moose compartment key with QGraphicsObject + self.qGraCompt = {} + + #A map between mooseId of all the mooseObject (except compartment) with QGraphicsObject + self.mooseId_GObj = {} + + self.border = 5 + self.arrowsize = 2 + self.iconScale = 1 + self.defaultComptsize = 5 + self.itemignoreZooming = False + self.lineItem_dict = {} + self.object2line = defaultdict(list) + + # Compartment and its members are put on the qgraphicsscene + self.mooseObjOntoscene() + + # All the moose Object are connected for visualization + self.drawLine_arrow(itemignoreZooming=False) + if hasattr(self, 'view') and isinstance(self.view, QtGui.QWidget): + self.layout().removeWidget(self.view) + self.view = GraphicalView(self.sceneContainer,self.border,self) + hLayout = QtGui.QGridLayout(self) + self.setLayout(hLayout) + hLayout.addWidget(self.view) + #self.layout().addWidget(self.view) + + def mooseObjOntoscene(self): + # All the compartments are put first on to the scene \ + # Need to do: Check With upi if empty compartments exist + 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 == 'ZEnz': + enzItem = EnzItem(enzObj,self.qGraCompt[cmpt]) + else: + enzItem = MMEnzItem(enzObj,self.qGraCompt[cmpt]) + 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' + poolItem = PoolItem(poolObj,self.qGraCompt[cmpt]) + self.setupDisplay(poolinfo,poolItem,"pool") + self.setupSlot(poolObj,poolItem) + + for cplxObj in find_index(memb,'cplx'): + cplxinfo = (cplxObj[0].parent).path+'/info' + cplxItem = CplxItem(cplxObj,self.mooseId_GObj[element(cplxObj[0]).parent.getId()]) + self.setupDisplay(cplxinfo,cplxItem,"cplx") + self.setupSlot(cplxObj,cplxItem) + + for reaObj in find_index(memb,'reaction'): + reainfo = reaObj.path+'/info' + reaItem = ReacItem(reaObj,self.qGraCompt[cmpt]) + self.setupDisplay(reainfo,reaItem,"reaction") + self.setupSlot(reaObj,reaItem) + + for tabObj in find_index(memb,'table'): + tabinfo = tabObj.path+'/info' + tabItem = PoolItem(tabObj,self.qGraCompt[cmpt]) + self.setupDisplay(tabinfo,tabItem,"tab") + self.setupSlot(tabObj,tabItem) + # compartment's rectangle size is calculated depending on children + for k, v in self.qGraCompt.items(): + rectcompt = v.childrenBoundingRect() + v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20)) + v.setPen(QtGui.QPen(Qt.QColor(66,66,66,100), 5, Qt.Qt.SolidLine, Qt.Qt.RoundCap, Qt.Qt.RoundJoin)) + v.cmptEmitter.connect(v.cmptEmitter,QtCore.SIGNAL("qgtextPositionChange(PyQt_PyObject)"),self.positionChange) + v.cmptEmitter.connect(v.cmptEmitter,QtCore.SIGNAL("qgtextItemSelectedChange(PyQt_PyObject)"),self.objectEditSlot) + + 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): + xpos,ypos = self.positioninfo(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")): + textcolor,bgcolor = "white","white" + elif objClass == "tab": + textcolor,bgcolor = getColor(info,self.colorMap) + else: + textcolor,bgcolor = getColor(info,self.colorMap) + + graphicalObj.setDisplayProperties(xpos,ypos,textcolor,bgcolor) + + def positioninfo(self,iteminfo): + if self.noPositionInfo: + + try: + # kkit does exist item's/info which up querying for parent.path gives the information of item's parent + x,y = self.autoCordinatepos[(element(iteminfo).parent).path] + except: + # But in Cspace reader doesn't create item's/info, up on querying gives me the error which need to change\ + # in ReadCspace.cpp, at present i am taking care b'cos i don't want to pass just the item where I need to check\ + # type of the object (rea,pool,enz,cplx,tab) which I have already done. + parent, child = posixpath.split(iteminfo) + x,y = self.autoCordinatepos[parent] + ypos = (y-self.ymin)*self.yratio + else: + x = float(element(iteminfo).getField('x')) + y = float(element(iteminfo).getField('y')) + #Qt origin is at the top-left corner. The x values increase to the right and the y values increase downwards \ + #as compared to Genesis codinates where origin is center and y value is upwards, that is why ypos is negated + ypos = -(y-self.ymin)*self.yratio + xpos = (x-self.xmin)*self.xratio + + return(xpos,ypos) + + def setupSlot(self,mooseObj,qgraphicItem): + self.mooseId_GObj[element(mooseObj).getId()] = qgraphicItem + qgraphicItem.connect(qgraphicItem,QtCore.SIGNAL("qgtextPositionChange(PyQt_PyObject)"),self.positionChange) + qgraphicItem.connect(qgraphicItem,QtCore.SIGNAL("qgtextItemSelectedChange(PyQt_PyObject)"),self.objectEditSlot) + + 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) + + def positionChange(self,mooseObject): + #If the item position changes, the corresponding arrow's are calculated + if isinstance(element(mooseObject),CubeMesh): + for k, v in self.qGraCompt.items(): + mesh = mooseObject.path+'/mesh[0]' + if k.path == mesh: + for rectChilditem in v.childItems(): + self.updateArrow(rectChilditem) + else: + mobj = self.mooseId_GObj[mooseObject.getId()] + self.updateArrow(mobj) + for k, v in self.qGraCompt.items(): + rectcompt = v.childrenBoundingRect() + v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20)) + + def emitItemtoEditor(self,mooseObject): + #self.emit(QtCore.SIGNAL("itemPressed(PyQt_PyObject)"),mooseObject) + self.editObject.emit(mooseObject.path) + + def drawLine_arrow(self, itemignoreZooming=False): + for inn,out in self.srcdesConnection.items(): + # self.srcdesConnection is dictionary which contains key,value \ + # key is Enzyme or Reaction and value [[list of substrate],[list of product]] (tuple) + # key is FuncBase and value is [list of pool] (list) + + #src = self.mooseId_GObj[inn] + if isinstance(out,tuple): + if len(out[0])== 0: + print inn.className + ':' +inn[0].name+ " doesn't output message" + else: + src = self.mooseId_GObj[inn] + for items in (items for items in out[0] ): + des = self.mooseId_GObj[element(items[0]).getId()] + + self.lineCord(src,des,items,itemignoreZooming) + if len(out[1]) == 0: + print inn.className + ':' +inn[0].name+ " doesn't output message" + else: + for items in (items for items in out[1] ): + des = self.mooseId_GObj[element(items[0]).getId()] + self.lineCord(src,des,items,itemignoreZooming) + + elif isinstance(out,list): + if len(out) == 0: + print "Func pool doesn't have sumtotal" + else: + src = self.mooseId_GObj[element(inn).getId()] + for items in (items for items in out ): + des = self.mooseId_GObj[element(items[0]).getId()] + self.lineCord(src,des,items,itemignoreZooming) + + def lineCord(self,src,des,type_no,itemignoreZooming): + 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,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) + pen = QtGui.QPen(QtCore.Qt.green, 0, Qt.Qt.SolidLine, Qt.Qt.RoundCap, Qt.Qt.RoundJoin) + pen.setWidth(self.arrowsize) + #pen.setCosmetic(True) + # 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.path+'/info' + color,bgcolor = getColor(pinfo,self.colorMap) + pen.setColor(color) + elif isinstance(source, moose.PoolBase): + 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,line) ) + self.object2line[ des ].append( ( qgLineitem, src,line ) ) + qgLineitem.setPen(pen) + + 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,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): + self.cplxUpdatearrow(srcdes[0]) + elif( type(srcdes[1]) == EnzItem): + 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 + + #Note: Here at this point enzItem has just one child which is cplxItem and childItems returns, PyQt4.QtGui.QGraphicsEllipseItem,CplxItem + #Assuming CplxItem is always[1], but still check if not[0], if something changes in structure one need to keep an eye. + if (srcdes.childItems()[1],CplxItem): + self.updateArrow(srcdes.childItems()[1]) + else: + self.updateArrow(srcdes.childItems()[0]) + + def keyPressEvent(self,event): + # key1 = event.key() # key event does not distinguish between capital and non-capital letters + key = event.text().toAscii().toHex() + if key == '41': # 'A' fits the view to iconScale factor + itemignoreZooming = False + self.updateItemTransformationMode(itemignoreZooming) + 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) + self.drawLine_arrow(itemignoreZooming=False) + + elif (key == '2e'): # '.' key, lower case for '>' zooms in + self.view.scale(1.1,1.1) + + elif (key == '2c'): # ',' key, lower case for '<' zooms in + self.view.scale(1/1.1,1/1.1) + + elif (key == '3c'): # '<' key. zooms-in to iconScale factor + self.iconScale *= 0.8 + self.updateScale( self.iconScale ) + + elif (key == '3e'): # '>' key. zooms-out to iconScale factor + self.iconScale *= 1.25 + self.updateScale( self.iconScale ) + + elif (key == '61'): # 'a' fits the view to initial value where iconscale=1 + self.iconScale = 1 + self.updateScale( self.iconScale ) + 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 updateItemTransformationMode(self, on): + for v in self.sceneContainer.items(): + if( not isinstance(v,ComptItem)): + #if ( isinstance(v, PoolItem) or isinstance(v, ReacItem) or isinstance(v, EnzItem) or isinstance(v, CplxItem) ): + if isinstance(v,KineticsDisplayItem): + v.setFlag(QtGui.QGraphicsItem.ItemIgnoresTransformations, on) + + def updateScale( self, scale ): + for item in self.sceneContainer.items(): + if isinstance(item,KineticsDisplayItem): + item.refresh(scale) + #iteminfo = item.mobj.path+'/info' + #xpos,ypos = self.positioninfo(iteminfo) + xpos = item.scenePos().x() + ypos = item.scenePos().y() + + if isinstance(item,ReacItem) or isinstance(item,EnzItem) or isinstance(item,MMEnzItem): + item.setGeometry(xpos,ypos, + item.gobj.boundingRect().width(), + item.gobj.boundingRect().height()) + elif isinstance(item,CplxItem): + item.setGeometry(item.gobj.boundingRect().width()/2,item.gobj.boundingRect().height(), + item.gobj.boundingRect().width(), + item.gobj.boundingRect().height()) + elif isinstance(item,PoolItem): + item.setGeometry(xpos, ypos,item.gobj.boundingRect().width() + +PoolItem.fontMetrics.width(' '), + item.gobj.boundingRect().height()) + item.bg.setRect(0, 0, item.gobj.boundingRect().width()+PoolItem.fontMetrics.width(' '), item.gobj.boundingRect().height()) + + self.drawLine_arrow(itemignoreZooming=False) + for k, v in self.qGraCompt.items(): + rectcompt = v.childrenBoundingRect() + comptPen = v.pen() + comptWidth = self.defaultComptsize*self.iconScale + comptPen.setWidth(comptWidth) + v.setPen(comptPen) + v.setRect(rectcompt.x()-comptWidth,rectcompt.y()-comptWidth,(rectcompt.width()+2*comptWidth),(rectcompt.height()+2*comptWidth)) + +if __name__ == "__main__": + app = QtGui.QApplication(sys.argv) + size = QtCore.QSize(1024 ,768) + modelPath = 'Kholodenko' + #modelPath = 'acc61' + #modelPath = 'acc8' + modelPath = '3ARECB' + #modelPath = '3AreacB' + modelPath = '5AreacB' + itemignoreZooming = False + try: + filepath = '../../Demos/Genesis_files/'+modelPath+'.g' + #filepath = '/home/harsha/genesis_files/gfile/'+modelPath+'.g' + print filepath + f = open(filepath, "r") + loadModel(filepath,'/'+modelPath) + + moose.le('/'+modelPath+'/kinetics') + dt = KineticsWidget() + dt.modelRoot ='/'+modelPath + ''' Loading moose signalling model in python ''' + #execfile('/home/harsha/BuildQ/Demos/Genesis_files/scriptKineticModel.py') + #dt.modelRoot = '/model' + + dt.updateModelView() + dt.show() + + except IOError, what: + (errno, strerror) = what + print "Error number",errno,"(%s)" %strerror + sys.exit(0) + sys.exit(app.exec_()) diff --git a/moose-gui/plugins/constants.py b/moose-gui/plugins/constants.py new file mode 100644 index 0000000000000000000000000000000000000000..558b5fc518e205f7536551e6f3d2580c4b889915 --- /dev/null +++ b/moose-gui/plugins/constants.py @@ -0,0 +1,16 @@ +INVALID = 6 +INTERIOR = 7 +BOUNDARY = 8 +SAME_OBJECT = 9 +OTHER_OBJECT = 10 +NO_OBJECT = 11 +RUBBERBAND_SELECTION = 12 +VALID = 13 + +ITEM = 0 +CONNECTOR = 1 +CONNECTION = 2 +EMPTY = 3 +COMPARTMENT = 14 +COMPARTMENT_BOUNDARY = 4 +COMPARTMENT_INTERIOR = 5 diff --git a/moose-gui/plugins/datastore/preferences.json b/moose-gui/plugins/datastore/preferences.json new file mode 100644 index 0000000000000000000000000000000000000000..914bcc61aad435982e5bbcdd1c81410e1ca1add9 --- /dev/null +++ b/moose-gui/plugins/datastore/preferences.json @@ -0,0 +1,44 @@ +{ + "chemical": { + "simulation": { + "default-runtime": 100.0, + "diffusion-dt": 0.01, + "gui-update-interval": 10.0, + "plot-update-interval": 10.0, + "simulation-dt": 10.0, + "solver": "Runge Kutta" + }, + "visualization": {} + }, + "electrical": { + "simulation": { + "default-runtime": 1.0, + "gui-update-interval": 0.01, + "plot-update-interval": 0.0005, + "simulation-dt": 5e-05, + "solver": "Gillespie" + }, + "visualization": { + "background-color": [ + 255, + 255, + 255, + 0 + ], + "base-color": [ + 255, + 5, + 0, + 251 + ], + "base-membrane-voltage": -0.07, + "peak-color": [ + 170, + 255, + 253, + 255 + ], + "peak-membrane-voltage": -0.06 + } + } +} diff --git a/moose-gui/plugins/default.py b/moose-gui/plugins/default.py new file mode 100644 index 0000000000000000000000000000000000000000..cb9407270b2c831ef42185e58de0a1d5c27f9a1a --- /dev/null +++ b/moose-gui/plugins/default.py @@ -0,0 +1,1503 @@ +# default.py --- +# +# Filename: default.py +# Description: +# Author: Subhasis Ray +# Maintainer: +# Created: Tue Nov 13 15:58:31 2012 (+0530) +# Version: +# Last-Updated: Thu Jul 18 10:35:00 2013 (+0530) +# By: subha +# Update #: 2244 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# The default placeholder plugin for MOOSE +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: + +import sys +import config +import pickle +import os +from collections import defaultdict +import numpy as np +from PyQt4 import QtGui, QtCore +from PyQt4.Qt import Qt + +import moose +from moose import utils +import mtree +from mtoolbutton import MToolButton +from msearch import SearchWidget +from checkcombobox import CheckComboBox + +from mplugin import MoosePluginBase, EditorBase, EditorWidgetBase, PlotBase, RunBase +#from defaultToolPanel import DefaultToolPanel +#from DataTable import DataTable +from matplotlib import rcParams +rcParams.update({'figure.autolayout': True}) +from matplotlib.lines import Line2D +from PlotWidgetContainer import PlotWidgetContainer + +from PyQt4 import QtCore, QtGui +from PyQt4.QtGui import QDoubleValidator +from kkitUtil import getColor +from Runner import Runner +# from Runner import Runner +# from __future__ import print_function +from PyQt4 import QtGui, QtCore +from PyQt4.QtGui import QToolBar +from PyQt4.QtGui import QToolButton +from PyQt4.QtGui import QLabel +from PyQt4.QtGui import QIcon +from PyQt4.QtGui import QLineEdit +from PyQt4.QtGui import QErrorMessage +from PyQt4.QtGui import QSizeGrip +from PyQt4.QtGui import QIcon +from PyQt4.QtGui import QPixmap +from PyQt4.QtGui import QAction +from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar +#from EventBlocker import EventBlocker +# from PlotNavigationToolbar import PlotNavigationToolbar +from global_constants import preferences +from setsolver import * +ELECTRICAL_MODEL = 0 +CHEMICAL_MODEL = 1 + +class MoosePlugin(MoosePluginBase): + """Default plugin for MOOSE GUI""" + def __init__(self, root, mainwindow): + MoosePluginBase.__init__(self, root, mainwindow) + #print "mplugin ",self.getRunView() + #self.connect(self, QtCore.SIGNAL("tableCreated"),self.getRunView().getCentralWidget().plotAllData) + 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 = MooseEditorView(self) + #signal to objecteditor from default plugin + self.editorView.getCentralWidget().editObject.connect(self.mainWindow.objectEditSlot) + self.currentView = self.editorView + return self.editorView + + def getPlotView(self): + if not hasattr(self, 'plotView'): + self.plotView = PlotView(self) + return self.plotView + + def getRunView(self): + + if not hasattr(self, 'runView') or self.runView is None: + self.runView = RunView(self.modelRoot, self) + return self.runView + + def getMenus(self): + """Create a custom set of menus.""" + return self._menus + + +class MooseEditorView(EditorBase): + """Default editor. + + """ + def __init__(self, plugin): + EditorBase.__init__(self, plugin) + self.__initMenus() + self.__initToolBars() + + def __initMenus(self): + editMenu = QtGui.QMenu('&Edit') + for menu in self.getCentralWidget().getMenus(): + editMenu.addMenu(menu) + self._menus.append(editMenu) + + def __initToolBars(self): + for toolbar in self.getCentralWidget().getToolBars(): + self._toolBars.append(toolbar) + + def getToolPanes(self): + return super(MooseEditorView, self).getToolPanes() + + def getLibraryPane(self): + return super(MooseEditorView, self).getLibraryPane() + + def getOperationsWidget(self): + return super(MooseEditorView, self).getOperationsPane() + + def getCentralWidget(self): + """Retrieve or initialize the central widget. + + Note that we call the widget's setModelRoot() function + explicitly with the plugin's modelRoot as the argument. This + enforces an update of the widget display with the current + modelRoot. + + This function should be overridden by any derived class as it + has the editor widget class hard coded into it. + + """ + if self._centralWidget is None: + self._centralWidget = DefaultEditorWidget() + if hasattr(self._centralWidget, 'init'): + self._centralWidget.init() + self._centralWidget.setModelRoot(self.plugin.modelRoot) + return self._centralWidget + + +class MooseTreeEditor(mtree.MooseTreeWidget): + """Subclass of MooseTreeWidget to implement drag and drop events. It + creates an element under the drop location using the dropped mime + data as class name. + + """ + def __init__(self, *args): + mtree.MooseTreeWidget.__init__(self, *args) + + def dragEnterEvent(self, event): + if event.mimeData().hasFormat('text/plain'): + event.acceptProposedAction() + + def dragMoveEvent(self, event): + if event.mimeData().hasFormat('text/plain'): + event.acceptProposedAction() + + def dropEvent(self, event): + """Insert an element of the specified class in drop location""" + if not event.mimeData().hasFormat('text/plain'): + return + pos = event.pos() + item = self.itemAt(pos) + try: + self.insertChildElement(item, str(event.mimeData().text())) + event.acceptProposedAction() + except NameError: + return + + +class DefaultEditorWidget(EditorWidgetBase): + """Editor widget for default plugin. + + Plugin-writers should code there own editor widgets derived from + EditorWidgetBase. + + It adds a toolbar for inserting moose objects into the element + tree. The toolbar contains MToolButtons for moose classes. + + Signals: editObject - inherited from EditorWidgetBase , emitted + with currently selected element's path as argument. Should be + connected to whatever slot is responsible for firing the object + editor in top level. + + """ + def __init__(self, *args): + EditorWidgetBase.__init__(self, *args) + layout = QtGui.QHBoxLayout() + self.setLayout(layout) + self.tree = MooseTreeEditor() + self.tree.setAcceptDrops(True) + self.getTreeMenu() + self.layout().addWidget(self.tree) + + def getTreeMenu(self): + try: + return self.treeMenu + except AttributeError: + self.treeMenu = QtGui.QMenu() + self.tree.setContextMenuPolicy(Qt.CustomContextMenu) + self.tree.customContextMenuRequested.connect(lambda : self.treeMenu.exec_(QtGui.QCursor.pos()) ) + # Inserting a child element + self.insertMenu = QtGui.QMenu('Insert') + self._menus.append(self.insertMenu) + self.treeMenu.addMenu(self.insertMenu) + self.insertMapper = QtCore.QSignalMapper(self) + ignored_bases = ['ZPool', 'Msg', 'Panel', 'SolverBase', 'none'] + ignored_classes = ['ZPool','ZReac','ZMMenz','ZEnz','CplxEnzBase'] + classlist = [ch[0].name for ch in moose.element('/classes').children + if (ch[0].baseClass not in ignored_bases) + and (ch[0].name not in (ignored_bases + ignored_classes)) + and not ch[0].name.startswith('Zombie') + and not ch[0].name.endswith('Base') + ] + insertMapper, actions = self.getInsertActions(classlist) + for action in actions: + self.insertMenu.addAction(action) + self.connect(insertMapper, QtCore.SIGNAL('mapped(const QString&)'), self.tree.insertElementSlot) + self.editAction = QtGui.QAction('Edit', self.treeMenu) + self.editAction.triggered.connect(self.editCurrentObjectSlot) + self.tree.elementInserted.connect(self.elementInsertedSlot) + self.treeMenu.addAction(self.editAction) + return self.treeMenu + + def updateModelView(self): + self.tree.recreateTree(root=self.modelRoot) + # if current in self.tree.odict: + # self.tree.setCurrentItem(current) + + def updateItemSlot(self, mobj): + """This should be overridden by derived classes to connect appropriate + slot for updating the display item. + + """ + self.tree.updateItemSlot(mobj) + + def editCurrentObjectSlot(self): + """Emits an `editObject(str)` signal with moose element path of + currently selected tree item as argument + + """ + mobj = self.tree.currentItem().mobj + self.editObject.emit(mobj.path) + + def sizeHint(self): + return QtCore.QSize(400, 300) + + def getToolBars(self): + if not hasattr(self, '_insertToolBar'): + self._insertToolBar = QtGui.QToolBar('Insert') + return self._toolBars + for action in self.insertMenu.actions(): + button = MToolButton() + button.setDefaultAction(action) + self._insertToolBar.addWidget(button) + self._toolBars.append(self._insertToolBar) + return self._toolBars + + +############################################################ +# +# View for running a simulation and runtime visualization +# +############################################################ + + +from mplot import CanvasWidget + +class RunView(RunBase): + """A default runtime view implementation. This should be + sufficient for most common usage. + + canvas: widget for plotting + + dataRoot: location of data tables + + """ + def __init__(self, modelRoot, *args, **kwargs): + RunBase.__init__(self, *args, **kwargs) + self.modelRoot = modelRoot + if modelRoot != "/": + self.dataRoot = modelRoot + '/data' + else: + self.dataRoot = "/data" + self.setModelRoot(moose.Neutral(self.plugin.modelRoot).path) + self.setDataRoot(moose.Neutral('/data').path) + self.setDataRoot(moose.Neutral(self.plugin.modelRoot).path) + self.plugin.modelRootChanged.connect(self.setModelRoot) + self.plugin.dataRootChanged.connect(self.setDataRoot) + # self.getCentralWidget() + self._menus += self.getCentralWidget().getMenus() + + def getCentralWidget(self): + """TODO: replace this with an option for multiple canvas + tabs""" + if self._centralWidget is None: + self._centralWidget = PlotWidgetContainer(self.modelRoot) + return self._centralWidget + + def setDataRoot(self, path): + self.dataRoot = path + + def setModelRoot(self, path): + self.modelRoot = path + + def getDataTablesPane(self): + """This should create a tree widget with dataRoot as the root + to allow visual selection of data tables for plotting.""" + raise NotImplementedError() + + def plotAllData(self): + """This is wrapper over the same function in PlotWidget.""" + self.centralWidget.plotAllData() + + def getToolPanes(self): + return [] + if not self._toolPanes: + self._toolPanes = [self.getSchedulingDockWidget()] + return self._toolPanes + + def getSchedulingDockWidget(self): + """Create and/or return a widget for schduling""" + if hasattr(self, 'schedulingDockWidget') and self.schedulingDockWidget is not None: + return self.schedulingDockWidget + self.schedulingDockWidget = QtGui.QDockWidget('Scheduling') + self.schedulingDockWidget.setFeatures( QtGui.QDockWidget.NoDockWidgetFeatures); + self.schedulingDockWidget.setWindowFlags(Qt.CustomizeWindowHint) + titleWidget = QtGui.QWidget(); + self.schedulingDockWidget.setTitleBarWidget(titleWidget) + widget = SchedulingWidget() + widget.setDataRoot(self.dataRoot) + widget.setModelRoot(self.modelRoot) + self.schedulingDockWidget.setWidget(widget) + widget.runner.simulationStarted.connect(self._centralWidget.extendXAxes) + widget.runner.simulationProgressed.connect(self._centralWidget.updatePlots) + widget.runner.simulationFinished.connect(self._centralWidget.rescalePlots) + # widget.runner.simulationContinued.connect(self._centralWidget.extendXAxes) + widget.runner.simulationReset.connect(self._centralWidget.plotAllData) + self._toolBars += widget.getToolBars() + return self.schedulingDockWidget + +''' +class MooseRunner(QtCore.QObject): + """Helper class to control simulation execution + + See: http://doc.qt.digia.com/qq/qq27-responsive-guis.html : + 'Solving a Problem Step by Step' for design details. + """ + resetAndRun = QtCore.pyqtSignal(name='resetAndRun') + update = QtCore.pyqtSignal(name='update') + currentTime = QtCore.pyqtSignal(float, name='currentTime') + finished = QtCore.pyqtSignal(name='finished') + + def __init__( self + , runTime + , updateInterval + ): + QtCore.QObject.__init__(self) + # if (MooseRunner.inited): + # return + self.runTime = runTime + self.updateInterval = updateInterval + self._updateInterval = 100e-3 + self._simtime = 0.0 + self._clock = moose.Clock('/clock') + self._pause = False + self.dataRoot = '/data' + self.modelRoot = '/model' + #MooseRunner.inited = True + + def doResetAndRun(self, tickDtMap, tickTargetMap, simtime, updateInterval): + self._pause = False + self._updateInterval = 0.1 #updateInterval + self._simtime = simtime + utils.updateTicks(tickDtMap) + utils.assignTicks(tickTargetMap) + self.resetAndRun.emit() + moose.reinit() + QtCore.QTimer.singleShot(0, self.run) + + def run(self): + """Run simulation for a small interval.""" + print("simtime => ", self._simtime) + print("update interval => ", self._updateInterval) + print("current time => ", self._clock.currentTime) + print("Base dt => ", self._clock.baseDt) + if self._clock.currentTime >= self._simtime: + self.finished.emit() + return + if self._pause: + return + toRun = self._simtime - self._clock.currentTime + if toRun > self._updateInterval: + toRun = self._updateInterval + if toRun < self._clock.baseDt: + return + moose.start(toRun) + self.update.emit() + self.currentTime.emit(self._clock.currentTime) + QtCore.QTimer.singleShot(0, self.run) + + def continueRun(self, simtime, updateInterval): + """Continue running without reset for `simtime`.""" + self._simtime = simtime + self._updateInterval = updateInterval + self._pause = False + QtCore.QTimer.singleShot(0, self.run) + + def stop(self): + """Pause simulation""" + self._pause = True +''' +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 + + # if not self.advanceOptiondisplayed: + # self.advancedOptionsWidget.hide() + + # self.__getUpdateIntervalWidget() + #layout.addWidget(self.__getUpdateIntervalWidget()) + # spacerItem = QtGui.QSpacerItem(450, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + # layout.addItem(spacerItem) + # self.setLayout(layout) + # self._toolBars.append( + 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) + # self.resetAndRunButton.clicked.connect(self.resetAndRunSlot) + # self.continueButton.clicked.connect(self.doContinueRun) + # self.continueRun.connect(self.runner.continueRun) + # self.stopButton.clicked.connect(self.runner.stop) + + 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('icons/arrow_undo.png') + , 'Reset' + , self.resetSimulation + ) + self.resetAction.setToolTip('Reset simulation.') + + self.runAction = bar.addAction( QIcon('icons/run.png') + , 'Run' + , self.runSimulation + ) + self.runAction.setToolTip('Run simulation.') + + + self.stopAction = bar.addAction( QIcon('icons/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 + # spacer.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) + # self._runToolBar.addWidget(spacer) + # self._runToolBar.addWidget(QtGui.QLabel('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)")) + # self._runToolBar.addWidget(self.()) + + bar.addSeparator() + + self.preferencesButton = QToolButton() + self.preferencesButton.setText("Preferences") + self.preferencesButton.clicked.connect(self.preferencesToggler) + + bar.addWidget(self.preferencesButton) + return bar + + # def updateTickswidget(self): + # if self.advanceOptiondisplayed: + # self.advancedOptionsWidget.hide() + # self.advanceOptiondisplayed = False + # else: + # self.advancedOptionsWidget.show() + # self.advanceOptiondisplayed = True + + 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) + # return + # if self.continueFlag: + # self.continueSimulation() + # else: + # self.runner.runSimulation() + # self.continueFlag = True + + 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"] + #print(self.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"] + #print(self.solver) + + def checkConsistency(self): + if self.updateInterval < self.simulationInterval : + self.updateInterval = self.simulationInterval + + # print("Hello") + # dialog = QErrorMessage() + # dialog.showMessage( + # """GUI Update interval should be greater than Simulation Interval. + # Please update these values in Edit > Preferences.""" + # ) + # return False + if self.runTime < self.updateInterval : + self.runTime = self.updateInterval + # dialog = QErrorMessage() + # dialog.showMessage( + # """Simulation runtime should greater than GUI Update interval. + # Please update the runtime in the Scheduling Toolbar""" + # ) + # return False + 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 setElectricalParameters(self): + # chemicalPreferences = self.preferences.getChemicalPreferences() + # self.updateInterval = chemicalPreferences["guiUpdateInterval"] + # self.simulationInterval = chemicalPreferences["simulationInterval"] + # chemicalPreferences["diffusionInterval"] + # chemicalPreferences + # self. chemicalPreferences + # self. chemicalPreferences + # self. chemicalPreferences + # self. runTime = float(self.simulationRuntime.text()) + + 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, 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() + +from collections import namedtuple + +# Keeps track of data sources for a plot. 'x' can be a table path or +# '/clock' to indicate time points from moose simulations (which will +# be created from currentTime field of the `/clock` element and the +# number of dat points in 'y'. 'y' should be a table. 'z' can be empty +# string or another table or something else. Will not be used most of +# the time (unless 3D or heatmap plotting). + +PlotDataSource = namedtuple('PlotDataSource', ['x', 'y', 'z'], verbose=False) +event = None +legend = None +canvas = None + +from PyQt4.QtGui import QWidget +from PyQt4.QtGui import QSizeGrip +from PyQt4.QtGui import QLayout +from PyQt4.QtGui import QScrollArea +from PyQt4.QtGui import QMenu +from PyQt4.QtCore import pyqtSlot,SIGNAL,SLOT, Signal, pyqtSignal + +class PlotWidget(QWidget): + """A wrapper over CanvasWidget to handle additional MOOSE-specific + stuff. + + modelRoot - path to the entire model our plugin is handling + + dataRoot - path to the container of data tables. + + TODO: do we really need this separation or should we go for + standardizing location of data with respect to model root. + + pathToLine - map from moose path to Line2D objects in plot. Can + one moose table be plotted multiple times? Maybe yes (e.g., when + you want multiple other tables to be compared with the same data). + + lineToDataSource - map from Line2D objects to moose paths + + """ + + widgetClosedSignal = pyqtSignal(object) + addGraph = pyqtSignal(object) + def __init__(self, model, graph, index, parentWidget, *args, **kwargs): + super(PlotWidget, self).__init__() + self.model = model + self.graph = graph + self.index = index + + self.menu = self.getContextMenu() + self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + self.connect( self + , SIGNAL("customContextMenuRequested(QPoint)") + , self + , SLOT("contextMenuRequested(QPoint)") + ) + + self.canvas = CanvasWidget(self.model, self.graph, self.index) + self.canvas.setParent(self) + self.navToolbar = NavigationToolbar(self.canvas, self) + self.hackNavigationToolbar() + self.canvas.mpl_connect('pick_event',self.togglePlot) + # self.canvas. + # self.navToolbar.addSeparator() + layout = QtGui.QGridLayout() + # canvasScrollArea = QScrollArea() + # canvasScrollArea.setWidget(self.canvas) + layout.addWidget(self.navToolbar, 0, 0) + layout.addWidget(self.canvas, 1, 0) + self.setLayout(layout) + # self.setAcceptDrops(True) + #self.modelRoot = '/' + self.pathToLine = defaultdict(set) + self.lineToDataSource = {} + self.axesRef = self.canvas.addSubplot(1, 1) + # box = self.axesRef.get_position() + # self.axesRef.set_position([box.x0, box.y0, box.width * 0.8, box.height]) + + self.legend = None + # layout.setSizeConstraint( QLayout.SetNoConstraint ) + # self.setSizePolicy( QtGui.QSizePolicy.Expanding + # , QtGui.QSizePolicy.Expanding + # ) + + desktop = QtGui.QApplication.desktop() + # print("**********************") + # print(desktop.screenGeometry()) + # print("***********************") + self.setMinimumSize(desktop.screenGeometry().width() / 4, desktop.screenGeometry().height() / 3) + # self.setMaximumSize(desktop.screenGeometry().width() / 2, desktop.screenGeometry().height() / 2) + # self.setMinimumSize(self.width(), self.height()) + # self.setMaximumSize(2 * self.width(), 2* self.height()) + # QtCore.QObject.connect(utils.tableEmitter,QtCore.SIGNAL("tableCreated()"),self.plotAllData) + self.canvas.updateSignal.connect(self.plotAllData) + self.plotAllData() + # self.plotView = PlotView(model, graph, index, self) + #self.dataTable = DataTable() + #utils.tableCreated.connect(plotAllData) + # self.plotAllData() + # self.setSizePolicy(QtGui.QSizePolicy.Fixed, + # QtGui.QSizePolicy.Expanding) + + def hackNavigationToolbar(self): + # ADD Graph Action + pixmap = QPixmap("icons/add_graph.png") + icon = QIcon(pixmap) + action = QAction(icon, "Add a graph", self.navToolbar) + # self.navToolbar.addAction(action) + action.triggered.connect(self.addGraph.emit) + self.navToolbar.insertAction(self.navToolbar.actions()[0], action) + + # Delete Graph Action + pixmap = QPixmap("icons/delete_graph.png") + icon = QIcon(pixmap) + action = QAction(icon, "Delete this graph", self.navToolbar) + # self.navToolbar.addAction(action) + action.triggered.connect(self.delete) + + self.navToolbar.insertAction(self.navToolbar.actions()[1], action) + + #Toggle Grid Action + + pixmap = QPixmap("icons/grid.png") + icon = QIcon(pixmap) + action = QAction(icon, "Toggle Grid", self.navToolbar) + # self.navToolbar.addAction(action) + action.triggered.connect(self.canvas.toggleGrid) + self.navToolbar.insertAction(self.navToolbar.actions()[2], action) + self.navToolbar.insertSeparator(self.navToolbar.actions()[3]) + + + @property + def plotAll(self): + return len(self.pathToLine) == 0 + + def toggleLegend(self): + if self.legend is not None: + self.legend.set_visible(not self.legend.get_visible()) + self.canvas.draw() + + def getContextMenu(self): + menu = QMenu() + # closeAction = menu.addAction("Delete") + exportCsvAction = menu.addAction("Export to CSV") + exportCsvAction.triggered.connect(self.saveAllCsv) + toggleLegendAction = menu.addAction("Toggle legend") + toggleLegendAction.triggered.connect(self.toggleLegend) + self.removeSubmenu = menu.addMenu("Remove") + # configureAction.triggered.connect(self.configure) + # self.connect(,SIGNAL("triggered()"), + # self,SLOT("slotShow500x500()")) + # self.connect(action1,SIGNAL("triggered()"), + # self,SLOT("slotShow100x100()")) + + return menu + + def deleteGraph(self): + print("Deleting " + self.graph.path) + moose.delete(self.graph.path) + + def delete(self, event): + print("Deleting PlotWidget") + self.deleteGraph() + self.close() + self.widgetClosedSignal.emit(self) + + def configure(self, event): + print("Displaying configure view!") + self.plotView.getCentralWidget().show() + + @pyqtSlot(QtCore.QPoint) + def contextMenuRequested(self,point): + # menu = QtGui.QMenu() + + # # action1 = menu.addAction("Set Size 100x100") + # # action2 = menu.addAction("Set Size 500x500") + + + # # self.connect(action2,SIGNAL("triggered()"), + # # self,SLOT("slotShow500x500()")) + # # self.connect(action1,SIGNAL("triggered()"), + # # self,SLOT("slotShow100x100()")) + self.menu.exec_(self.mapToGlobal(point)) + + def setModelRoot(self, path): + self.modelRoot = path + + def setDataRoot(self, path): + self.dataRoot = path + #plotAllData() + + def genColorMap(self,tableObject): + #print "tableObject in colorMap ",tableObject + species = tableObject+'/info' + colormap_file = open(os.path.join(config.settings[config.KEY_COLORMAP_DIR], 'rainbow2.pkl'),'rb') + self.colorMap = pickle.load(colormap_file) + colormap_file.close() + hexchars = "0123456789ABCDEF" + color = 'white' + #Genesis model exist the path and color will be set but not xml file so bypassing + #print "here genColorMap ",moose.exists(species) + if moose.exists(species): + color = moose.element(species).getField('color') + if ((not isinstance(color,(list,tuple)))): + if color.isdigit(): + tc = int(color) + tc = (tc * 2 ) + r,g,b = self.colorMap[tc] + color = "#"+ hexchars[r / 16] + hexchars[r % 16] + hexchars[g / 16] + hexchars[g % 16] + hexchars[b / 16] + hexchars[b % 16] + else: + color = 'white' + return color + + + def removePlot(self, table): + print("removePlot =>", table) + moose.delete(table) + self.plotAllData() + + def makeRemovePlotAction(self, label, table): + action = self.removeSubmenu.addAction(label) + action.triggered.connect(lambda: self.removePlot(table)) + return action + + def plotAllData(self): + """Plot data from existing tables""" + self.axesRef.lines = [] + self.pathToLine.clear() + self.removeSubmenu.clear() + if self.legend is not None: + self.legend.set_visible(False) + path = self.model.path + modelroot = self.model.path + time = moose.Clock('/clock').currentTime + tabList = [] + #for tabId in moose.wildcardFind('%s/##[TYPE=Table]' % (path)): + #harsha: policy graphs will be under /model/modelName need to change in kkit + #for tabId in moose.wildcardFind('%s/##[TYPE=Table]' % (modelroot)): + + plotTables = list(moose.wildcardFind(self.graph.path + '/##[TYPE=Table]')) + plotTables.extend(moose.wildcardFind(self.graph.path + '/##[TYPE=Table2]')) + if len (plotTables) > 0: + for tabId in plotTables: + tab = moose.Table(tabId) + #print("Table =>", tab) + line_list=[] + tableObject = tab.neighbors['requestOut'] + # Not a good way + #tableObject.msgOut[0] + if len(tableObject) > 0: + + # This is the default case: we do not plot the same + # table twice. But in special cases we want to have + # multiple variations of the same table on different + # axes. + # + #Harsha: Adding color to graph for signalling model, check if given path has cubemesh or cylmesh + + color = '#FFFFFF' + if moose.exists(tableObject[0].path + '/info'): + color = getColor(tableObject[0].path + '/info') + color = str(color[1].name()).upper() + + lines = self.pathToLine[tab.path] + if len(lines) == 0: + #Harsha: pass color for plot if exist and not white else random color + #print "tab in plotAllData ",tab, tab.path,tab.name + field = tab.path.rpartition(".")[-1] + if field.endswith("[0]") or field.endswith("_0_"): + field = field[:-3] + # label = ( tableObject[0].path.partition(self.model.path + "/model[0]/")[-1] + # + "." + # + field + # ) + label = ( tableObject[0].path.rpartition("/")[-1] + + "." + + field + ) + self.makeRemovePlotAction(label, tab) + if (color != '#FFFFFF'): + newLines = self.addTimeSeries(tab, label=label,color=color) + else: + newLines = self.addTimeSeries(tab, label=label) + self.pathToLine[tab.path].update(newLines) + for line in newLines: + self.lineToDataSource[line] = PlotDataSource(x='/clock', y=tab.path, z='') + else: + for line in lines: + dataSrc = self.lineToDataSource[line] + xSrc = moose.element(dataSrc.x) + ySrc = moose.element(dataSrc.y) + if isinstance(xSrc, moose.Clock): + ts = np.linspace(0, time, len(tab.vector)) + elif isinstance(xSrc, moose.Table): + ts = xSrc.vector.copy() + line.set_data(ts, tab.vector.copy()) + tabList.append(tab) + + # if len(tabList) > 0: + self.legend = self.canvas.callAxesFn( 'legend' + , loc='upper right' + , prop= {'size' : 10 } + # , bbox_to_anchor=(1.0, 0.5) + , fancybox = True + , shadow=False + , ncol=1 + ) + if self.legend is not None: + self.legend.draggable() + self.legend.get_frame().set_alpha(0.5) + self.legend.set_visible(True) + + + self.canvas.draw() + + # # leg = self.canvas.callAxesFn( 'legend' + # # , loc ='upper right' + # # , prop = {'size' : 10 } + # # # , bbox_to_anchor = (0.5, -0.03) + # # , fancybox = False + # # # , shadow = True + # # , ncol = 1 + # # ) + # # leg.draggable(False) + # # print(leg.get_window_extent()) + # #leg = self.canvas.callAxesFn('legend') + # #leg = self.canvas.callAxesFn('legend',loc='upper left', fancybox=True, shadow=True) + # #global legend + # #legend =leg + # for legobj in leg.legendHandles: + # legobj.set_linewidth(5.0) + # legobj.set_picker(True) + # else: + # print "returning as len tabId is zero ",tabId, " tableObject ",tableObject, " len ",len(tableObject) + + def togglePlot(self, event): + #print "onclick",event1.artist.get_label() + #harsha:To workout with double-event-registered on onclick event + #http://stackoverflow.com/questions/16278358/double-event-registered-on-mouse-click-if-legend-is-outside-axes + legline = event.artist + for line in self.axesRef.lines: + if line.get_label() == event.artist.get_label(): + vis = not line.get_visible() + line.set_visible(vis) + if vis: + legline.set_alpha(1.0) + else: + legline.set_alpha(0.2) + break + self.canvas.draw() + + def addTimeSeries(self, table, *args, **kwargs): + ts = np.linspace(0, moose.Clock('/clock').currentTime, len(table.vector)) + return self.canvas.plot(ts, table.vector, *args, **kwargs) + + def addRasterPlot(self, eventtable, yoffset=0, *args, **kwargs): + """Add raster plot of events in eventtable. + + yoffset - offset along Y-axis. + """ + y = np.ones(len(eventtable.vector)) * yoffset + return self.canvas.plot(eventtable.vector, y, '|') + + def updatePlots(self): + for path, lines in self.pathToLine.items(): + element = moose.element(path) + if isinstance(element, moose.Table2): + tab = moose.Table2(path) + else: + tab = moose.Table(path) + data = tab.vector + ts = np.linspace(0, moose.Clock('/clock').currentTime, len(data)) + for line in lines: + line.set_data(ts, data) + self.canvas.draw() + + def extendXAxes(self, xlim): + for axes in self.canvas.axes.values(): + # axes.autoscale(False, axis='x', tight=True) + axes.set_xlim(right=xlim) + axes.autoscale_view(tight=True, scalex=True, scaley=True) + self.canvas.draw() + + def rescalePlots(self): + """This is to rescale plots at the end of simulation. + + ideally we should set xlim from simtime. + """ + for axes in self.canvas.axes.values(): + axes.autoscale(True, tight=True) + axes.relim() + axes.autoscale_view(tight=True,scalex=True,scaley=True) + self.canvas.draw() + + + def saveCsv(self, line, directory): + """Save selected plot data in CSV file""" + src = self.lineToDataSource[line] + xSrc = moose.element(src.x) + ySrc = moose.element(src.y) + y = ySrc.vector.copy() + if isinstance(xSrc, moose.Clock): + x = np.linspace(0, xSrc.currentTime, len(y)) + elif isinstance(xSrc, moose.Table): + x = xSrc.vector.copy() + filename = str(directory)+'/'+'%s.csv' % (ySrc.name) + np.savetxt(filename, np.vstack((x, y)).transpose()) + print 'Saved data from %s and %s in %s' % (xSrc.path, ySrc.path, filename) + + def saveAllCsv(self): + """Save data for all currently plotted lines""" + #Harsha: Plots were saved in GUI folder instead provided QFileDialog box to save to + #user choose + fileDialog2 = QtGui.QFileDialog(self) + fileDialog2.setFileMode(QtGui.QFileDialog.Directory) + fileDialog2.setWindowTitle('Select Directory to save plots') + fileDialog2.setOptions(QtGui.QFileDialog.ShowDirsOnly) + fileDialog2.setLabelText(QtGui.QFileDialog.Accept, self.tr("Save")) + targetPanel = QtGui.QFrame(fileDialog2) + targetPanel.setLayout(QtGui.QVBoxLayout()) + layout = fileDialog2.layout() + layout.addWidget(targetPanel) + if fileDialog2.exec_(): + directory = fileDialog2.directory().path() + for line in self.lineToDataSource.keys(): + self.saveCsv(line,directory) + + + def getMenus(self): + if not hasattr(self, '_menus'): + self._menus = [] + self.plotAllAction = QtGui.QAction('Plot all data', self) + self.plotAllAction.triggered.connect(self.plotAllData) + self.plotMenu = QtGui.QMenu('Plot') + self.plotMenu.addAction(self.plotAllAction) + self.saveAllCsvAction = QtGui.QAction('Save all data in CSV files', self) + self.saveAllCsvAction.triggered.connect(self.saveAllCsv) + self.plotMenu.addAction(self.saveAllCsvAction) + self._menus.append(self.plotMenu) + return self._menus + + # def resizeEvent(self, event): + # print("Here", event) + # self.canvas.figure.subplots_adjust(bottom=0.2)#, left = 0.18) + +################################################### +# +# Plot view - select fields to record +# +################################################### +''' +class PlotView(PlotBase): + """View for selecting fields on elements to plot.""" + def __init__(self, model, graph, index, *args): + PlotBase.__init__(self, *args) + self.model = model + self.graph = graph + self.index = index + # self.plugin.modelRootChanged.connect(self.getSelectionPane().setSearchRoot) + # self.plugin.dataRootChanged.connect(self.setDataRoot) + # self.dataRoot = self.plugin.dataRoot + + def setDataRoot(self, root): + self.dataRoot = moose.element(root).path + + def getToolPanes(self): + return (self.getFieldSelectionDock(), ) + + def getSelectionPane(self): + """Creates a widget to select elements and fields for plotting. + search-root, field-name, comparison operator , value + """ + if not hasattr(self, '_selectionPane'): + self._searchWidget = SearchWidget() + self._searchWidget.setSearchRoot(self.model.path) + self._fieldLabel = QtGui.QLabel('Field to plot') + self._fieldEdit = QtGui.QLineEdit() + self._fieldEdit.returnPressed.connect(self._searchWidget.searchSlot) + self._selectionPane = QtGui.QWidget() + layout = QtGui.QHBoxLayout() + layout.addWidget(self._fieldLabel) + layout.addWidget(self._fieldEdit) + self._searchWidget.layout().addLayout(layout) + self._selectionPane = self._searchWidget + self._selectionPane.layout().addStretch(1) + return self._selectionPane + + def getOperationsPane(self): + """TODO: complete this""" + if hasattr(self, 'operationsPane'): + return self.operationsPane + self.operationsPane = QtGui.QWidget() + self._createTablesButton = QtGui.QPushButton('Create tables for recording selected fields', self.operationsPane) + self._createTablesButton.clicked.connect(self.setupRecording) + layout = QtGui.QVBoxLayout() + self.operationsPane.setLayout(layout) + layout.addWidget(self._createTablesButton) + return self.operationsPane + + def getFieldSelectionDock(self): + if not hasattr(self, '_fieldSelectionDock'): + self._fieldSelectionDock = QtGui.QDockWidget('Search and select elements') + self._fieldSelectionWidget = QtGui.QWidget() + layout = QtGui.QVBoxLayout() + self._fieldSelectionWidget.setLayout(layout) + layout.addWidget(self.getSelectionPane()) + layout.addWidget(self.getOperationsPane()) + self._fieldSelectionDock.setWidget(self._fieldSelectionWidget) + return self._fieldSelectionDock + + def getCentralWidget(self): + if not hasattr(self, '_centralWidget') or self._centralWidget is None: + self._centralWidget = PlotSelectionWidget(self.model, self.graph) + self.getSelectionPane().executed.connect(self.selectElements) + return self._centralWidget + + def selectElements(self, elements): + """Refines the selection. + + Currently checks if _fieldEdit has an entry and if so, selects + only elements which have that field, and ticks the same in the + PlotSelectionWidget. + + """ + field = str(self._fieldEdit.text()).strip() + if len(field) == 0: + self.getCentralWidget().setSelectedElements(elements) + return + classElementDict = defaultdict(list) + for epath in elements: + el = moose.element(epath) + classElementDict[el.className].append(el) + refinedList = [] + elementFieldList = [] + for className, elist in classElementDict.items(): + if field in elist[0].getFieldNames('valueFinfo'): + refinedList +=elist + elementFieldList += [(el, field) for el in elist] + self.getCentralWidget().setSelectedElements(refinedList) + self.getCentralWidget().setSelectedFields(elementFieldList) + + + def setupRecording(self): + """Create the tables for recording selected data and connect them.""" + for element, field in self.getCentralWidget().getSelectedFields(): + #createRecordingTable(element, field, self._recordingDict, self._reverseDict, self.dataRoot) + #harsha:CreateRecordingTable function is moved to python/moose/utils.py file as create function + #as this is required when I drop table on to the plot + utils.create(self.plugin.modelRoot,moose.element(element),field,"Table2") + #self.dataTable.create(self.plugin.modelRoot, moose.element(element), field) + #self.updateCallback() + + def createRecordingTable(self, element, field): + """Create table to record `field` from element `element` + + Tables are created under `dataRoot`, the names are generally + created by removing `/model` in the beginning of `elementPath` + and replacing `/` with `_`. If this conflicts with an existing + table, the id value of the target element (elementPath) is + appended to the name. + + """ + if len(field) == 0 or ((element, field) in self._recordingDict): + return + # The table path is not foolproof - conflict is + # possible: e.g. /model/test_object and + # /model/test/object will map to same table. So we + # check for existing table without element field + # path in recording dict. + relativePath = element.path.partition('/model[0]/')[-1] + if relativePath.startswith('/'): + relativePath = relativePath[1:] + #Convert to camelcase + if field == "concInit": + field = "ConcInit" + elif field == "conc": + field = "Conc" + elif field == "nInit": + field = "NInit" + elif field == "n": + field = "N" + elif field == "volume": + field = "Volume" + elif field == "diffConst": + field ="DiffConst" + + tablePath = relativePath.replace('/', '_') + '.' + field + tablePath = re.sub('.', lambda m: {'[':'_', ']':'_'}.get(m.group(), m.group()),tablePath) + tablePath = self.dataRoot + '/' +tablePath + if moose.exists(tablePath): + tablePath = '%s_%d' % (tablePath, element.getId().value) + if not moose.exists(tablePath): + table = moose.Table(tablePath) + print 'Created', table.path, 'for plotting', '%s.%s' % (element.path, field) + target = element + moose.connect(table, 'requestOut', target, 'get%s' % (field)) + self._recordingDict[(target, field)] = table + self._reverseDict[table] = (target, field) +''' +class PlotSelectionWidget(QtGui.QScrollArea): + """Widget showing the fields of specified elements and their plottable + fields. User can select any number of fields for plotting and click a + button to generate the tables for recording data. + + The data tables are by default created under /data. One can call + setDataRoot with a path to specify alternate location. + + """ + def __init__(self, model, graph, *args): + QtGui.QScrollArea.__init__(self, *args) + self.model = moose.element(model.path + "/model") + self.modelRoot = self.model.path + self.setLayout(QtGui.QVBoxLayout(self)) + self.layout().addWidget(self.getPlotListWidget()) + self.setDataRoot(self.model.path) + self._elementWidgetsDict = {} # element path to corresponding qlabel and fields combo + + def getPlotListWidget(self): + """An internal widget to display the list of elements and their + plottable fields in comboboxes.""" + if not hasattr(self, '_plotListWidget'): + self._plotListWidget = QtGui.QWidget(self) + layout = QtGui.QGridLayout(self._plotListWidget) + self._plotListWidget.setLayout(layout) + layout.addWidget(QtGui.QLabel('<h1>Elements matching search criterion will be listed here</h1>'), 0, 0) + return self._plotListWidget + + def setSelectedElements(self, elementlist): + """Create a grid of widgets displaying paths of elements in + `elementlist` if it has at least one plottable field (a field + with a numeric value). The numeric fields are listed in a + combobox next to the element path and can be selected for + plotting by the user. + + """ + for ii in range(self.getPlotListWidget().layout().count()): + item = self.getPlotListWidget().layout().itemAt(ii) + if item is None: + continue + self.getPlotListWidget().layout().removeItem(item) + w = item.widget() + w.hide() + del w + del item + self._elementWidgetsDict.clear() + label = QtGui.QLabel('Element') + label.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.getPlotListWidget().layout().addWidget(label, 0, 0, 1, 2) + self.getPlotListWidget().layout().addWidget(QtGui.QLabel('Fields to plot'), 0, 2, 1, 1) + for ii, entry in enumerate(elementlist): + el = moose.element(entry) + plottableFields = [] + for field, dtype in moose.getFieldDict(el.className, 'valueFinfo').items(): + if dtype == 'double': + plottableFields.append(field) + if len(plottableFields) == 0: + continue + elementLabel = QtGui.QLabel(el.path) + fieldsCombo = CheckComboBox(self) + fieldsCombo.addItem('') + for item in plottableFields: + fieldsCombo.addItem(item) + self.getPlotListWidget().layout().addWidget(elementLabel, ii+1, 0, 1, 2) + self.getPlotListWidget().layout().addWidget(fieldsCombo, ii+1, 2, 1, 1) + self._elementWidgetsDict[el] = (elementLabel, fieldsCombo) + + def setModelRoot(self, root): + pass + + def setDataRoot(self, path): + """The tables will be created under dataRoot""" + pass + self.dataRoot = path + + def getSelectedFields(self): + """Returns a list containing (element, field) for all selected fields""" + ret = [] + for el, widgets in self._elementWidgetsDict.items(): + combo = widgets[1] + for ii in range(combo.count()): + field = str(combo.itemText(ii)).strip() + if len(field) == 0: + continue + checked, success = combo.itemData(ii, Qt.CheckStateRole).toInt() + if success and checked == Qt.Checked: + ret.append((el, field)) + return ret + + def setSelectedFields(self, elementFieldList): + """Set the checked fields for each element in elementFieldList. + + elementFieldList: ((element1, field1), (element2, field2), ...) + + """ + for el, field in elementFieldList: + combo = self._elementWidgetsDict[el][1] + idx = combo.findText(field) + if idx >= 0: + combo.setItemData(idx, QtCore.QVariant(Qt.Checked), Qt.CheckStateRole) + combo.setCurrentIndex(idx) +# +# default.py ends here diff --git a/moose-gui/plugins/defines.py b/moose-gui/plugins/defines.py new file mode 100644 index 0000000000000000000000000000000000000000..0f550e46f0e59b60e370d1081a7adfc3e3d61622 --- /dev/null +++ b/moose-gui/plugins/defines.py @@ -0,0 +1,7 @@ +ELECTRICAL_SIMULATION_DT_CLOCKS = [1,2,3,4,5,6,7] +ELECTRICAL_PLOT_UPDATE_INTERVAL_CLOCKS = [8] +ELECTRICAL_DIFFUSION_INTERVAL_CLOCKS = [10] + +CHEMICAL_SIMULATION_DT_CLOCKS = [11, 12, 13, 14, 15, 16, 17] +CHEMICAL_PLOT_UPDATE_INTERVAL_CLOCKS = [18] +CHEMICAL_DIFFUSION_DT_CLOCKS = [10] diff --git a/moose-gui/plugins/kkit.py b/moose-gui/plugins/kkit.py new file mode 100644 index 0000000000000000000000000000000000000000..44b5f27e16820a9c2a1faf8187b841a787727ff5 --- /dev/null +++ b/moose-gui/plugins/kkit.py @@ -0,0 +1,961 @@ +import sys +from PyQt4 import QtGui, QtCore, Qt +from default import * +from moose import * +from moose.genesis import write +#sys.path.append('plugins') +from mplugin import * +from kkitUtil import * +from kkitQGraphics import PoolItem, ReacItem,EnzItem,CplxItem,ComptItem +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': + writeerror = moose.writeSBML(self.modelRoot,str(filename)) + 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.') + 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': + #self.test = KkitEditorView(self).getCentralWidget().mooseId_GObj + filename = filename + self.test = None + writeerror = write(self.modelRoot,str(filename),self.test) + if writeerror == False: + QtGui.QMessageBox.information(None,'Could not save the Model','\nCheck the file') + else: + QtGui.QMessageBox.information(None,'Saved the Model','\n File saved to \'{filename}\''.format(filename =filename+'.g'),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 AnotherKkitRunViewsCentralWidget(QWidget): + +# def __init__(): +# QWidget.__init__() + +# def + +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.defaultComptsize = 5 + self.noPositionInfo = True + self.xyCord = {} + self.reset() + self.qGraCompt = {} + self.mooseId_GObj = {} + self.srcdesConnection = {} + self.editor = None + + def reset(self): + #print "reset " + 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) + 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() + 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) + 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) + 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.xmin = 0.0 + self.xmax = 1.0 + self.ymin = 0.0 + self.ymax = 1.0 + self.autoCordinatepos = {} + self.srcdesConnection = {} + + #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.autocoordinates = False + if self.srcdesConnection: + self.srcdesConnection.clear() + else: + self.srcdesConnection = {} + setupItem(self.modelRoot,self.srcdesConnection) + if not self.noPositionInfo: + self.autocoordinates = True + + self.xmin,self.xmax,self.ymin,self.ymax,self.autoCordinatepos = autoCoordinates(self.meshEntry,self.srcdesConnection) + # TODO: size will be dummy at this point, but size I need the availiable size from the Gui + 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) + + 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.parent).path+'/info' + funcParent =self.mooseId_GObj[element(funcObj.parent)] + 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.comptChilrenBoundingRect() + + + def comptChilrenBoundingRect(self): + for k, v in self.qGraCompt.items(): + # compartment's rectangle size is calculated depending on children + #rectcompt = v.childrenBoundingRect() + 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") + else: + textcolor,bgcolor = getColor(info) + if bgcolor.name() == "#ffffff" or bgcolor == "white": + bgcolor = getRandColor() + Annoinfo.color = str(bgcolor.name()) + if isinstance(self,kineticEditorWidget): + 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) + + def positioninfo(self,iteminfo): + Anno = moose.Annotator(self.modelRoot+'/info') + if not self.noPositionInfo: + try: + # kkit does exist item's/info which up querying for parent.path gives the information of item's parent + x,y = self.autoCordinatepos[(element(iteminfo).parent).path] + except: + # But in Cspace reader doesn't create item's/info, up on querying gives me the error which need to change\ + # in ReadCspace.cpp, at present i am taking care b'cos i don't want to pass just the item where I need to check\ + # type of the object (rea,pool,enz,cplx,tab) which I have already done. + parent, child = posixpath.split(iteminfo) + x,y = self.autoCordinatepos[parent] + ypos = (y-self.ymin)*self.yratio + else: + x = float(element(iteminfo).getField('x')) + y = float(element(iteminfo).getField('y')) + #Qt origin is at the top-left corner. The x values increase to the right and the y values increase downwards \ + #as compared to Genesis codinates where origin is center and y value is upwards, that is why ypos is negated + if Anno.modeltype == "kkit": + ypos = 1.0-(y-self.ymin)*self.yratio + else: + ypos = (y-self.ymin)*self.yratio + xpos = (x-self.xmin)*self.xratio + + return(xpos,ypos) + + 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: + print "Func pool 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.path+'/info' + color,bgcolor = getColor(pinfo) + #color = QColor(color[0],color[1],color[2]) + pen.setColor(color) + 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 = mooseObject + 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) + 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') + for k, v in self.qGraCompt.items(): + rectcompt = v.childrenBoundingRect() + if linfo.modeltype == "new_kkit": + #if newly built model then compartment is size is fixed for some size. + comptBoundingRect = v.boundingRect() + if not comptBoundingRect.contains(rectcompt): + self.updateCompartmentSize(v) + else: + #if already built model then compartment size depends on max and min objects + rectcompt = calculateChildBoundingRect(v) + v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20)) + + def updateCompartmentSize(self, compartment): + compartmentBoundary = compartment.rect() + #childrenBoundary = compartment.childrenBoundingRect() + 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): + self.cplxUpdatearrow(srcdes[0]) + elif( type(srcdes[1]) == EnzItem): + 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 deleteSolver(self): + # print " delete Solver" + # print "### ",moose.wildcardFind(self.modelRoot+'/data/graph#/#') + # if moose.wildcardFind(self.modelRoot+'/##[ISA=ChemCompt]'): + # compt = moose.wildcardFind(self.modelRoot+'/##[ISA=ChemCompt]') + # print " deletSolver ", + # # print moose.exists(compt[0].path+'/stoich'), " ksolve ", moose.exists(compt[0].path+'/ksolve') + # # print "gsolve ", moose.delete( compt[0].path+'/gsolve' ) + # if ( moose.exists( compt[0].path+'/stoich' ) ): + # #print "delete" + # moose.delete( compt[0].path+'/stoich' ) + # if ( moose.exists( compt[0].path+'/ksolve' ) ): + # moose.delete( compt[0].path+'/ksolve' ) + # if ( moose.exists( compt[0].path+'/gsolve' ) ): + # moose.delete( compt[0].path+'/gsolve' ) + # for x in moose.wildcardFind( self.modelRoot+'/data/graph#/#' ): + # x.tick = -1 + 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 + self.insertMenu = QtGui.QMenu('&Insert') + self._menus.append(self.insertMenu) + self.insertMapper = QtCore.QSignalMapper(self) + classlist = ['CubeMesh','CylMesh','Pool','BufPool','Function','Reac','Enz','MMenz','StimulusTable'] + self.toolTipinfo = { "CubeMesh":"", + "CylMesh" : "", + "Pool":"A Pool is a collection of molecules of a given species in a given cellular compartment.\n It can undergo reactions that convert it into other pool(s). \nParameters: initConc (Initial concentration), diffConst (diffusion constant). Variable: conc (Concentration)", + "BufPool":"A BufPool is a buffered pool. \nIt is a collection of molecules of a given species in a given cellular compartment, that are always present at the same concentration.\n This is set by the initConc parameter. \nIt can undergo reactions in the same way as a pool.", + "Function":"A Func computes an arbitrary mathematical expression of one or more input concentrations of Pools. The output can be used to control the concentration of another Pool, or as an input to another Func", + "StimulusTable":"A StimulusTable stores an array of values that are read out during a simulation, and typically control the concentration of one of the pools in the model. \nParameters: size of table, values of entries, start and stop times, and an optional loopTime that defines the period over which the StimulusTable should loop around to repeat its values", + "Reac":"A Reac is a chemical reaction that converts substrates into products, and back. \nThe rates of these conversions are specified by the rate constants Kf and Kb respectively.", + "MMenz":"An MMenz is the Michaelis-Menten version of an enzyme activity of a given Pool.\n The MMenz must be created on a pool and can only catalyze a single reaction with a specified substrate(s). \nIf a given enzyme species can have multiple substrates, then multiple MMenz activites must be created on the parent Pool. \nThe rate of an MMenz is V [S].[E].kcat/(Km + [S]). There is no enzyme-substrate complex. Parameters: Km and kcat.", + "Enz":"An Enz is an enzyme activity of a given Pool. The Enz must be created on a pool and can only catalyze a single reaction with a specified substrate(s). \nIf a given enzyme species can have multiple substrates, then multiple Enz activities must be created on the parent Pool. \nThe reaction for an Enz is E + S <===> E.S ---> E + P. \nThis means that a new Pool, the enzyme-substrate complex E.S, is always formed when you create an Enz. \nParameters: Km and kcat, or alternatively, K1, K2 and K3. Km = (K2+K3)/K1" + + } + insertMapper, actions = self.getInsertActions(classlist) + for action in actions: + self.insertMenu.addAction(action) + doc = self.toolTipinfo[str(action.text())] + if doc == "": + classname = str(action.text()) + doc = moose.element('/classes/%s' % (classname)).docs + doc = doc.split('Description:')[-1].split('Name:')[0].strip() + action.setToolTip(doc) + + def GrViewresize(self,event): + #when Gui resize and event is sent which inturn call resizeEvent of qgraphicsview + pass + #self.view.resizeEvent1(event) + + def makePoolItem(self, poolObj, qGraCompt): + return PoolItem(poolObj, qGraCompt) + + def getToolBars(self): + #Add specific tool items with respect to kkit + if not hasattr(self, '_insertToolBar'): + self._insertToolBar = QtGui.QToolBar('Insert') + self._toolBars.append(self._insertToolBar) + for action in self.insertMenu.actions(): + button = MToolButton() + button.setDefaultAction(action) + #set the unicode instead of image by setting + #button.setText(unicode(u'\u20de')) + Iconpath = os.path.join(config.MOOSE_GUI_DIR, 'icons/classIcon/') + button.setIcon(QtGui.QIcon(Iconpath+action.text()+".png")) + #button.setIcon(QtGui.QIcon("icons/classIcon/"+action.text()+".png")) + #button.setIconSize(QtCore.QSize(200,200)) + self._insertToolBar.addWidget(button) + return self._toolBars + +class kineticRunWidget(KineticsWidget): + def __init__(self, plugin, *args): + KineticsWidget.__init__(self, plugin,*args) + + def showEvent(self, event): + self.refresh() + # pass + def refresh(self): + self.sceneContainer.clear() + self.Comptexist = wildcardFind(self.modelRoot+'/##[ISA=ChemCompt]') + if self.Comptexist: + # pass + self.getMooseObj() + self.mooseObjOntoscene() + self.drawLine_arrow(itemignoreZooming=False) + + def makePoolItem(self, poolObj, qGraCompt): + return PoolItemCircle(poolObj, qGraCompt) + + def getToolBars(self): + return self._toolBars + + def updateValue(self): + for item in self.sceneContainer.items(): + if isinstance(item,ReacItem) or isinstance(item,MMEnzItem) or isinstance(item,EnzItem) or isinstance(item,PoolItemCircle) or isinstance(item,CplxItem): + item.updateValue(item.mobj) + + def changeBgSize(self): + for item in self.sceneContainer.items(): + if isinstance(item,PoolItemCircle): + initialConc = moose.element(item.mobj).concInit + presentConc = moose.element(item.mobj).conc + if initialConc != 0: + ratio = presentConc/initialConc + else: + # multipying by 1000 b'cos moose concentration is in milli in moose + ratio = presentConc + #print "ratio",item.mobj,ratio + if ratio > '10': + ratio = 9 + if ratio < '0.0': + ratio =0.1 + #print "size ",ratio + item.updateRect(math.sqrt(abs(ratio))) + + def resetColor(self): + for item in self.sceneContainer.items(): + if isinstance(item,PoolItemCircle): + item.returnEllispeSize() + + # def addSolver(self,solver): + # print "\t addSolver--------" + # compt = moose.wildcardFind(self.modelRoot+'/##[ISA=ChemCompt]') + # comptinfo = moose.Annotator(moose.element(compt[0]).path+'/info') + # print " $$$$$$$$$$$$$$ ",moose.element(compt[0].path) + # previousSolver = comptinfo.solver + + # print "pre solver from kkit ",previousSolver, solver + # currentSolver = previousSolver + # if solver == "Gillespie": + # currentSolver = "Gillespie" + # elif solver == "Runge Kutta": + # currentSolver = "Runge Kutta" + # elif solver == " Exponential Euler": + # currentSolver == "Exponential Euler" + + # if previousSolver != currentSolver: + # if ( moose.exists( compt[0].path+'/stoich' ) ): + # print "1" + # self.deleteSolver() + # self.setCompartmentSolver(compt,currentSolver) + # elif ( moose.exists( compt[0].path+'/stoich' ) ): + # print "2" + # self.setCompartmentSolver(compt, currentSolver) + # comptinfo.solver = currentSolver + # else: + # print "3", moose.exists(compt[0].path+'/stoich') + # if not ( moose.exists( compt[0].path+'/stoich' ) ): + # self.setCompartmentSolver(compt,currentSolver) + # for x in moose.wildcardFind( self.modelRoot+'/data/graph#/#' ): + # x.tick = 18 + # #self.solverStatus() + # def setCompartmentSolver(self,compt,solver): + # if solver == 'GSL' or solver == "Runge Kutta": + # solver = 'gsl' + # elif solver == 'Gillespie': + # solver = 'gssa' + # elif solver == "Exponential Euler": + # solver = 'ee' + # print "setCompartmentSolver ",solver + # if ( solver == 'gsl' ): + # ksolve = moose.Ksolve( compt[0].path+'/ksolve' ) + # if ( solver == 'gssa' ): + # ksolve = moose.Gsolve( compt[0].path+'/gsolve' ) + # if (solver!= 'ee'): + # stoich = moose.Stoich( compt[0].path+'/stoich' ) + # stoich.compartment = compt[0] + # stoich.ksolve = ksolve + # stoich.path = compt[0].path+'/##' + # moose.reinit() + +if __name__ == "__main__": + app = QtGui.QApplication(sys.argv) + size = QtCore.QSize(1024 ,768) + #modelPath = 'Kholodenko' + modelPath = 'acc27' + #modelPath = 'acc8' + #modelPath = '3ARECB' + #modelPath = '3AreacB' + #modelPath = '5AreacB' + itemignoreZooming = False + try: + filepath = '../../Demos/Genesis_files/'+modelPath+'.g' + filepath = '/home/harsha/genesis_files/gfile/'+modelPath+'.g' + print filepath + f = open(filepath, "r") + loadModel(filepath,'/'+modelPath) + + #moose.le('/'+modelPath+'/kinetics') + dt = KineticsWidget() + dt.modelRoot ='/'+modelPath + ''' Loading moose signalling model in python ''' + #execfile('/home/harsha/BuildQ/Demos/Genesis_files/scriptKineticModel.py') + #dt.modelRoot = '/model' + + dt.updateModelView() + dt.show() + + except IOError, what: + (errno, strerror) = what + print "Error number",errno,"(%s)" %strerror + sys.exit(0) + sys.exit(app.exec_()) diff --git a/moose-gui/plugins/kkitCalcArrow.py b/moose-gui/plugins/kkitCalcArrow.py new file mode 100644 index 0000000000000000000000000000000000000000..e11ebe3ff29d3110751239f00782dd1f260143ed --- /dev/null +++ b/moose-gui/plugins/kkitCalcArrow.py @@ -0,0 +1,162 @@ +from PyQt4.QtGui import QPolygonF +from PyQt4.QtCore import QLineF,QPointF +import math +from kkitQGraphics import PoolItem #, ReacItem,EnzItem,CplxItem,ComptItem + +''' One to need to pass the source, destination,endtype and order for drawing the arrow between 2 object \ + endtype is to check if needs arrow head (arrowhead for product and sumtotal) \ + order for higher order reaction +''' +def calcArrow(srcdes_list,itemignoreZooming,iconScale): + ''' if PoolItem then boundingrect should be background rather than graphicsobject ''' + src = srcdes_list[0] + des = srcdes_list[1] + endtype = srcdes_list[2] + order = srcdes_list[3] + # print("Source => ", src) + compartment = src.parentItem() + srcobj = src.gobj + desobj = des.gobj + if isinstance(src,PoolItem): + srcobj = src.bg + if isinstance(des,PoolItem): + desobj = des.bg + + # if itemignoreZooming: + # srcRect = self.recalcSceneBoundingRect(srcobj) + # desRect = self.recalcSceneBoundingRect(desobj) + # else: + srcRect = compartment.mapFromScene(srcobj.sceneBoundingRect()).boundingRect() + desRect = compartment.mapFromScene(desobj.sceneBoundingRect()).boundingRect() + arrow = QPolygonF() + if srcRect.intersects(desRect): + ''' This is created for getting a emptyline reference \ + because 'lineCord' function keeps a reference between qgraphicsline and its src and des + ''' + arrow.append(QPointF(0,0)) + arrow.append(QPointF(0,0)) + return arrow + if (order == 0): + tmpLine = QLineF(srcRect.center().x(), + srcRect.center().y(), + desRect.center().x(), + desRect.center().y()) + elif(order > 0): + dx = desRect.center().x()- srcRect.center().x() + dy = desRect.center().y()- srcRect.center().y() + dx0 = dy + dy0 = -dx + tetha1 = (math.atan2(dy0,dx0)) + a0 = 4 *(math.cos(tetha1)) + b0 = 4 *(math.sin(tetha1)) + ''' Higher order ( > 4) connectivity will not be done''' + if ((order == 3) or (order == 4)): + a0 = a0*2 + b0 = b0*2 + if(order %2 == 0): + srcCentera0 = srcRect.center().x()-a0 + srcCenterb0 = srcRect.center().y()-b0 + desCentera0 = desRect.center().x()-a0 + desCenterb0 = desRect.center().y()-b0 + else: + srcCentera0 = srcRect.center().x()+a0 + srcCenterb0 = srcRect.center().y()+b0 + desCentera0 = desRect.center().x()+a0 + desCenterb0 = desRect.center().y()+b0 + pointa = QPointF(srcCentera0,srcCenterb0) + pointb = QPointF(desCentera0,desCenterb0) + tmpLine = QLineF(srcCentera0,srcCenterb0,desCentera0,desCenterb0) + + srcIntersects, lineSrcPoint = calcLineRectIntersection(srcRect, tmpLine) + destIntersects, lineDestPoint = calcLineRectIntersection(desRect, tmpLine) + + if not srcIntersects: + print 'Source does not intersect line. Arrow points:',lineSrcPoint,src.mobj.name, src.mobj.className + if not destIntersects: + print 'Dest does not intersect line. Arrow points:', lineDestPoint, des.mobj.name, des.mobj.className + + '''src and des are connected with line co-ordinates + Arrow head is drawned if the distance between src and des line is >8 just for clean appeareance + ''' + if (abs(lineSrcPoint.x()-lineDestPoint.x()) > 8 or abs(lineSrcPoint.y()-lineDestPoint.y())>8): + srcAngle = tmpLine.angle() + if endtype == 'p' or endtype == 'stp': + ''' Arrow head for Destination is calculated''' + arrow.append(lineSrcPoint) + arrow.append(lineDestPoint) + degree = -60 + srcXArr1,srcYArr1= arrowHead(srcAngle,degree,lineDestPoint,iconScale) + arrow.append(QPointF(srcXArr1,srcYArr1)) + arrow.append(QPointF(lineDestPoint.x(),lineDestPoint.y())) + + degree = -120 + srcXArr2,srcYArr2 = arrowHead(srcAngle,degree,lineDestPoint,iconScale) + arrow.append(QPointF(srcXArr2,srcYArr2)) + arrow.append(QPointF(lineDestPoint.x(),lineDestPoint.y())) + + elif endtype == 'st': + ''' Arrow head for Source is calculated''' + arrow.append(lineDestPoint) + arrow.append(lineSrcPoint) + degree = 60 + srcXArr2,srcYArr2 = arrowHead(srcAngle,degree,lineSrcPoint,iconScale) + arrow.append(QPointF(srcXArr2,srcYArr2)) + arrow.append(QPointF(lineSrcPoint.x(),lineSrcPoint.y())) + + degree = 120 + srcXArr1,srcYArr1= arrowHead(srcAngle,degree,lineSrcPoint,iconScale) + arrow.append(QPointF(srcXArr1,srcYArr1)) + arrow.append(QPointF(lineSrcPoint.x(),lineSrcPoint.y())) + + elif endtype == 's' or endtype == 'sts': + arrow.append(lineDestPoint) + arrow.append(lineSrcPoint) + + degree = 60 + srcXArr2,srcYArr2 = arrowHead(srcAngle,degree,lineSrcPoint,iconScale) + arrow.append(QPointF(srcXArr2,srcYArr2)) + arrow.append(QPointF(lineSrcPoint.x(),lineSrcPoint.y())) + + degree = 120 + srcXArr1,srcYArr1= arrowHead(srcAngle,degree,lineSrcPoint,iconScale) + arrow.append(QPointF(srcXArr1,srcYArr1)) + arrow.append(QPointF(lineSrcPoint.x(),lineSrcPoint.y())) + else: + arrow.append(lineSrcPoint) + arrow.append(lineDestPoint) + return arrow + +def calcLineRectIntersection(rect, centerLine): + ''' checking which side of rectangle intersect with centerLine \ + Here the 1. a. intersect point between center and 4 sides of src and \ + b. intersect point between center and 4 sides of des and \ + to draw a line connecting for src & des + 2. angle for src for the arrow head calculation is returned + ''' + x = rect.x() + y = rect.y() + w = rect.width() + h = rect.height() + borders = [(x,y,x+w,y), + (x+w,y,x+w,y+h), + (x+w,y+h,x,y+h), + (x,y+h,x,y)] + intersectionPoint = QPointF() + intersects = False + for lineEnds in borders: + line = QLineF(*lineEnds) + intersectType = centerLine.intersect(line, intersectionPoint) + if intersectType == centerLine.BoundedIntersection: + intersects = True + break + return (intersects, intersectionPoint) + +def arrowHead(srcAngle,degree,lineSpoint,iconScale): + ''' arrow head is calculated ''' + r = 8*iconScale + delta = math.radians(srcAngle) + math.radians(degree) + width = math.sin(delta)*r + height = math.cos(delta)*r + srcXArr = (lineSpoint.x() + width) + srcYArr = (lineSpoint.y() + height) + return srcXArr,srcYArr diff --git a/moose-gui/plugins/kkitOrdinateUtil.py b/moose-gui/plugins/kkitOrdinateUtil.py new file mode 100644 index 0000000000000000000000000000000000000000..36e8e833251bfbaaab70b2ad06264d98ad15f918 --- /dev/null +++ b/moose-gui/plugins/kkitOrdinateUtil.py @@ -0,0 +1,246 @@ +from moose import * +import numpy as np +import networkx as nx +from collections import Counter + +def xyPosition(objInfo,xory): + try: + return(float(element(objInfo).getField(xory))) + except ValueError: + return (float(0)) + +def setupMeshObj(modelRoot): + ''' Setup compartment and its members pool,reaction,enz cplx under self.meshEntry dictionaries \ + self.meshEntry with "key" as compartment, + value is key2:list where key2 represents moose object type,list of objects of a perticular type + e.g self.meshEntry[meshEnt] = { 'reaction': reaction_list,'enzyme':enzyme_list,'pool':poollist,'cplx': cplxlist } + ''' + xmin = 0.0 + xmax = 1.0 + ymin = 0.0 + ymax = 1.0 + positionInfoExist = True + meshEntry = {} + if meshEntry: + meshEntry.clear() + else: + meshEntry = {} + xcord = [] + ycord = [] + meshEntryWildcard = '/##[ISA=ChemCompt]' + if modelRoot != '/': + meshEntryWildcard = modelRoot+meshEntryWildcard + for meshEnt in wildcardFind(meshEntryWildcard): + mollist = [] + realist = [] + enzlist = [] + cplxlist = [] + tablist = [] + funclist = [] + + mol_cpl = wildcardFind(meshEnt.path+'/##[ISA=PoolBase]') + funclist = wildcardFind(meshEnt.path+'/##[ISA=Function]') + enzlist = wildcardFind(meshEnt.path+'/##[ISA=EnzBase]') + realist = wildcardFind(meshEnt.path+'/##[ISA=ReacBase]') + tablist = wildcardFind(meshEnt.path+'/##[ISA=StimulusTable]') + if mol_cpl or funclist or enzlist or realist or tablist: + for m in mol_cpl: + if isinstance(element(m.parent),CplxEnzBase): + cplxlist.append(m) + objInfo = m.parent.path+'/info' + elif isinstance(element(m),moose.PoolBase): + mollist.append(m) + objInfo =m.path+'/info' + xcord.append(xyPosition(objInfo,'x')) + ycord.append(xyPosition(objInfo,'y')) + + getxyCord(xcord,ycord,funclist) + getxyCord(xcord,ycord,enzlist) + getxyCord(xcord,ycord,realist) + getxyCord(xcord,ycord,tablist) + + meshEntry[meshEnt] = {'enzyme':enzlist, + 'reaction':realist, + 'pool':mollist, + 'cplx':cplxlist, + 'table':tablist, + 'function':funclist + } + xmin = min(xcord) + xmax = max(xcord) + ymin = min(ycord) + ymax = max(ycord) + positionInfoExist = not(len(np.nonzero(xcord)[0]) == 0 \ + and len(np.nonzero(ycord)[0]) == 0) + return(meshEntry,xmin,xmax,ymin,ymax,positionInfoExist) + +def sizeHint(self): + return QtCore.QSize(800,400) +def getxyCord(xcord,ycord,list1): + for item in list1: + # if isinstance(item,Function): + # objInfo = moose.element(item.parent).path+'/info' + # else: + # objInfo = item.path+'/info' + if not isinstance(item,Function): + objInfo = item.path+'/info' + xcord.append(xyPosition(objInfo,'x')) + ycord.append(xyPosition(objInfo,'y')) + +def setupItem(modelPath,cntDict): + '''This function collects information of what is connected to what. \ + eg. substrate and product connectivity to reaction's and enzyme's \ + sumtotal connectivity to its pool are collected ''' + #print " setupItem" + sublist = [] + prdlist = [] + zombieType = ['ReacBase','EnzBase','Function','StimulusTable'] + for baseObj in zombieType: + path = '/##[ISA='+baseObj+']' + if modelPath != '/': + path = modelPath+path + if ( (baseObj == 'ReacBase') or (baseObj == 'EnzBase')): + for items in wildcardFind(path): + sublist = [] + prdlist = [] + uniqItem,countuniqItem = countitems(items,'subOut') + subNo = uniqItem + for sub in uniqItem: + sublist.append((element(sub),'s',countuniqItem[sub])) + + uniqItem,countuniqItem = countitems(items,'prd') + prdNo = uniqItem + if (len(subNo) == 0 or len(prdNo) == 0): + print "Substrate Product is empty ",path, " ",items + + for prd in uniqItem: + prdlist.append((element(prd),'p',countuniqItem[prd])) + + if (baseObj == 'CplxEnzBase') : + uniqItem,countuniqItem = countitems(items,'toEnz') + for enzpar in uniqItem: + sublist.append((element(enzpar),'t',countuniqItem[enzpar])) + + uniqItem,countuniqItem = countitems(items,'cplxDest') + for cplx in uniqItem: + prdlist.append((element(cplx),'cplx',countuniqItem[cplx])) + + if (baseObj == 'EnzBase'): + uniqItem,countuniqItem = countitems(items,'enzDest') + for enzpar in uniqItem: + sublist.append((element(enzpar),'t',countuniqItem[enzpar])) + cntDict[items] = sublist,prdlist + elif baseObj == 'Function': + for items in wildcardFind(path): + sublist = [] + prdlist = [] + item = items.path+'/x[0]' + uniqItem,countuniqItem = countitems(item,'input') + for funcpar in uniqItem: + sublist.append((element(funcpar),'sts',countuniqItem[funcpar])) + + uniqItem,countuniqItem = countitems(items,'valueOut') + for funcpar in uniqItem: + prdlist.append((element(funcpar),'stp',countuniqItem[funcpar])) + cntDict[items] = sublist,prdlist + + # elif baseObj == 'Function': + # #ZombieSumFunc adding inputs + # inputlist = [] + # outputlist = [] + # funplist = [] + # nfunplist = [] + # for items in wildcardFind(path): + # for funplist in moose.element(items).neighbors['valueOut']: + # for func in funplist: + # funcx = moose.element(items.path+'/x[0]') + # uniqItem,countuniqItem = countitems(funcx,'input') + # for inPut in uniqItem: + # inputlist.append((inPut,'st',countuniqItem[inPut])) + # cntDict[func] = inputlist + else: + for tab in wildcardFind(path): + tablist = [] + uniqItem,countuniqItem = countitems(tab,'output') + for tabconnect in uniqItem: + tablist.append((element(tabconnect),'tab',countuniqItem[tabconnect])) + cntDict[tab] = tablist + +def countitems(mitems,objtype): + items = [] + #print "mitems in countitems ",mitems,objtype + items = element(mitems).neighbors[objtype] + uniqItems = set(items) + countuniqItems = Counter(items) + return(uniqItems,countuniqItems) + +def autoCoordinates(meshEntry,srcdesConnection): + #for cmpt,memb in meshEntry.items(): + # print memb + xmin = 0.0 + xmax = 1.0 + ymin = 0.0 + ymax = 1.0 + G = nx.Graph() + for cmpt,memb in meshEntry.items(): + for enzObj in find_index(memb,'enzyme'): + G.add_node(enzObj.path) + for cmpt,memb in meshEntry.items(): + for poolObj in find_index(memb,'pool'): + G.add_node(poolObj.path) + for cplxObj in find_index(memb,'cplx'): + G.add_node(cplxObj.path) + G.add_edge((cplxObj.parent).path,cplxObj.path) + for reaObj in find_index(memb,'reaction'): + G.add_node(reaObj.path) + + for inn,out in srcdesConnection.items(): + if (inn.className =='ZombieReac'): arrowcolor = 'green' + elif(inn.className =='ZombieEnz'): arrowcolor = 'red' + else: arrowcolor = 'blue' + if isinstance(out,tuple): + if len(out[0])== 0: + print inn.className + ':' +inn.name + " doesn't have input message" + else: + for items in (items for items in out[0] ): + G.add_edge(element(items[0]).path,inn.path) + if len(out[1]) == 0: + print inn.className + ':' + inn.name + "doesn't have output mssg" + else: + for items in (items for items in out[1] ): + G.add_edge(inn.path,element(items[0]).path) + elif isinstance(out,list): + if len(out) == 0: + print "Func pool doesn't have sumtotal" + else: + for items in (items for items in out ): + G.add_edge(element(items[0]).path,inn.path) + + nx.draw(G,pos=nx.spring_layout(G)) + #plt.savefig('/home/harsha/Desktop/netwrokXtest.png') + xcord = [] + ycord = [] + position = nx.spring_layout(G) + for item in position.items(): + xy = item[1] + ann = moose.Annotator(item[0]+'/info') + ann.x = xy[0] + xcord.append(xy[0]) + ann.y = xy[1] + ycord.append(xy[1]) + # for y in position.values(): + # xcord.append(y[0]) + # ycord.append(y[1]) + if xcord and ycord: + xmin = min(xcord) + xmax = max(xcord) + ymin = min(ycord) + ymax = max(ycord) + return(xmin,xmax,ymin,ymax,position) + +def find_index(value, key): + """ Value.get(key) to avoid expection which would raise if empty value in dictionary for a given key """ + if value.get(key) != None: + return value.get(key) + else: + raise ValueError('no dict with the key found') diff --git a/moose-gui/plugins/kkitQGraphics.py b/moose-gui/plugins/kkitQGraphics.py new file mode 100644 index 0000000000000000000000000000000000000000..222a07d4764ed16b4b9541e88e5f0b42133d0762 --- /dev/null +++ b/moose-gui/plugins/kkitQGraphics.py @@ -0,0 +1,646 @@ +#import sys +#sys.path.insert(0, '/home/harsha/trunk/gui') +import config +from PyQt4 import QtGui, QtCore, Qt +from moose import * +from PyQt4.QtGui import QPixmap, QImage, QGraphicsPixmapItem +from constants import * + +class KineticsDisplayItem(QtGui.QGraphicsWidget): + """Base class for display elemenets in kinetics layout""" + name = ITEM + defaultFontName = "Helvetica" + defaultFontSize = 10 + def __init__(self, mooseObject, parent=None): + QtGui.QGraphicsObject.__init__(self,parent) + self.mobj = mooseObject + self.gobj = None + self.pressed = False + self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable,True) + self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True) + self.setAcceptHoverEvents(True) + self.setFocusPolicy(QtCore.Qt.StrongFocus) + if QtCore.QT_VERSION >= 0x040600: + self.setFlag(QtGui.QGraphicsItem.ItemSendsGeometryChanges,1) + self.setFlag(QtGui.QGraphicsItem.ItemIgnoresTransformations, False) + + def getParentMooseObject(self): + return moose.element(self.mobj).parent + + def getParentGraphicsObject(self): + return self.parentItem() + + def setDisplayProperties(self, dinfo): + self.setGeometry(dinfo.x, dinfo.y) + + def paint(self, painter=None, option=None, widget = None): + #If item is selected + if self.hasFocus() or self.isSelected(): + painter.setPen(QtGui.QPen(QtGui.QPen(QtCore.Qt.black, 1.8,Qt.Qt.DashLine, Qt.Qt.RoundCap, Qt.Qt.RoundJoin))) + painter.drawRect(self.boundingRect()) + # def mouseDoubleClickEvent(self, event): + # self.emit(QtCore.SIGNAL("qgtextDoubleClick(PyQt_PyObject)"),element(self.mobj)) + + def itemChange(self,change,value): + #pass + #if change == QtGui.QGraphicsItem.ItemPositionChange: + #print "itemChange ---->",self.mobj + # self.emit(QtCore.SIGNAL("qgtextPositionChange(PyQt_PyObject)"),self.mobj) + if change == QtGui.QGraphicsItem.ItemSelectedChange and value == True: + self.emit(QtCore.SIGNAL("qgtextItemSelectedChange(PyQt_PyObject)"),element(self.mobj)) + #print " itemChange ",self.mobj,change,value + return QtGui.QGraphicsItem.itemChange(self,change,value) + +class FuncItem(KineticsDisplayItem): + name = ITEM + """Class for displaying Functions""" + #fontMetrics = None + font =QtGui.QFont(KineticsDisplayItem.defaultFontName) + font.setPointSize(KineticsDisplayItem.defaultFontSize) + fontMetrics = QtGui.QFontMetrics(font) + def __init__(self, mobj, parent): + super(FuncItem, self).__init__(mobj, parent) + self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, False) + self.funcImage = QImage('icons/classIcon/Function.png').scaled(15,33) + self.bg = QtGui.QGraphicsRectItem(self) + self.bg.setAcceptHoverEvents(True) + self.gobj = QtGui.QGraphicsPixmapItem(QtGui.QPixmap.fromImage(self.funcImage),self.bg) + #self.gobj = QtGui.QGraphicsPixmapItem(QtGui.QPixmap('../icons/classIcon/Function.png')) + self.gobj.setAcceptHoverEvents(True) + self.gobj.mobj = self.mobj + classname = self.mobj.className + funcdoc = (element(self.mobj.path)).expr + self.gobj.setToolTip(funcdoc) + #self.bg.setPen(Qt.QColor(100,100,10,10)) + + def setDisplayProperties(self,x,y,textcolor,bgcolor): + """Set the display properties of this item.""" + #With Respect to BuffPool (parent) I am placing at 0,30 (which is below the BuffPool) + self.setGeometry(0, 30,self.gobj.boundingRect().width(),self.gobj.boundingRect().height()) + self.bg.setBrush(QtGui.QBrush(bgcolor)) + self.setFlag(QtGui.QGraphicsItem.ItemIsMovable,False) + def refresh(self,scale): + # fontsize = PoolItem.defaultFontsize*scale + # font =QtGui.QFont("Helvetica") + # font.setPointSize(fontsize) + # self.gobj.setFont(font) + pass + def boundingRect(self): + ''' reimplimenting boundingRect for redrawning ''' + return QtCore.QRectF(0,0,self.gobj.boundingRect().width(),self.gobj.boundingRect().height()) + + def updateSlot(self): + pass + # #This func will adjust the background color with respect to text size + # self.gobj.setText(self.mobj.name) + # self.bg.setRect(0, 0, self.gobj.boundingRect().width()+PoolItem.fontMetrics.width(' '), self.gobj.boundingRect().height()) + + def updateColor(self,bgcolor): + #self.bg.setBrush(QtGui.QBrush(QtGui.QColor(bgcolor))) + pass + + def updateRect(self,ratio): + pass + # width = self.gobj.boundingRect().width()+PoolItem.fontMetrics.width(' ') + # height = self.gobj.boundingRect().height() + # adjustw = width*ratio + # adjusth = height*ratio + # self.bgColor.setRect(width/2-abs(adjustw/2),height/2-abs(adjusth/2),adjustw, adjusth) + #self.bg.setRect(0,0,self.gobj.boundingRect().width()*ratio+PoolItem.fontMetrics.width(' '), self.gobj.boundingRect().height()*ratio) + def returnColor(self): + return (self.bg.brush().color()) + + def updateValue(self,gobj): + self.gobj.setToolTip(funcdoc) + # self._gobj = gobj + # #if type(self._gobj) is moose.ZombiePool: + # if (isinstance(self._gobj,PoolBase)): + # self._conc = self.mobj.conc + # self._n = self.mobj.n + # doc = "Conc\t: "+str(self._conc)+"\nn\t: "+str(self._n) + # self.gobj.setToolTip(doc) + + +class PoolItem(KineticsDisplayItem): + name = ITEM + """Class for displaying pools. Uses a QGraphicsSimpleTextItem to + display the name.""" + #fontMetrics = None + font =QtGui.QFont(KineticsDisplayItem.defaultFontName) + font.setPointSize(KineticsDisplayItem.defaultFontSize) + fontMetrics = QtGui.QFontMetrics(font) + def __init__(self, mobj, parent): + KineticsDisplayItem.__init__(self, mobj, parent) + self.bg = QtGui.QGraphicsRectItem(self) + self.bg.setAcceptHoverEvents(True) + self.gobj = QtGui.QGraphicsSimpleTextItem(self.mobj.name, self.bg) + self.gobj.mobj = self.mobj + classname = self.mobj.className + # classname = 'PoolBase' + # doc = moose.element('/classes/%s' % (classname)).docs + # print "docs ",self.gobj.mobj, " ",doc + # doc = doc.split('Description:')[-1].split('Name:')[0].strip() + self._conc = self.mobj.conc + self._n = self.mobj.n + doc = "Conc\t: "+str(self._conc)+"\nn\t: "+str(self._n) + self.gobj.setToolTip(doc) + self.gobj.setFont(PoolItem.font) + if not PoolItem.fontMetrics: + PoolItem.fontMetrics = QtGui.QFontMetrics(self.gobj.font()) + self.bg.setRect(0, + 0, + self.gobj.boundingRect().width() + +PoolItem.fontMetrics.width(' '), + self.gobj.boundingRect().height()) + self.bg.setPen(Qt.QColor(0,0,0,0)) + self.gobj.setPos(PoolItem.fontMetrics.width(' '), 0) + def setDisplayProperties(self,x,y,textcolor,bgcolor): + """Set the display properties of this item.""" + self.setGeometry(x, y,self.gobj.boundingRect().width() + +PoolItem.fontMetrics.width(''), + self.gobj.boundingRect().height()) + self.bg.setBrush(QtGui.QBrush(bgcolor)) + + def refresh(self,scale): + fontsize = KineticsDisplayItem.defaultFontSize*scale + font = QtGui.QFont(KineticsDisplayItem.defaultFontName) + if (fontsize < 1): + fontsize = self.gobj.font().pointSize() + font.setPointSize(fontsize) + #self.gobj.setFont(PoolItem.font) + self.gobj.setFont(font) + + def boundingRect(self): + ''' reimplimenting boundingRect for redrawning ''' + return QtCore.QRectF(0,0,self.gobj.boundingRect().width()+PoolItem.fontMetrics.width(' '),self.gobj.boundingRect().height()) + + def updateSlot(self): + #This func will adjust the background color with respect to text size + self.gobj.setText(self.mobj.name) + self.bg.setRect(0, 0, self.gobj.boundingRect().width()+PoolItem.fontMetrics.width(' '), self.gobj.boundingRect().height()) + + def updateColor(self,bgcolor): + self.bg.setBrush(QtGui.QBrush(QtGui.QColor(bgcolor))) + #pass + + def updateRect(self,ratio=1.0): + width = self.gobj.boundingRect().width()+PoolItem.fontMetrics.width(' ') + height = self.gobj.boundingRect().height() + adjustw = width*ratio + adjusth = height*ratio + self.bg.setRect(width/2-abs(adjustw/2),height/2-abs(adjusth/2),adjustw, adjusth) + #self.bg.setRect(0,0,self.gobj.boundingRect().width()*ratio+PoolItem.fontMetrics.width(' '), self.gobj.boundingRect().height()*ratio) + + def returnColor(self): + return (self.bg.brush().color()) + + def updateValue(self,gobj): + self._gobj = gobj + #if type(self._gobj) is moose.ZombiePool: + if (isinstance(self._gobj,PoolBase)): + self._conc = self.mobj.conc + self._n = self.mobj.n + doc = "Conc\t: "+str(self._conc)+"\nn\t: "+str(self._n) + self.gobj.setToolTip(doc) + +class PoolItemCircle(PoolItem): + name = ITEM + def __init__(self,*args,**kwargs): + PoolItem.__init__(self, *args, **kwargs) + self.setFlag(QtGui.QGraphicsItem.ItemIsMovable,True) + self.bgColor = QtGui.QGraphicsEllipseItem(self) + self.bgColor.setFlag(QtGui.QGraphicsItem.ItemStacksBehindParent,True) + self.bgColor.setRect(((self.gobj.boundingRect().width()+PoolItem.fontMetrics.width(' '))/2)-5,self.gobj.boundingRect().height()/2-5,10,10) + + def setDisplayProperties(self,x,y,textcolor,bgcolor): + self.setGeometry(x, y,self.gobj.boundingRect().width() + +PoolItem.fontMetrics.width(' '), + self.gobj.boundingRect().height()) + self.bgColor.setBrush(QtGui.QBrush(QtGui.QColor(bgcolor.red(),bgcolor.green(),bgcolor.blue(),255))) + + def updateRect(self,ratio): + width = self.gobj.boundingRect().width()+PoolItem.fontMetrics.width(' ') + height = self.gobj.boundingRect().height() + adjustw = width*ratio + adjusth = height*ratio + self.bgColor.setRect(width/2-abs(adjustw/2),height/2-abs(adjusth/2),adjustw, adjusth) + self.updateValue(self.gobj) + + def returnEllispeSize(self): + self.bgColor.setRect(((self.gobj.boundingRect().width()+PoolItem.fontMetrics.width(' '))/2)-5,self.gobj.boundingRect(). + height()/2-5,10,10) + + def refresh(self,scale): + fontsize = KineticsDisplayItem.defaultFontSize*scale + font =QtGui.QFont(KineticsDisplayItem.defaultFontName) + if (fontsize < 1): + fontsize = self.gobj.font().pointSize() + font.setPointSize(fontsize) + self.gobj.setFont(font) + + def MooseRef(self): + return self.gobj.mobj + +class TableItem(KineticsDisplayItem): + defaultWidth = 30 + defaultHeight = 30 + defaultPenWidth = 2 + name = ITEM + def __init__(self, *args, **kwargs): + KineticsDisplayItem.__init__(self, *args, **kwargs) + + points = [QtCore.QPointF(0,TableItem.defaultWidth/2), + QtCore.QPointF(TableItem.defaultHeight/2-2,0), + QtCore.QPointF(TableItem.defaultWidth/2+2,0), + QtCore.QPointF(TableItem.defaultWidth,TableItem.defaultHeight/2), + ] + + path = QtGui.QPainterPath() + path.moveTo(points[0]) + for p in points[1:]: + path.lineTo(p) + path.moveTo(p) + path.moveTo(0,0) + path.lineTo(TableItem.defaultWidth,0) + path.moveTo(-(TableItem.defaultWidth/3),TableItem.defaultHeight/4) + path.lineTo((TableItem.defaultWidth+10),TableItem.defaultHeight/4) + + self.gobj = QtGui.QGraphicsPathItem(path, self) + #self.gobj.setToolTip("Need to see what to show unlike conc/nint for pool") + tabledoc = (element(self.mobj.path)).outputValue + self.gobj.setToolTip(str(tabledoc)) + self.gobj.setPen(QtGui.QPen(QtCore.Qt.black, 2,Qt.Qt.SolidLine, Qt.Qt.RoundCap, Qt.Qt.RoundJoin)) + self.gobj.mobj = self.mobj + + def refresh( self,scale): + defaultWidth = TableItem.defaultWidth*scale + defaultHeight = TableItem.defaultHeight*scale + points = [QtCore.QPointF(0,defaultWidth/2), + QtCore.QPointF(defaultHeight/2-2,0), + QtCore.QPointF(defaultWidth/2+2,0), + QtCore.QPointF(defaultWidth,defaultHeight/2) + ] + path = QtGui.QPainterPath() + path.moveTo(points[0]) + for p in points[1:]: + path.lineTo(p) + path.moveTo(p) + path.moveTo(0,0) + path.lineTo(defaultWidth,0) + path.moveTo(-(defaultWidth/3),defaultHeight/4) + path.lineTo((defaultWidth+10),defaultHeight/4) + self.gobj.setPath(path) + TablePen = self.gobj.pen() + defaultpenwidth = TableItem.defaultPenWidth + tableWidth = TableItem.defaultPenWidth*scale + TablePen.setWidth(tableWidth) + self.gobj.setPen(TablePen) + + def setDisplayProperties(self, x,y,textcolor,bgcolor): + #TODO check the table bounding reactangle b'cos selection looks ugly + """Set the display properties of this item.""" + self.setGeometry(x,y, + self.gobj.boundingRect().width(), + self.gobj.boundingRect().height()) + +class ReacItem(KineticsDisplayItem): + defaultWidth = 30 + defaultHeight = 30 + defaultPenWidth = 2 + name = ITEM + def __init__(self, *args, **kwargs): + KineticsDisplayItem.__init__(self, *args, **kwargs) + points = [QtCore.QPointF(ReacItem.defaultWidth/4, 0), + QtCore.QPointF(0, ReacItem.defaultHeight/4), + QtCore.QPointF(ReacItem.defaultWidth, ReacItem.defaultHeight/4), + QtCore.QPointF(3*ReacItem.defaultWidth/4, ReacItem.defaultHeight/2)] + path = QtGui.QPainterPath() + path.moveTo(points[0]) + for p in points[1:]: + path.lineTo(p) + path.moveTo(p) + self.gobj = QtGui.QGraphicsPathItem(path, self) + self.gobj.setPen(QtGui.QPen(QtCore.Qt.black, 2,Qt.Qt.SolidLine, Qt.Qt.RoundCap, Qt.Qt.RoundJoin)) + self.gobj.mobj = self.mobj + #classname = self.mobj.className + # classname = 'ReacBase' + # doc = moose.element('/classes/%s' % (classname)).docs + # print "docs ",self.gobj.mobj, " ",doc + # doc = doc.split('Description:')[-1].split('Name:')[0].strip() + self._Kf = self.gobj.mobj.Kf + self._Kb = self.gobj.mobj.Kb + doc = "Kf\t: "+str(self._Kf)+"\nKb\t: "+str(self._Kb) + self.gobj.setToolTip(doc) + + def updateValue(self,gobj): + self._gobj = gobj + #if ( type(self._gobj) is moose.ZombieReac or type(self_gobj) is moose.Reac): + if (isinstance(self._gobj,ReacBase)): + self._Kf = self._gobj.Kf + self._Kb = self._gobj.Kb + doc = "Kf\t: "+str(self._Kf)+"\nKb\t: "+str(self._Kb) + self.gobj.setToolTip(doc) + + def refresh( self,scale): + defaultWidth = ReacItem.defaultWidth*scale + defaultHeight = ReacItem.defaultHeight*scale + points = [QtCore.QPointF(defaultWidth/4, 0), + QtCore.QPointF(0,defaultHeight/4), + QtCore.QPointF(defaultWidth, defaultHeight/4), + QtCore.QPointF(3*defaultWidth/4,defaultHeight/2)] + path = QtGui.QPainterPath() + path.moveTo(points[0]) + for p in points[1:]: + path.lineTo(p) + path.moveTo(p) + + self.gobj.setPath(path) + ReacPen = self.gobj.pen() + defaultpenwidth = ReacItem.defaultPenWidth + reacWidth = defaultpenwidth*scale + ReacPen.setWidth(reacWidth) + self.gobj.setPen(ReacPen) + + def setDisplayProperties(self, x,y,textcolor,bgcolor): + """Set the display properties of this item.""" + self.setGeometry(x,y, + self.gobj.boundingRect().width(), + self.gobj.boundingRect().height()) + +class EnzItem(KineticsDisplayItem): + defaultWidth = 20 + defaultHeight = 10 + name = ITEM + def __init__(self, *args, **kwargs): + KineticsDisplayItem.__init__(self, *args, **kwargs) + self.gobj = QtGui.QGraphicsEllipseItem(0, 0, + EnzItem.defaultWidth, + EnzItem.defaultHeight, self) + self.gobj.mobj = self.mobj + # classname = 'EnzBase' + # doc = moose.element('/classes/%s' % (classname)).docs + # doc = doc.split('Description:')[-1].split('Name:')[0].strip() + self._Km = self.gobj.mobj.Km + self._Kcat = self.gobj.mobj.kcat + doc = "Km\t: "+str(self._Km)+"\nKcat\t: "+str(self._Kcat) + self.gobj.setToolTip(doc) + + def updateValue(self,gobj): + self._gobj = gobj + if ( isinstance(self.gobj,EnzBase)): + self._Km = self._gobj.Km + self._Kcat = self._gobj.kcat + doc = "Km\t: "+str(self._Km)+"\nKcat\t: "+str(self._Kcat) + self.gobj.setToolTip(doc) + + def updateColor(self,bgcolor): + self.gobj.setBrush(QtGui.QBrush(QtGui.QColor(bgcolor))) + + def setDisplayProperties(self,x,y,textcolor,bgcolor): + """Set the display properties of this item.""" + self.setGeometry(x,y, + self.gobj.boundingRect().width(), + self.gobj.boundingRect().height()) + self.gobj.setBrush(QtGui.QBrush(bgcolor)) + + def refresh(self,scale): + defaultWidth = EnzItem.defaultWidth*scale + defaultHeight = EnzItem.defaultHeight*scale + self.gobj.setRect(0,0,defaultWidth,defaultHeight) + +class MMEnzItem(EnzItem): + name = ITEM + def __init__(self,*args, **kwargs): + EnzItem.__init__(self,*args, **kwargs) + +class CplxItem(KineticsDisplayItem): + defaultWidth = 10 + defaultHeight = 10 + name = ITEM + def __init__(self, *args, **kwargs): + KineticsDisplayItem.__init__(self, *args, **kwargs) + self.gobj = QtGui.QGraphicsRectItem(0,0, CplxItem.defaultWidth, CplxItem.defaultHeight, self) + self.gobj.mobj = self.mobj + self._conc = self.mobj.conc + self._n = self.mobj.n + doc = "Conc\t: "+str(self._conc)+"\nn\t: "+str(self._n) + self.gobj.setToolTip(doc) + + def updateValue(self,gobj): + self._gobj = gobj + if (isinstance(self._gobj,PoolBase)): + self._conc = self.mobj.conc + self._n = self.mobj.n + doc = "Conc\t: "+str(self._conc)+"\nn\t: "+str(self._n) + self.gobj.setToolTip(doc) + + def setDisplayProperties(self,x,y,textcolor,bgcolor): + """Set the display properties of this item.""" + self.setGeometry(self.gobj.boundingRect().width()/2,self.gobj.boundingRect().height(), + self.gobj.boundingRect().width(), + self.gobj.boundingRect().height()) + self.setFlag(QtGui.QGraphicsItem.ItemIsMovable,False) + + def refresh(self,scale): + defaultWidth = CplxItem.defaultWidth*scale + defaultHeight = CplxItem.defaultHeight*scale + + self.gobj.setRect(0,0,defaultWidth,defaultHeight) + +class ComptItem(QtGui.QGraphicsRectItem): + name = COMPARTMENT + def __init__(self,parent,x,y,w,h,item): + self.cmptEmitter = QtCore.QObject() + iParent = item + ''' + self._rect = QtCore.QRectF(x,y,w,h) + self._scene = parent + print "self comptItem",self._scene.sceneContainer ," and",self._scene.sceneContainer.graphicsView + self.mouseOver = False + self.resizeHandleSize = 4.0 + self.mousePressPos = None + self.mouseMovePos = None + self.mouseIsPressed = False + #self.setAcceptsHoverEvents(True) + self.updateResizeHandles() + ''' + if hasattr(iParent, "__iter__"): + self.mobj = iParent[0] + else: + self.mobj = iParent + self.layoutWidgetPt = parent + QtGui.QGraphicsRectItem.__init__(self,x,y,w,h) + + self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True); + self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable) + #self.setFlag(QtGui.QGraphicsItem.ItemSendsGeometryChanges, 1) + if config.QT_MINOR_VERSION >= 6: + self.setFlag(QtGui.QGraphicsItem.ItemSendsGeometryChanges, 1) + ''' + def hoverEnterEvent(self, event): + self.updateResizeHandles() + self.mouseOver = True + self.prepareGeometryChange() + + def hoverLeaveEvent(self, event): + self.mouseOver = False + self.prepareGeometryChange() + + def hoverMoveEvent(self, event): + + if self.topLeft.contains(event.scenePos()) or self.bottomRight.contains(event.scenePos()): + self.setCursor(QtCore.Qt.SizeFDiagCursor) + elif self.topRight.contains(event.scenePos()) or self.bottomLeft.contains(event.scenePos()): + self.setCursor(QtCore.Qt.SizeBDiagCursor) + else: + self.setCursor(QtCore.Qt.SizeAllCursor) + + QtGui.QGraphicsRectItem.hoverMoveEvent(self, event) + + def mousePressEvent(self, event): + """ + Capture mouse press events and find where the mosue was pressed on the object + """ + self.mousePressPos = event.scenePos() + self.mouseIsPressed = True + self.rectPress = copy.deepcopy(self._rect) + + # Top left corner + if self.topLeft.contains(event.scenePos()): + self.mousePressArea = 'topleft' + # top right corner + elif self.topRight.contains(event.scenePos()): + self.mousePressArea = 'topright' + # bottom left corner + elif self.bottomLeft.contains(event.scenePos()): + self.mousePressArea = 'bottomleft' + # bottom right corner + elif self.bottomRight.contains(event.scenePos()): + self.mousePressArea = 'bottomright' + # entire rectangle + else: + self.mousePressArea = None + + QtGui.QGraphicsRectItem.mousePressEvent(self, event) + + def mouseReleaseEvent(self, event): + """ + Capture nmouse press events. + """ + self.mouseIsPressed = False + + self.updateResizeHandles() + self.prepareGeometryChange() + + QtGui.QGraphicsRectItem.mouseReleaseEvent(self, event) + + def mouseMoveEvent(self, event): + """ + Handle mouse move events. + """ + self.mouseMovePos = event.scenePos() + + if self.mouseIsPressed: + # Move top left corner + if self.mousePressArea=='topleft': + self._rect.setTopLeft(self.rectPress.topLeft()-(self.mousePressPos-self.mouseMovePos)) + # Move top right corner + elif self.mousePressArea=='topright': + self._rect.setTopRight(self.rectPress.topRight()-(self.mousePressPos-self.mouseMovePos)) + # Move bottom left corner + elif self.mousePressArea=='bottomleft': + self._rect.setBottomLeft(self.rectPress.bottomLeft()-(self.mousePressPos-self.mouseMovePos)) + # Move bottom right corner + elif self.mousePressArea=='bottomright': + self._rect.setBottomRight(self.rectPress.bottomRight()-(self.mousePressPos-self.mouseMovePos)) + # Move entire rectangle, don't resize + else: + self._rect.moveCenter(self.rectPress.center()-(self.mousePressPos-self.mouseMovePos)) + + self.updateResizeHandles() + self.prepareGeometryChange() + + QtGui.QGraphicsRectItem.mousePressEvent(self, event) + + def boundingRect(self): + """ + Return bounding rectangle + """ + return self._boundingRect + + def updateResizeHandles(self): + """ + Update bounding rectangle and resize handles + """ + self.offset = self.resizeHandleSize*(self._scene.sceneContainer.graphicsView.mapToScene(1,0)-self._scene.sceneContainer.graphicsView.mapToScene(0,1)).x() + + self._boundingRect = self._rect.adjusted(-self.offset, self.offset, self.offset, -self.offset) + + # Note: this draws correctly on a view with an inverted y axes. i.e. QGraphicsView.scale(1,-1) + self.topLeft = QtCore.QRectF(self._boundingRect.topLeft().x(), self._boundingRect.topLeft().y() - 2*self.offset, + 2*self.offset, 2*self.offset) + self.topRight = QtCore.QRectF(self._boundingRect.topRight().x() - 2*self.offset, self._boundingRect.topRight().y() - 2*self.offset, + 2*self.offset, 2*self.offset) + self.bottomLeft = QtCore.QRectF(self._boundingRect.bottomLeft().x(), self._boundingRect.bottomLeft().y(), + 2*self.offset, 2*self.offset) + self.bottomRight = QtCore.QRectF(self._boundingRect.bottomRight().x() - 2*self.offset, self._boundingRect.bottomRight().y(), + 2*self.offset, 2*self.offset) + + def paint(self, painter, option, widget): + """ + Paint Widget + """ + + # show boundingRect for debug purposes + painter.setPen(QtGui.QPen(QtCore.Qt.red, 0, QtCore.Qt.DashLine)) + painter.drawRect(self._boundingRect) + + # Paint rectangle + painter.setPen(QtGui.QPen(QtCore.Qt.black, 0, QtCore.Qt.SolidLine)) + painter.drawRect(self._rect) + + # If mouse is over, draw handles + if self.mouseOver: + # if rect selected, fill in handles + if self.isSelected(): + painter.setBrush(QtGui.QBrush(QtGui.QColor(0,0,0))) + painter.drawRect(self.topLeft) + painter.drawRect(self.topRight) + painter.drawRect(self.bottomLeft) + painter.drawRect(self.bottomRight) + ''' + def pointerLayoutpt(self): + return (self.layoutWidgetPt) + + # def mouseDoubleClickEvent(self, event): + # self.cmptEmitter.emit(QtCore.SIGNAL("qgtextDoubleClick(PyQt_PyObject)"),element(self.mooseObj_)) + + def itemChange(self,change,value): + if change == QtGui.QGraphicsItem.ItemPositionChange: + self.cmptEmitter.emit(QtCore.SIGNAL("qgtextPositionChange(PyQt_PyObject)"),self.mobj) + if change == QtGui.QGraphicsItem.ItemSelectedChange and value == True: + self.cmptEmitter.emit(QtCore.SIGNAL("qgtextItemSelectedChange(PyQt_PyObject)"),self.mobj) + return QtGui.QGraphicsItem.itemChange(self,change,value) + + +if __name__ == '__main__': + app = QtGui.QApplication(sys.argv) + a = moose.Pool('pool') + b = moose.Reac('reac') + c = moose.Enz('enzyme') + gview = QtGui.QGraphicsView() + scene = QtGui.QGraphicsScene(gview) + #item = PoolItem(a) + #dinfo = (5, 5, QtGui.QColor('red'), QtGui.QColor('blue')) + #item.setDisplayProperties(dinfo) + reacItem = ReacItem(b) + reacItem.setDisplayProperties(50, 5, QtGui.QColor('yellow'), QtGui.QColor('green')) + enzItem = EnzItem(c) + enzItem.setDisplayProperties(100, 10, QtGui.QColor('blue'), QtGui.QColor('yellow')) + #scene.addItem(item) + scene.addItem(reacItem) + scene.addItem(enzItem) + gview.setScene(scene) + #print 'Position', reacItem.pos() + gview.show() + sys.exit(app.exec_()) diff --git a/moose-gui/plugins/kkitUtil.py b/moose-gui/plugins/kkitUtil.py new file mode 100644 index 0000000000000000000000000000000000000000..84f5a17c96a68906285d8108a2ad2faf6587b8f6 --- /dev/null +++ b/moose-gui/plugins/kkitUtil.py @@ -0,0 +1,155 @@ +from moose import Annotator +from kkitQGraphics import PoolItem, ReacItem,EnzItem,CplxItem,ComptItem +from PyQt4 import QtCore,QtGui,QtSvg +from PyQt4.QtGui import QColor +import numpy as np +import os +import config +import pickle +import random +import matplotlib + +colormap_file = open(os.path.join(config.settings[config.KEY_COLORMAP_DIR], 'rainbow2.pkl'),'rb') +colorMap = pickle.load(colormap_file) +colormap_file.close() + +ignoreColor= ["mistyrose","antiquewhite","aliceblue","azure","bisque","black","blanchedalmond","blue","cornsilk","darkolivegreen","darkslategray","dimgray","floralwhite","gainsboro","ghostwhite","honeydew","ivory","lavender","lavenderblush","lemonchiffon","lightcyan","lightgoldenrodyellow","lightgray","lightyellow","linen","mediumblue","mintcream","navy","oldlace","papayawhip","saddlebrown","seashell","snow","wheat","white","whitesmoke"] +matplotcolor = {} +for name,hexno in matplotlib.colors.cnames.iteritems(): + matplotcolor[name]=hexno + +def getRandColor(): + k = random.choice(matplotcolor.keys()) + if k in ignoreColor: + return getRandColor() + else: + return QColor(matplotcolor[k]) + +def getRandColor1(): + color = (np.random.randint(low=0, high=255, size=3)).tolist() + if not all((x <= 65 or x >= 105) for x in (color[0],color[1],color[2])): + return QColor(color[0],color[1],color[2]) + else: + return getRandColor() + + +def getColor(iteminfo): + """ Getting a textcolor and background color for the given mooseObject \ + If textcolor is empty replaced with green \ + background color is empty replaced with blue + if textcolor and background is same as it happend in kkit files \ + replacing textcolor with random color\ + The colors are not valid there are siliently replaced with some values \ + but while model building can raise an exception + """ + textcolor = Annotator(iteminfo).getField('textColor') + bgcolor = Annotator(iteminfo).getField('color') + if(textcolor == ''): textcolor = 'green' + if(bgcolor == ''): bgcolor = 'blue' + if(textcolor == bgcolor):textcolor = getRandColor() + textcolor = colorCheck(textcolor,"fc") + bgcolor = colorCheck(bgcolor,"bg") + return(textcolor,bgcolor) + +def colorCheck(fc_bgcolor,fcbg): + """ textColor or background can be anything like string or tuple or list \ + if string its taken as colorname further down in validColorcheck checked for valid color, \ + but for tuple and list its taken as r,g,b value. + """ + if isinstance(fc_bgcolor,str): + if fc_bgcolor.startswith("#"): + fc_bgcolor = QColor(fc_bgcolor) + elif fc_bgcolor.isdigit(): + """ color is int a map from int to r,g,b triplets from pickled color map file """ + tc = int(fc_bgcolor) + tc = 2*tc + pickledColor = colorMap[tc] + fc_bgcolor = QColor(*pickledColor) + + elif fc_bgcolor.isalpha() or fc_bgcolor.isalnum(): + fc_bgcolor = validColorcheck(fc_bgcolor) + else: + fc_bgcolor = QColor(*eval(fc_bgcolor)) + # fc_bgcolor = validColorcheck(fc_bgcolor) + return(fc_bgcolor) + +def validColorcheck(color): + ''' + Both in Qt4.7 and 4.8 if not a valid color it makes it as back but in 4.7 there will be a warning mssg which is taken here + checking if textcolor or backgroundcolor is valid color, if 'No' making white color as default + where I have not taken care for checking what will be backgroundcolor for textcolor or textcolor for backgroundcolor + ''' + if QColor(color).isValid(): + return (QColor(color)) + else: + return(QColor("white")) + + +def moveMin(reference, collider, layoutPt,margin): + referenceRect = reference.sceneBoundingRect() + colliderRect = collider.sceneBoundingRect() + xDistance = referenceRect.x() + referenceRect.width() / 2.0 + colliderRect.width() / 2.0 + margin - colliderRect.x() + yDistance = 0.0 + if colliderRect.y() < referenceRect.y(): + yDistance = (referenceRect.y() - referenceRect.height() / 2.0 - colliderRect.height() / 2.0 - margin) - colliderRect.y() + else: + yDistance = referenceRect.y() + referenceRect.height() / 2.0 + colliderRect.height() / 2.0 + margin - colliderRect.y() + + #if xDistance > yDistance: + collider.moveBy(xDistance, yDistance) + #else: + # collider.moveBy(xDistance, 0.0) + layoutPt.drawLine_arrow(itemignoreZooming=False) + +def moveX(reference, collider, layoutPt, margin): + referenceRect = reference.sceneBoundingRect() + colliderRect = collider.sceneBoundingRect() + xc = abs(referenceRect.topRight().x()) - abs(colliderRect.topLeft().x())+margin + yc = 0.0 + collider.moveBy(xc,yc) + layoutPt.drawLine_arrow(itemignoreZooming=False) + +def handleCollisions(compartments, moveCallback, layoutPt,margin = 5.0): + + if len(compartments) is 0 : return + compartments = sorted(compartments, key = lambda c: c.sceneBoundingRect().center().x()) + reference = compartments.pop(0); + print reference.name + referenceRect = reference.sceneBoundingRect() + colliders = filter( lambda compartment : referenceRect.intersects(compartment.sceneBoundingRect()) + , compartments + ) + for collider in colliders: + moveCallback(reference, collider, layoutPt,margin) + return handleCollisions(compartments, moveCallback, layoutPt,margin) + +def calculateChildBoundingRect(compt): + ''' In this function I am trying to calculate BoundingRect of the compartments + looking into children and its children which default "ChildrenBoundingRect" + function doing but in multi-compartment cross-compartment reaction + the arrow width is taken into account which doesn't belong to this perticular compartment + ''' + ypos = [] + xpos = [] + for l in compt.childItems(): + ''' All the children including pool,reac,enz,polygon(arrow),table ''' + if not isinstance(l,QtSvg.QGraphicsSvgItem): + xpos.append((l.pos().x())+(l.boundingRect().bottomRight().x())) + xpos.append(l.pos().x()) + ypos.append(l.pos().y()+l.boundingRect().bottomRight().y()) + ypos.append(l.pos().y()) + + if (isinstance(l,PoolItem) or isinstance(l,EnzItem)): + ''' For Enz cplx height and for pool function height needs to be taken''' + + for ll in l.childItems(): + ''' eleminating polygonItem (arrow) [This is happen in cross-compartment model that arrow from one compartment will be child] + pool's outboundary RectItem and Enz's outerboundary Ellipse is eleminating since its same + ''' + if ( (not isinstance(ll,QtGui.QGraphicsPolygonItem)) and + (not isinstance(ll,QtGui.QGraphicsRectItem)) and + (not isinstance(ll,QtGui.QGraphicsEllipseItem)) + ): + ypos.append(l.pos().y()+ll.pos().y()+ll.boundingRect().bottomRight().y()) + calculateRectcompt = QtCore.QRectF(min(xpos),min(ypos),(max(xpos)-min(xpos)),(max(ypos)-min(ypos))) + return calculateRectcompt \ No newline at end of file diff --git a/moose-gui/plugins/kkitViewcontrol.py b/moose-gui/plugins/kkitViewcontrol.py new file mode 100644 index 0000000000000000000000000000000000000000..404e89341d54a54b5004c8b92426f5f07bfb18e9 --- /dev/null +++ b/moose-gui/plugins/kkitViewcontrol.py @@ -0,0 +1,1131 @@ +import sys +from modelBuild import * +from constants import * +from PyQt4.QtGui import QPixmap, QImage, QPen, QGraphicsPixmapItem, QGraphicsLineItem +from PyQt4.QtCore import pyqtSignal +from kkitUtil import * +from setsolver import * +from PyQt4 import QtSvg +from moose import utils + +class GraphicalView(QtGui.QGraphicsView): + + def __init__(self, modelRoot,parent,border,layoutPt,createdItem): + QtGui.QGraphicsView.__init__(self,parent) + self.state = None + self.move = False + self.resetState() + self.connectionSign = None + self.connectionSource = None + self.expectedConnection = None + self.selections = [] + self.connector = None + self.connectionSignImagePath = "../gui/icons/connection.png" + self.connectionSignImage = QImage(self.connectionSignImagePath) + + # self.expectedConnectionPen = QPen() + self.setScene(parent) + self.modelRoot = modelRoot + self.sceneContainerPt = parent + self.setDragMode(QtGui.QGraphicsView.RubberBandDrag) + self.itemSelected = False + self.customrubberBand = None + self.rubberbandWidth = 0 + self.rubberbandHeight = 0 + self.moved = False + self.showpopupmenu = False + self.popupmenu4rlines = True + self.border = 6 + self.setRenderHints(QtGui.QPainter.Antialiasing) + self.layoutPt = layoutPt + # All the object which are stacked on the scene are listed + self.stackOrder = self.sceneContainerPt.items(Qt.Qt.DescendingOrder) + #From stackOrder selecting only compartment + self.cmptStackorder = [i for i in self.stackOrder if isinstance(i,ComptItem)] + self.viewBaseType = " " + self.iconScale = 1 + self.arrowsize = 2 + self.defaultComptsize = 5 + self.connectorlist = {"plot": None ,"clone": None,"move": None,"delete": None} + self.setHorizontalScrollBarPolicy(PyQt4.QtCore.Qt.ScrollBarAlwaysOn) + self.setVerticalScrollBarPolicy(PyQt4.QtCore.Qt.ScrollBarAlwaysOn) + + def setRefWidget(self,path): + self.viewBaseType = path + + def resizeEvent(self, event): + #print event.size().width(),event.size().height() + self.fitInView(self.sceneContainerPt.itemsBoundingRect().x()-10,self.sceneContainerPt.itemsBoundingRect().y()-10,self.sceneContainerPt.itemsBoundingRect().width()+20,self.sceneContainerPt.itemsBoundingRect().height()+20,Qt.Qt.IgnoreAspectRatio) + #print("Called =>", event) + + return + + def resolveCompartmentInteriorAndBoundary(self, item, position): + bound = item.rect().adjusted(3,3,-3,-3) + return COMPARTMENT_INTERIOR if bound.contains(item.mapFromScene(position)) else COMPARTMENT_BOUNDARY + + def resetState(self): + self.state = { "press" : { "mode" : INVALID + , "item" : None + , "sign" : None + , "pos" : None + } + , "move" : { "happened": False + } + , "release" : { "mode" : INVALID + , "item" : None + , "sign" : None + } + } + + + def resolveItem(self, items, position): + solution = None + for item in items: + # if isinstance(item, QtGui.QGraphicsPixmapItem): + # return (item, CONNECTOR) + if isinstance(item, QtSvg.QGraphicsSvgItem): + return (item, CONNECTOR) + + if isinstance(item, QtGui.QGraphicsPolygonItem): + return (item, CONNECTION) + + for item in items: + if hasattr(item, "name"): + #print(item.name) + if item.name == ITEM: + return (item, ITEM) + if item.name == COMPARTMENT: + solution = (item, self.resolveCompartmentInteriorAndBoundary(item, position)) + + if solution is None: + return (None, EMPTY) + return solution + + def editorMousePressEvent(self, event): + # self.deselectSelections() + # if self.state["press"]["item"] is not None: + # self.state["press"]["item"].setSelected(False) + # self.resetState() + if event.buttons() == QtCore.Qt.LeftButton: + self.clickPosition = self.mapToScene(event.pos()) + (item, itemType) = self.resolveItem(self.items(event.pos()), self.clickPosition) + self.state["press"]["mode"] = VALID + self.state["press"]["item"] = item + self.state["press"]["type"] = itemType + self.state["press"]["pos"] = event.pos() + #If connector exist and if mousePress on Compartment interior, + # then removing any connect if exist + if itemType == COMPARTMENT_INTERIOR: + self.removeConnector() + elif itemType == ITEM: + if not self.move: + self.showConnector(self.state["press"]["item"]) + # self.layoutPt.plugin.mainWindow.objectEditSlot(self.state["press"]["item"].mobj, False) + else: + self.resetState() + comptList = [] + for k, v in self.layoutPt.qGraCompt.items(): + comptList.append(v) + if len(comptList) > 1: + popupmenu = QtGui.QMenu('PopupMenu', self) + popupmenu.addAction("LinearLayout", lambda : handleCollisions(comptList, moveX, self.layoutPt)) + popupmenu.addAction("VerticalLayout" ,lambda : handleCollisions(comptList, moveMin, self.layoutPt )) + popupmenu.exec_(self.mapToGlobal(event.pos())) + + + def editorMouseMoveEvent(self, event): + + if self.state["press"]["mode"] == INVALID: + self.state["move"]["happened"] = False + return + + if self.move: + initial = self.mapToScene(self.state["press"]["pos"]) + final = self.mapToScene(event.pos()) + displacement = final - initial + #print("Displacement", displacement) + for item in self.selectedItems: + if isinstance(item, KineticsDisplayItem) and not isinstance(item,ComptItem) and not isinstance(item,CplxItem): + item.moveBy(displacement.x(), displacement.y()) + self.layoutPt.positionChange(item.mobj.path) + self.state["press"]["pos"] = event.pos() + return + + self.state["move"]["happened"] = True + itemType = self.state["press"]["type"] + item = self.state["press"]["item"] + + if itemType == CONNECTOR: + ''' connecting 2 object is removed and movement is impled''' + actionType = str(item.data(0).toString()) + if actionType == "move": + QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CrossCursor)) + initial = item.parent().pos() + final = self.mapToScene(event.pos()) + displacement = final-initial + if not isinstance(item.parent(),FuncItem) and not isinstance(item.parent(),CplxItem): + self.removeConnector() + item.parent().moveBy(displacement.x(), displacement.y()) + if isinstance(item.parent(),PoolItem): + for funcItem in item.parent().childItems(): + if isinstance(funcItem,FuncItem): + self.layoutPt.updateArrow(funcItem) + + self.state["press"]["pos"] = event.pos() + self.layoutPt.positionChange(item.parent().mobj) + if actionType == "clone": + pixmap = QtGui.QPixmap(24, 24) + pixmap.fill(QtCore.Qt.transparent) + painter = QtGui.QPainter() + painter.begin(pixmap) + painter.setRenderHints(painter.Antialiasing) + pen = QtGui.QPen(QtGui.QBrush(QtGui.QColor("black")), 1) + pen.setWidthF(1.5) + painter.setPen(pen) + painter.drawLine(12,7,12,17) + painter.drawLine(7,12,17,12) + painter.end() + #self.setCursor(QtGui.QCursor(pixmap)) + QtGui.QApplication.setOverrideCursor(QtGui.QCursor(pixmap)) + + if itemType == ITEM: + self.drawExpectedConnection(event) + + if itemType == COMPARTMENT_BOUNDARY: + initial = self.mapToScene(self.state["press"]["pos"]) + final = self.mapToScene(event.pos()) + displacement = final - initial + item.moveBy(displacement.x(), displacement.y()) + self.layoutPt.positionChange(item.mobj.path) + self.state["press"]["pos"] = event.pos() + + if itemType == COMPARTMENT_INTERIOR: + if self.customrubberBand == None: + self.customrubberBand = QtGui.QRubberBand(QtGui.QRubberBand.Rectangle,self) + self.customrubberBand.show() + + startingPosition = self.state["press"]["pos"] + endingPosition = event.pos() + displacement = endingPosition - startingPosition + + x0 = startingPosition.x() + x1 = endingPosition.x() + y0 = startingPosition.y() + y1 = endingPosition.y() + + if displacement.x() < 0 : + x0,x1= x1,x0 + + if displacement.y() < 0 : + y0,y1= y1,y0 + + self.customrubberBand.setGeometry(QtCore.QRect(QtCore.QPoint(x0, y0), QtCore.QSize(abs(displacement.x()), abs(displacement.y())))) + + + # if itemType == COMPARTMENT: + # rubberband selection + + # if itemType == COMPARTMENT_BOUNDARY: + + # if itemType == ITEM: + # dragging the item + + def editorMouseReleaseEvent(self, event): + if self.move: + #self.move = False + self.setCursor(Qt.Qt.ArrowCursor) + if self.state["press"]["mode"] == INVALID: + self.state["release"]["mode"] = INVALID + self.resetState() + return + + self.clickPosition = self.mapToScene(event.pos()) + (item, itemType) = self.resolveItem(self.items(event.pos()), self.clickPosition) + self.state["release"]["mode"] = VALID + self.state["release"]["item"] = item + self.state["release"]["type"] = itemType + + clickedItemType = self.state["press"]["type"] + if clickedItemType == ITEM: + if not self.state["move"]["happened"]: + if not self.move: + self.showConnector(self.state["press"]["item"]) + self.layoutPt.plugin.mainWindow.objectEditSlot(self.state["press"]["item"].mobj, True) + # compartment's rectangle size is calculated depending on children + #self.layoutPt.comptChilrenBoundingRect() + l = self.modelRoot + if self.modelRoot.find('/',1) > 0: + l = self.modelRoot[0:self.modelRoot.find('/',1)] + + linfo = moose.Annotator(l+'/model/info') + for k, v in self.layoutPt.qGraCompt.items(): + rectcompt = v.childrenBoundingRect() + if linfo.modeltype == "new_kkit": + #if newly built model then compartment is size is fixed for some size. + comptBoundingRect = v.boundingRect() + if not comptBoundingRect.contains(rectcompt): + self.layoutPt.updateCompartmentSize(v) + else: + #if already built model then compartment size depends on max and min objects + rectcompt = calculateChildBoundingRect(v) + v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20)) + + else: + if isinstance(self.state["release"]["item"], KineticsDisplayItem): + if not moose.element(self.state["press"]["item"].mobj) == moose.element(self.state["release"]["item"].mobj): + self.populate_srcdes( self.state["press"]["item"].mobj + , self.state["release"]["item"].mobj + ) + else: + pass + self.removeExpectedConnection() + self.removeConnector() + self.move = False + if clickedItemType == CONNECTOR: + actionType = str(self.state["press"]["item"].data(0).toString()) + + if actionType == "move": + QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.Qt.ArrowCursor)) + + if actionType == "delete": + self.removeConnector() + pixmap = QtGui.QPixmap(24, 24) + pixmap.fill(QtCore.Qt.transparent) + painter = QtGui.QPainter() + painter.begin(pixmap) + painter.setRenderHints(painter.Antialiasing) + pen = QtGui.QPen(QtGui.QBrush(QtGui.QColor("black")), 1) + pen.setWidthF(1.5) + painter.setPen(pen) + painter.drawLine(8,8,16,16) + painter.drawLine(8,16,16,8) + painter.end() + QtGui.QApplication.setOverrideCursor(QtGui.QCursor(pixmap)) + 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: + #delete solver first as topology is changing + deleteSolver(self.modelRoot) + self.deleteObj([item.parent()]) + QtGui.QApplication.restoreOverrideCursor() + else: + QtGui.QApplication.restoreOverrideCursor() + + elif actionType == "plot": + element = moose.element(item.parent().mobj.path) + if isinstance (element,moose.PoolBase): + self.graph = moose.element(self.modelRoot+'/data/graph_0') + tablePath = utils.create_table_path(moose.element(self.modelRoot), self.graph, element, "Conc") + table = utils.create_table(tablePath, element, "Conc","Table2") + self.layoutPt.plugin.view.getCentralWidget().plotWidgetContainer.plotAllData() + reply = QtGui.QMessageBox.information(self, "plot Object","Plot is added to Graph1", + QtGui.QMessageBox.Ok) + elif actionType == "clone": + if self.state["move"]["happened"]: + QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.Qt.ArrowCursor)) + self.state["press"]["item"].parent().mobj + cloneObj = self.state["press"]["item"] + posWrtComp = self.mapToScene(event.pos()) + itemAtView = self.sceneContainerPt.itemAt(self.mapToScene(event.pos())) + self.removeConnector() + if isinstance(itemAtView,ComptItem): + #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) + lKey = [key for key, value in self.layoutPt.qGraCompt.iteritems() if value == itemAtView][0] + iR = 0 + iP = 0 + t = moose.element(cloneObj.parent().mobj) + name = t.name + if isinstance(cloneObj.parent().mobj,PoolBase): + retValue = self.objExist(lKey.path,name,iP) + if retValue != None: + name += retValue + + pmooseCp = moose.copy(t,lKey.path,name,1) + #if moose.copy failed then check for path != '/' + if pmooseCp.path != '/': + ct = moose.element(pmooseCp) + concInit = pmooseCp.concInit[0] + #this is b'cos if pool copied across the comptartment, + #then it doesn't calculate nInit according but if one set + #concInit then it would, just a hack + ct.concInit = concInit + #itemAtView = self.state["release"]["item"] + poolObj = moose.element(ct) + poolinfo = moose.element(poolObj.path+'/info') + qGItem = PoolItem(poolObj,itemAtView) + self.layoutPt.mooseId_GObj[poolObj] = qGItem + #bgcolor = getRandColor() + color,bgcolor = getColor(poolinfo) + qGItem.setDisplayProperties(posWrtComp.x(),posWrtComp.y(),color,bgcolor) + self.emit(QtCore.SIGNAL("dropped"),poolObj) + + if isinstance(cloneObj.parent().mobj,ReacBase): + retValue = self.objExist(lKey.path,name,iR) + if retValue != None : + name += retValue + rmooseCp = moose.copy(t,lKey.path,name,1) + if rmooseCp.path != '/': + ct = moose.element(rmooseCp) + #itemAtView = self.state["release"]["item"] + reacObj = moose.element(ct) + reacinfo = moose.Annotator(reacObj.path+'/info') + qGItem = ReacItem(reacObj,itemAtView) + self.layoutPt.mooseId_GObj[reacObj] = qGItem + posWrtComp = self.mapToScene(event.pos()) + qGItem.setDisplayProperties(posWrtComp.x(),posWrtComp.y(),"white", "white") + self.emit(QtCore.SIGNAL("dropped"),reacObj) + + self.updateScale(self.iconScale) + + else: + if itemAtView == None: + QtGui.QMessageBox.information(None,'Dropping Not possible ','Dropping not allowed outside the compartment',QtGui.QMessageBox.Ok) + else: + srcdesString = ((self.state["release"]["item"]).mobj).className + QtGui.QMessageBox.information(None,'Dropping Not possible','Dropping on \'{srcdesString}\' not allowed'.format(srcdesString = srcdesString),QtGui.QMessageBox.Ok) + if clickedItemType == CONNECTION: + popupmenu = QtGui.QMenu('PopupMenu', self) + popupmenu.addAction("Delete", lambda : self.deleteConnection(item)) + popupmenu.exec_(self.mapToGlobal(event.pos())) + + if clickedItemType == COMPARTMENT_BOUNDARY: + if not self.state["move"]["happened"]: + self.layoutPt.plugin.mainWindow.objectEditSlot(self.state["press"]["item"].mobj, True) + self.resetState() + + if clickedItemType == COMPARTMENT_INTERIOR: + if self.state["move"]["happened"]: + startingPosition = self.state["press"]["pos"] + endingPosition = event.pos() + displacement = endingPosition - startingPosition + + x0 = startingPosition.x() + x1 = endingPosition.x() + y0 = startingPosition.y() + y1 = endingPosition.y() + + if displacement.x() < 0 : + x0,x1= x1,x0 + + if displacement.y() < 0 : + y0,y1= y1,y0 + + #print "kkitview COMPARTMENT_INTERIOR",x0,y0 + self.selectedItems = selectedItems = self.items(x0,y0,abs(displacement.x()), abs(displacement.y())) + # print("Rect => ", self.customrubberBand.rect()) + # selectedItems = self.items(self.mapToScene(self.customrubberBand.rect()).boundingRect()) + self.selectSelections(selectedItems) + for item in selectedItems: + if isinstance(item, KineticsDisplayItem) and not isinstance(item,ComptItem): + item.setSelected(True) + #print("Rubberband Selections => ", self.selections) + self.customrubberBand.hide() + self.customrubberBand = None + popupmenu = QtGui.QMenu('PopupMenu', self) + + popupmenu.addAction("Delete", lambda: self.deleteSelections(x0,y0,x1,y1)) + popupmenu.addAction("Zoom", lambda: self.zoomSelections(x0,y0,x1,y1)) + popupmenu.addAction("Move", lambda: self.moveSelections()) + popupmenu.exec_(self.mapToGlobal(event.pos())) + # self.delete = QtGui.QAction(self.tr('delete'), self) + # self.connect(self.delete, QtCore.SIGNAL('triggered()'), self.deleteItems) + # self.zoom = QtGui.QAction(self.tr('zoom'), self) + # self.connect(self.zoom, QtCore.SIGNAL('triggered()'), self.zoomItem) + # self.move = QtGui.QAction(self.tr('move'), self) + # self.connect(self.move, QtCore.SIGNAL('triggered()'), self.moveItem) + + + + + # else: + # self.layoutPt.plugin.mainWindow.objectEditSlot(self.state["press"]["item"].mobj, True) + self.resetState() + + def drawExpectedConnection(self, event): + self.connectionSource = self.state["press"]["item"] + sourcePoint = self.connectionSource.mapToScene( + self.connectionSource.boundingRect().center() + ) + destinationPoint = self.mapToScene(event.pos()) + if self.expectedConnection is None: + self.expectedConnection = QGraphicsLineItem( sourcePoint.x() + , sourcePoint.y() + , destinationPoint.x() + , destinationPoint.y() + ) + self.expectedConnection.setPen(QPen(Qt.Qt.DashLine)) + + self.sceneContainerPt.addItem(self.expectedConnection) + else: + self.expectedConnection.setLine( sourcePoint.x() + , sourcePoint.y() + , destinationPoint.x() + , destinationPoint.y() + ) + + ''' + print " drawExpectedConnection ()() ",self.state["item"]["press"].mobj + sourcePoint = self.connectionSource.mapToScene( + self.connectionSource.boundingRect().center() + ) + destinationPoint = self.mapToScene(event.pos()) + if self.expectedConnection is None: + self.expectedConnection = QGraphicsLineItem( sourcePoint.x() + , sourcePoint.y() + , destinationPoint.x() + , destinationPoint.y() + ) + self.expectedConnection.setPen(QPen(Qt.Qt.DashLine)) + + self.sceneContainerPt.addItem(self.expectedConnection) + else: + self.expectedConnection.setLine( sourcePoint.x() + , sourcePoint.y() + , destinationPoint.x() + , destinationPoint.y() + ) + ''' + def removeExpectedConnection(self): + #print("removeExpectedConnection") + self.sceneContainerPt.removeItem(self.expectedConnection) + self.expectedConnection = None + self.connectionSource = None + + def removeConnector(self): + try: + for l,k in self.connectorlist.items(): + if k is not None: + self.sceneContainerPt.removeItem(k) + self.connectorlist[l] = None + ''' + if self.connectionSign is not None: + # self.sceneContainerPt.removeItem(self.connectionSign) + # self.connectionSign = None + ''' + except: + #print("Exception received!") + pass + # if self.connectionSign is not None: + # print "self.connectionSign ",self.connectionSign + # self.sceneContainerPt.removeItem(self.connectionSign) + # self.connectionSign = None + + def showConnector(self, item): + self.removeConnector() + self.connectionSource = item + rectangle = item.boundingRect() + + for l in self.connectorlist.keys(): + self.xDisp = 0 + self.yDisp = 0 + self.connectionSign = None + if isinstance(item.mobj,PoolBase) or isinstance(item.mobj,ReacBase): + if l == "clone": + self.connectionSign = QtSvg.QGraphicsSvgItem('icons/clone.svg') + self.connectionSign.setData(0, QtCore.QVariant("clone")) + self.connectionSign.setParent(self.connectionSource) + self.connectionSign.setScale( + (1.0 * rectangle.height()) / self.connectionSign.boundingRect().height() + ) + position = item.mapToParent(rectangle.bottomLeft()) + self.xDisp = 15 + self.yDisp = 2 + self.connectionSign.setZValue(1) + self.connectionSign.setToolTip("Click and drag to clone the object") + self.connectorlist["clone"] = self.connectionSign + if isinstance(item.mobj,PoolBase): + if l == "plot": + self.connectionSign = QtSvg.QGraphicsSvgItem('icons/plot.svg') + self.connectionSign.setData(0, QtCore.QVariant("plot")) + self.connectionSign.setParent(self.connectionSource) + self.connectionSign.setScale( + (1.0 * rectangle.height()) / self.connectionSign.boundingRect().height() + ) + position = item.mapToParent(rectangle.bottomRight()) + #self.xDisp = 15 + #self.yDisp = 2 + self.connectionSign.setZValue(1) + self.connectionSign.setToolTip("plot the object") + self.connectorlist["plot"] = self.connectionSign + + if l == "move": + self.connectionSign = QtSvg.QGraphicsSvgItem('icons/move.svg') + self.connectionSign.setData(0, QtCore.QVariant("move")) + self.connectionSign.setParent(self.connectionSource) + self.connectionSign.setToolTip("Drag to move.") + self.connectionSign.setScale( + (1.0 * rectangle.height()) / self.connectionSign.boundingRect().height() + ) + position = item.mapToParent(rectangle.topLeft()) + self.xDisp = 15 + self.yDisp = 2 + self.connectionSign.setZValue(1) + self.connectorlist["move"] = self.connectionSign + elif l == "delete": + self.connectionSign = QtSvg.QGraphicsSvgItem('icons/delete.svg') + self.connectionSign.setParent(self.connectionSource) + self.connectionSign.setData(0, QtCore.QVariant("delete")) + self.connectionSign.setScale( + (1.0 * rectangle.height()) / self.connectionSign.boundingRect().height() + ) + position = item.mapToParent(rectangle.topRight()) + self.connectionSign.setZValue(1) + self.connectionSign.setToolTip("Delete the object") + self.connectorlist["delete"] = self.connectionSign + + if self.connectionSign != None: + self.connectionSign.setFlag(QtGui.QGraphicsItem.ItemIsSelectable,True) + self.connectionSign.setParentItem(item.parentItem()) + self.connectionSign.setPos(0.0,0.0) + self.connectionSign.moveBy( position.x()-self.xDisp + , position.y() +self.yDisp - rectangle.height() / 2.0 + ) + + def objExist(self,path,name,index): + if index == 0: + fPath = path+'/'+name + else: + fPath = path+'/'+name+'_'+str(index) + if moose.exists(fPath): + index += 1 + return self.objExist(path,name,index) + else: + if index == 0: + return + else: + return ('_'+str(index)) + + def selectSelections(self, selections): + for selection in selections : + if isinstance(selection, KineticsDisplayItem): + self.selections.append(selection) + + def deselectSelections(self): + for selection in self.selections: + selection.setSelected(False) + self.selections = [] + + def mousePressEvent(self, event): + selectedItem = None + if self.viewBaseType == "editorView": + return self.editorMousePressEvent(event) + + elif self.viewBaseType == "runView": + pos = event.pos() + item = self.itemAt(pos) + if item: + itemClass = type(item).__name__ + if ( itemClass!='ComptItem' and itemClass != 'QGraphicsPolygonItem' and + itemClass != 'QGraphicsEllipseItem' and itemClass != 'QGraphicsRectItem'): + self.setCursor(Qt.Qt.CrossCursor) + mimeData = QtCore.QMimeData() + mimeData.setText(item.mobj.name) + mimeData.setData("text/plain", "") + mimeData.data =(self.modelRoot,item.mobj) + drag = QtGui.QDrag(self) + drag.setMimeData(mimeData) + dropAction = drag.start(QtCore.Qt.MoveAction) + self.setCursor(Qt.Qt.ArrowCursor) + + + def mouseMoveEvent(self,event): + if self.viewBaseType == "editorView": + return self.editorMouseMoveEvent(event) + + + def mouseReleaseEvent(self, event): + if self.viewBaseType == "editorView": + for preSelectedItem in self.sceneContainerPt.selectedItems(): + preSelectedItem.setSelected(False) + return self.editorMouseReleaseEvent(event) + + return + + if self.state["press"]["mode"] == CONNECTION: + desPos =self.mapToScene(event.pos()) + destination = self.items(event.pos()) + src = self.state["press"]["item"] + des = [j for j in destination if isinstance(j,KineticsDisplayItem)] + if len(des): + self.populate_srcdes(src.mobj,des[0].mobj) + #print " pop", self.layoutPt.srcdesConnection() + self.setCursor(Qt.Qt.ArrowCursor) + QtGui.QGraphicsView.mouseReleaseEvent(self, event) + '''if(self.customrubberBand): + self.customrubberBand.hide() + self.customrubberBand = 0 + if event.button() == QtCore.Qt.LeftButton and self.itemSelected == False : + self.endingPos = event.pos() + self.endScenepos = self.mapToScene(self.endingPos) + self.rubberbandWidth = (self.endScenepos.x()-self.startScenepos.x()) + self.rubberbandHeight = (self.endScenepos.y()-self.startScenepos.y()) + selecteditems = self.sceneContainerPt.selectedItems() + #print "selecteditems ",selecteditems + if self.rubberbandWidth != 0 and self.rubberbandHeight != 0 and len(selecteditems) != 0 : + self.showpopupmenu = True + ''' + #self.itemSelected = False + ''' + if self.showpopupmenu: + popupmenu = QtGui.QMenu('PopupMenu', self) + self.delete = QtGui.QAction(self.tr('delete'), self) + self.connect(self.delete, QtCore.SIGNAL('triggered()'), self.deleteItems) + self.zoom = QtGui.QAction(self.tr('zoom'), self) + self.connect(self.zoom, QtCore.SIGNAL('triggered()'), self.zoomItem) + self.move = QtGui.QAction(self.tr('move'), self) + self.connect(self.move, QtCore.SIGNAL('triggered()'), self.moveItem) + popupmenu.addAction(self.delete) + popupmenu.addAction(self.zoom) + popupmenu.addAction(self.move) + popupmenu.exec_(event.globalPos()) + self.showpopupmenu = False + ''' + + def updateItemTransformationMode(self, on): + for v in self.sceneContainerPt.items(): + #v.setFlag(QtGui.QGraphicsItem.ItemIgnoresTransformations,on) + if( not isinstance(v,ComptItem)): + #if ( isinstance(v, PoolItem) or isinstance(v, ReacItem) or isinstance(v, EnzItem) or isinstance(v, CplxItem) ): + if isinstance(v,KineticsDisplayItem): + v.setFlag(QtGui.QGraphicsItem.ItemIgnoresTransformations, on) + def keyPressEvent(self,event): + key = event.key() + self.removeConnector() + if (key == Qt.Qt.Key_A and (event.modifiers() & Qt.Qt.ShiftModifier)): # 'A' fits the view to iconScale factor + itemignoreZooming = False + self.updateItemTransformationMode(itemignoreZooming) + self.fitInView(self.sceneContainerPt.itemsBoundingRect().x()-10,self.sceneContainerPt.itemsBoundingRect().y()-10,self.sceneContainerPt.itemsBoundingRect().width()+20,self.sceneContainerPt.itemsBoundingRect().height()+20,Qt.Qt.IgnoreAspectRatio) + self.layoutPt.drawLine_arrow(itemignoreZooming=False) + + elif (key == Qt.Qt.Key_Less or key == Qt.Qt.Key_Minus):# and (event.modifiers() & Qt.Qt.ShiftModifier)): # '<' key. zooms-in to iconScale factor + self.iconScale *= 0.8 + self.updateScale( self.iconScale ) + + elif (key == Qt.Qt.Key_Greater or key == Qt.Qt.Key_Plus):# and (event.modifiers() & Qt.Qt.ShiftModifier)): # '>' key. zooms-out to iconScale factor + self.iconScale *= 1.25 + self.updateScale( self.iconScale ) + + elif (key == Qt.Qt.Key_Period): # '.' key, lower case for '>' zooms in + self.scale(1.1,1.1) + + elif (key == Qt.Qt.Key_Comma): # ',' key, lower case for '<' zooms in + self.scale(1/1.1,1/1.1) + + elif (key == Qt.Qt.Key_A): # 'a' fits the view to initial value where iconscale=1 + self.updateScale( 1 ) + self.fitInView(self.sceneContainerPt.itemsBoundingRect().x()-10,self.sceneContainerPt.itemsBoundingRect().y()-10,self.sceneContainerPt.itemsBoundingRect().width()+20,self.sceneContainerPt.itemsBoundingRect().height()+20,Qt.Qt.IgnoreAspectRatio) + + def updateScale( self, scale ): + for item in self.sceneContainerPt.items(): + if isinstance(item,KineticsDisplayItem): + item.refresh(scale) + #iteminfo = item.mobj.path+'/info' + #xpos,ypos = self.positioninfo(iteminfo) + xpos = item.scenePos().x() + ypos = item.scenePos().y() + if isinstance(item,ReacItem) or isinstance(item,EnzItem) or isinstance(item,MMEnzItem): + item.setGeometry(xpos,ypos, + item.gobj.boundingRect().width(), + item.gobj.boundingRect().height()) + elif isinstance(item,CplxItem): + item.setGeometry(item.gobj.boundingRect().width()/2,item.gobj.boundingRect().height(), + item.gobj.boundingRect().width(), + item.gobj.boundingRect().height()) + elif isinstance(item,PoolItem) or isinstance(item, PoolItemCircle): + item.setGeometry(xpos, ypos,item.gobj.boundingRect().width() + +PoolItem.fontMetrics.width(' '), + item.gobj.boundingRect().height()) + item.bg.setRect(0, 0, item.gobj.boundingRect().width()+PoolItem.fontMetrics.width(' '), item.gobj.boundingRect().height()) + + self.layoutPt.drawLine_arrow(itemignoreZooming=False) + self.layoutPt.comptChilrenBoundingRect() + #compartment width is resize according apart from calculating boundingRect + # for k, v in self.layoutPt.qGraCompt.items(): + # rectcompt = v.childrenBoundingRect() + # comptPen = v.pen() + # comptWidth = self.defaultComptsize*self.iconScale + # comptPen.setWidth(comptWidth) + # v.setPen(comptPen) + # v.setRect(rectcompt.x()-comptWidth,rectcompt.y()-comptWidth,(rectcompt.width()+2*comptWidth),(rectcompt.height()+2*comptWidth)) + + def moveSelections(self): + self.setCursor(Qt.Qt.CrossCursor) + self.move = True + return + + def GrVfitinView(self): + #print " here in GrVfitinView" + itemignoreZooming = False + self.layoutPt.updateItemTransformationMode(itemignoreZooming) + self.fitInView(self.sceneContainerPt.itemsBoundingRect().x()-10,self.sceneContainerPt.itemsBoundingRect().y()-10,self.sceneContainerPt.itemsBoundingRect().width()+20,self.sceneContainerPt.itemsBoundingRect().height()+20,Qt.Qt.IgnoreAspectRatio) + self.layoutPt.drawLine_arrow(itemignoreZooming=False) + + def deleteSelections(self,x0,y0,x1,y1): + if( x1-x0 > 0 and y1-y0 >0): + self.rubberbandlist = self.sceneContainerPt.items(self.mapToScene(QtCore.QRect(x0, y0, x1 - x0, y1 - y0)).boundingRect(), Qt.Qt.IntersectsItemShape) + for unselectitem in self.rubberbandlist: + if unselectitem.isSelected() == True: + unselectitem.setSelected(0) + self.deleteObj(self.rubberbandlist) + # deleteSolver(self.layoutPt.modelRoot) + # for item in (qgraphicsitem for qgraphicsitem in self.rubberbandlist): + # #First Loop to remove all the enz b'cos if parent (which is a Pool) is removed, + # #then it will created problem at qgraphicalitem not having parent. + # #So first delete enz and then delete pool + # if isinstance(item,MMEnzItem) or isinstance(item,EnzItem) or isinstance(item,CplxItem): + # self.deleteItem(item) + # for item in (qgraphicsitem for qgraphicsitem in self.rubberbandlist): + # if not (isinstance(item,MMEnzItem) or isinstance(item,EnzItem) or isinstance(item,CplxItem)): + # if isinstance(item,PoolItem): + # plot = moose.wildcardFind(self.layoutPt.modelRoot+'/data/graph#/#') + # for p in plot: + # if len(p.neighbors['requestOut']): + # if item.mobj.path == moose.element(p.neighbors['requestOut'][0]).path: + # p.tick = -1 + # moose.delete(p) + # self.layoutPt.plugin.view.getCentralWidget().plotWidgetContainer.plotAllData() + # self.deleteItem(item) + self.selections = [] + def deleteObj(self,item): + self.rubberbandlist = item + deleteSolver(self.layoutPt.modelRoot) + for item in (qgraphicsitem for qgraphicsitem in self.rubberbandlist): + #First Loop to remove all the enz b'cos if parent (which is a Pool) is removed, + #then it will created problem at qgraphicalitem not having parent. + #So first delete enz and then delete pool + if isinstance(item,MMEnzItem) or isinstance(item,EnzItem) or isinstance(item,CplxItem): + self.deleteItem(item) + for item in (qgraphicsitem for qgraphicsitem in self.rubberbandlist): + if not (isinstance(item,MMEnzItem) or isinstance(item,EnzItem) or isinstance(item,CplxItem)): + if isinstance(item,PoolItem): + plot = moose.wildcardFind(self.layoutPt.modelRoot+'/data/graph#/#') + for p in plot: + if len(p.neighbors['requestOut']): + if item.mobj.path == moose.element(p.neighbors['requestOut'][0]).path: + p.tick = -1 + moose.delete(p) + self.layoutPt.plugin.view.getCentralWidget().plotWidgetContainer.plotAllData() + self.deleteItem(item) + + def deleteObject2line(self,qpolygonline,src,des,endt): + object2lineInfo = self.layoutPt.object2line[des] + if len(object2lineInfo) == 1: + for polygon,objdes,endtype,numL in object2lineInfo: + if polygon == qpolygonline and objdes == src and endtype == endt: + del(self.layoutPt.object2line[des]) + else: + print " check this condition when is len is single and else condition",qpolygonline, objdes,endtype + else: + n = 0 + for polygon,objdes,endtype,numL in object2lineInfo: + if polygon == qpolygonline and objdes == src and endtype == endt: + tup = object2lineInfo[:n]+object2lineInfo[n+1:] + self.layoutPt.object2line[des] = tup + #d[keyNo].append((a,b,c)) + else: + n = n+1 + + def deleteConnection(self,item): + #Delete moose connection, i.e one can click on connection arrow and delete the connection + deleteSolver(self.layoutPt.modelRoot) + msgIdforDeleting = " " + if isinstance(item,QtGui.QGraphicsPolygonItem): + src = self.layoutPt.lineItem_dict[item] + lineItem_value = self.layoutPt.lineItem_dict[item] + i = iter(lineItem_value) + source = i.next() + destination = i.next() + endt = i.next() + numl = i.next() + self.deleteObject2line(item,source,destination,endt) + self.deleteObject2line(item,destination,source,endt) + try: + del self.layoutPt.lineItem_dict[item] + except KeyError: + pass + srcZero = [k for k, v in self.layoutPt.mooseId_GObj.iteritems() if v == src[0]] + srcOne = [k for k, v in self.layoutPt.mooseId_GObj.iteritems() if v == src[1]] + + if isinstance (moose.element(srcZero[0]),moose.MMenz): + gItem =self.layoutPt.mooseId_GObj[moose.element(srcZero[0])] + # This block is done b'cos for MMenz while loaded from ReadKKit, the msg + # from parent pool to Enz is different as compared to direct model building. + # if ReadKKit get the msg from parent Pool, else from MMenz itself. + + # Rules: If some one tries to remove connection parent Pool to Enz + # then delete entire enz itself, this is True for enz and mmenz + for msg in srcZero[0].msgIn: + if moose.element(msg.e1.path) == moose.element(srcOne[0].path): + if src[2] == "t": + if msg.destFieldsOnE2[0] == "enzDest": + # delete indivial msg if later adding parent is possible + # msgIdforDeleting = msg + # moose.delete(msgIdforDeleting) + # self.sceneContainerPt.removeItem(item) + self.deleteItem(gItem) + return + else: + self.getMsgId(src,srcZero,srcOne,item) + moose.delete(msgIdforDeleting) + self.sceneContainerPt.removeItem(item) + setupItem(self.modelRoot,self.layoutPt.srcdesConnection) + for msg in moose.element(srcZero[0].parent).msgIn: + if moose.element(msg.e2.path) == moose.element(srcZero[0].parent.path): + if src[2] == 't': + if len(msg.destFieldsOnE1) > 0: + if msg.destFieldsOnE1[0] == "enzDest": + # delete indivial msg if later adding parent is possible + # msgIdforDeleting = msg + # moose.delete(msgIdforDeleting) + # self.sceneContainerPt.removeItem(item) + self.deleteItem(gItem) + return + else: + self.getMsgId(src,srcZero,srcOne,item) + + elif isinstance (moose.element(srcZero[0]),moose.Enz): + self.getMsgId(src,srcZero,srcOne,item) + + elif isinstance(moose.element(srcZero[0]),moose.Function): + v = moose.Variable(srcZero[0].path+'/x') + found = False + for msg in v.msgIn: + if moose.element(msg.e1.path) == moose.element(srcOne[0].path): + if src[2] == "sts": + if msg.destFieldsOnE2[0] == "input": + msgIdforDeleting = msg + self.deleteSceneObj(msgIdforDeleting,item) + found = True + if not found: + for msg in srcZero[0].msgOut: + if moose.element(msg.e2.path) == moose.element(srcOne[0].path): + if src[2] == "stp": + if msg.destFieldsOnE2[0] == "setN": + gItem =self.layoutPt.mooseId_GObj[moose.element(srcZero[0])] + self.deleteItem(gItem) + self.deleteSceneObj(msg,item) + return + elif msg.destFieldsOnE2[0] == "setNumKf" or msg.destFieldsOnE2[0] == "setConcInit" or msg.destFieldsOnE2[0]=="increment": + msgIdforDeleting = msg + self.deleteSceneObj(msgIdforDeleting,item) + gItem =self.layoutPt.mooseId_GObj[moose.element(srcZero[0])] + self.deleteItem(gItem) + + else: + self.getMsgId(src,srcZero,srcOne,item) + + def deleteSceneObj(self,msgIdforDeleting,item): + moose.delete(msgIdforDeleting) + self.sceneContainerPt.removeItem(item) + setupItem(self.modelRoot,self.layoutPt.srcdesConnection) + + def getMsgId(self,src,srcZero,srcOne,item): + for msg in srcZero[0].msgOut: + msgIdforDeleting = " " + if moose.element(msg.e2.path) == moose.element(srcOne[0].path): + if src[2] == 's': + # substrate connection for R,E + if msg.srcFieldsOnE1[0] == "subOut": + msgIdforDeleting = msg + self.deleteSceneObj(msgIdforDeleting,item) + return + elif src[2] == 'p': + # product connection for R,E + if msg.srcFieldsOnE1[0] == "prdOut": + msgIdforDeleting = msg + self.deleteSceneObj(msgIdforDeleting,item) + return + elif src[2] == 't': + if msg.srcFieldsOnE1[0] == "enzOut": + gItem =self.layoutPt.mooseId_GObj[moose.element(srcZero[0])] + self.deleteItem(gItem) + return + elif src[2] == 'tab': + #stimulation Table connection + if msg.srcFieldsOnE1[0] == "output": + msgIdforDeleting = msg + self.deleteSceneObj(msgIdforDeleting,item) + return + + def deleteItem(self,item): + #delete Items + + self.layoutPt.plugin.mainWindow.objectEditSlot('/', False) + if isinstance(item,KineticsDisplayItem): + if moose.exists(item.mobj.path): + # if isinstance(item.mobj,Function): + # print " inside the function" + # for items in moose.element(item.mobj.path).children: + # print items + if isinstance(item,PoolItem) or isinstance(item,BufPool): + # pool is item is removed, then check is made if its a parent to any + # enz if 'yes', then enz and its connection are removed before + # removing Pool + for items in moose.element(item.mobj.path).children: + # if isinstance(moose.element(items), Function): + # gItem = self.layoutPt.mooseId_GObj[moose.element(items)] + # for l in self.layoutPt.object2line[gItem]: + # sceneItems = self.sceneContainerPt.items() + # if l[0] in sceneItems: + # #deleting the connection which is connected to Enz + # self.sceneContainerPt.removeItem(l[0]) + # moose.delete(items) + # self.sceneContainerPt.removeItem(gItem) + if isinstance(moose.element(items), EnzBase): + gItem = self.layoutPt.mooseId_GObj[moose.element(items)] + for l in self.layoutPt.object2line[gItem]: + # Need to check if the connection on the scene exist + # or its removed from some other means + # E.g Enz to pool and pool to Enz is connected, + # when enz is removed the connection is removed, + # but when pool tried to remove then qgraphicscene says + # "item scene is different from this scene" + sceneItems = self.sceneContainerPt.items() + if l[0] in sceneItems: + #deleting the connection which is connected to Enz + self.sceneContainerPt.removeItem(l[0]) + moose.delete(items) + self.sceneContainerPt.removeItem(gItem) + #If pool/bufpool is input to a function and if pool/bufpool is removed then function is also removed. + for msg in moose.element(item.mobj.path).msgOut: + if (moose.element(msg.e2.path).className == "Variable" and msg.destFieldsOnE2[0]=="input"): + funcp = moose.element(msg.e2.path).parent + pool = moose.element(funcp).parent + self.deleteItem(self.layoutPt.mooseId_GObj[funcp]) + + for l in self.layoutPt.object2line[item]: + sceneItems = self.sceneContainerPt.items() + if l[0] in sceneItems: + self.sceneContainerPt.removeItem(l[0]) + self.sceneContainerPt.removeItem(item) + moose.delete(item.mobj) + for key, value in self.layoutPt.object2line.items(): + self.layoutPt.object2line[key] = filter( lambda tup: tup[1] != item ,value) + self.layoutPt.getMooseObj() + setupItem(self.modelRoot,self.layoutPt.srcdesConnection) + + def zoomSelections(self, x0, y0, x1, y1): + p0 = self.mapToScene(x0, y0) + p1 = self.mapToScene(x1, y1) + #print QtCore.QRectF(p0, p1) + self.fitInView(QtCore.QRectF(p0, p1), Qt.Qt.KeepAspectRatio) + self.deselectSelections() + return + + + def wheelEvent(self,event): + factor = 1.41 ** (event.delta() / 240.0) + self.scale(factor, factor) + + + def dragEnterEvent(self, event): + if self.viewBaseType == "editorView": + if event.mimeData().hasFormat('text/plain'): + event.acceptProposedAction() + else: + pass + + def dragMoveEvent(self, event): + if self.viewBaseType == "editorView": + if event.mimeData().hasFormat('text/plain'): + event.acceptProposedAction() + else: + pass + + def eventFilter(self, source, event): + if self.viewBase == "editorView": + if (event.type() == QtCore.QEvent.Drop): + pass + else: + pass + + def dropEvent(self, event): + """Insert an element of the specified class in drop location""" + """ Pool and reaction should have compartment as parent, dropping outside the compartment is not allowed """ + """ Enz should be droped on the PoolItem which inturn will be under compartment""" + if self.viewBaseType == "editorView": + if not event.mimeData().hasFormat('text/plain'): + return + event_pos = event.pos() + string = str(event.mimeData().text()) + createObj(self.viewBaseType,self,self.modelRoot,string,event_pos,self.layoutPt) + + def populate_srcdes(self,src,des): + self.modelRoot = self.layoutPt.modelRoot + callsetupItem = True + #print " populate_srcdes ",src,des + srcClass = moose.element(src).className + if 'Zombie' in srcClass: + srcClass = srcClass.split('Zombie')[1] + desClass = moose.element(des).className + if 'Zombie' in desClass: + desClass = desClass.split('Zombie')[1] + if ( isinstance(moose.element(src),PoolBase) and ( (isinstance(moose.element(des),ReacBase) ) or isinstance(moose.element(des),EnzBase) )): + #If one to tries to connect pool to Reac/Enz (substrate to Reac/Enz), check if already (product to Reac/Enz) exist. + #If exist then connection not allowed one need to delete the msg and try connecting back. + found = False + for msg in des.msgOut: + if moose.element(msg.e2.path) == src: + if msg.srcFieldsOnE1[0] == "prdOut": + found = True + if found == False: + # moose.connect(src, 'reac', des, 'sub', 'OneToOne') + moose.connect(des, 'sub', src, 'reac', 'OneToOne') + else: + srcdesString = srcClass+' is already connected as '+ '\'Product\''+' to '+desClass +' \n \nIf you wish to connect this object then first delete the exist connection' + QtGui.QMessageBox.information(None,'Connection Not possible','{srcdesString}'.format(srcdesString = srcdesString),QtGui.QMessageBox.Ok) + + elif (isinstance (moose.element(src),PoolBase) and (isinstance(moose.element(des),Function))): + numVariables = des.numVars + expr = "" + expr = (des.expr+'+'+'x'+str(numVariables)) + expr = expr.lstrip("0 +") + expr = expr.replace(" ","") + des.expr = expr + moose.connect( src, 'nOut', des.x[numVariables], 'input' ) + + elif ( isinstance(moose.element(src),Function) and (moose.element(des).className=="Pool") ): + if ((element(des).parent).className != 'Enz'): + moose.connect(src, 'valueOut', des, 'increment', 'OneToOne') + else: + srcdesString = element(src).className+'-- EnzCplx' + QtGui.QMessageBox.information(None,'Connection Not possible','\'{srcdesString}\' not allowed to connect'.format(srcdesString = srcdesString),QtGui.QMessageBox.Ok) + callsetupItem = False + elif ( isinstance(moose.element(src),Function) and (moose.element(des).className=="BufPool") ): + moose.connect(src, 'valueOut', des, 'setN', 'OneToOne') + elif ( isinstance(moose.element(src),Function) and (isinstance(moose.element(des),ReacBase) ) ): + moose.connect(src, 'valueOut', des, 'setNumKf', 'OneToOne') + elif (((isinstance(moose.element(src),ReacBase))or (isinstance(moose.element(src),EnzBase))) and (isinstance(moose.element(des),PoolBase))): + found = False + for msg in src.msgOut: + if moose.element(msg.e2.path) == des: + if msg.srcFieldsOnE1[0] == "subOut": + found = True + if found == False: + #moose.connect(src, 'prd', des, 'reac', 'OneToOne') + moose.connect(src, 'prd', des, 'reac', 'OneToOne') + else: + srcdesString = desClass+' is already connected as '+'\'Substrate\''+' to '+srcClass +' \n \nIf you wish to connect this object then first delete the exist connection' + QtGui.QMessageBox.information(None,'Connection Not possible','{srcdesString}'.format(srcdesString = srcdesString),QtGui.QMessageBox.Ok) + # elif( isinstance(moose.element(src),ReacBase) and (isinstance(moose.element(des),PoolBase) ) ): + # moose.connect(src, 'prd', des, 'reac', 'OneToOne') + # elif( isinstance(moose.element(src),EnzBase) and (isinstance(moose.element(des),PoolBase) ) ): + # moose.connect(src, 'prd', des, 'reac', 'OneToOne') + elif( isinstance(moose.element(src),StimulusTable) and (isinstance(moose.element(des),PoolBase) ) ): + moose.connect(src, 'output', des, 'setConcInit', 'OneToOne') + else: + srcString = moose.element(src).className + desString = moose.element(des).className + srcdesString = srcString+'--'+desString + QtGui.QMessageBox.information(None,'Connection Not possible','\'{srcdesString}\' not allowed to connect'.format(srcdesString = srcdesString),QtGui.QMessageBox.Ok) + callsetupItem = False + + if callsetupItem: + self.layoutPt.getMooseObj() + setupItem(self.modelRoot,self.layoutPt.srcdesConnection) + self.layoutPt.drawLine_arrow(False) + diff --git a/moose-gui/plugins/list.txt b/moose-gui/plugins/list.txt new file mode 100644 index 0000000000000000000000000000000000000000..c3e68ca7e52c133afc56589791d43db4ba9a8547 --- /dev/null +++ b/moose-gui/plugins/list.txt @@ -0,0 +1,3 @@ +kkit +NeuroKit + diff --git a/moose-gui/plugins/modelBuild.py b/moose-gui/plugins/modelBuild.py new file mode 100644 index 0000000000000000000000000000000000000000..80b77e0d877ddbf59a13a327f3847a5cd4a00441 --- /dev/null +++ b/moose-gui/plugins/modelBuild.py @@ -0,0 +1,286 @@ +import moose +from kkitQGraphics import * +from kkitOrdinateUtil import * +from kkitUtil import * +import PyQt4 +from setsolver import * + +def updateCompartmentSize(qGraCompt): + #childBoundingRect = qGraCompt.childrenBoundingRect() + childBoundingRect = calculateChildBoundingRect(qGraCompt) + comptBoundingRect = qGraCompt.boundingRect() + rectcompt = comptBoundingRect.united(childBoundingRect) + comptPen = qGraCompt.pen() + comptWidth = 1 + comptPen.setWidth(comptWidth) + qGraCompt.setPen(comptPen) + if not comptBoundingRect.contains(childBoundingRect): + qGraCompt.setRect(rectcompt.x()-comptWidth,rectcompt.y()-comptWidth,rectcompt.width()+(comptWidth*2),rectcompt.height()+(comptWidth*2)) + +# def checkCreate(string,num,itemAt,qGraCompt,modelRoot,scene,pos,posf,view,qGIMob): +def checkCreate(scene,view,modelpath,mobj,string,ret_string,num,event_pos,layoutPt): + # The variable 'compt' will be empty when dropping cubeMesh,cyclMesh, but rest it shd be + # compartment + # if modelpath.find('/',1) > -1: + # modelRoot = modelpath[0:modelpath.find('/',1)] + # else: + # modelRoot = modelpath + if moose.exists(modelpath+'/info'): + mType = moose.Annotator((moose.element(modelpath+'/info'))).modeltype + + itemAtView = view.sceneContainerPt.itemAt(view.mapToScene(event_pos)) + pos = view.mapToScene(event_pos) + modelpath = moose.element(modelpath) + + if num: + string_num = ret_string+str(num) + else: + string_num = ret_string + if string == "CubeMesh" or string == "CylMesh": + if string == "CylMesh": + mobj = moose.CylMesh(modelpath.path+'/'+string_num) + else: + mobj = moose.CubeMesh(modelpath.path+'/'+string_num) + + mobj.volume = 1e-15 + mesh = moose.element(mobj.path+'/mesh') + qGItem = ComptItem(scene,pos.toPoint().x(),pos.toPoint().y(),500,500,mobj) + qGItem.setPen(QtGui.QPen(Qt.QColor(66,66,66,100), 1, Qt.Qt.SolidLine, Qt.Qt.RoundCap, Qt.Qt.RoundJoin)) + view.sceneContainerPt.addItem(qGItem) + qGItem.cmptEmitter.connect(qGItem.cmptEmitter,QtCore.SIGNAL("qgtextPositionChange(PyQt_PyObject)"),layoutPt.positionChange1) + qGItem.cmptEmitter.connect(qGItem.cmptEmitter,QtCore.SIGNAL("qgtextItemSelectedChange(PyQt_PyObject)"),layoutPt.objectEditSlot) + compartment = qGItem + layoutPt.qGraCompt[mobj]= qGItem + view.emit(QtCore.SIGNAL("dropped"),mobj) + + elif string == "Pool" or string == "BufPool": + #getting pos with respect to compartment otherwise if compartment is moved then pos would be wrong + posWrtComp = (itemAtView.mapFromScene(pos)).toPoint() + if string == "Pool": + poolObj = moose.Pool(mobj.path+'/'+string_num) + else: + poolObj = moose.BufPool(mobj.path+'/'+string_num) + + poolinfo = moose.Annotator(poolObj.path+'/info') + #Compartment's one Pool object is picked to get the font size + + + qGItem = PoolItem(poolObj,itemAtView) + layoutPt.mooseId_GObj[poolObj] = qGItem + posWrtComp = (itemAtView.mapFromScene(pos)).toPoint() + bgcolor = getRandColor() + qGItem.setDisplayProperties(posWrtComp.x(),posWrtComp.y(),QtGui.QColor('green'),bgcolor) + poolinfo.color = str(bgcolor.getRgb()) + if mType == "new_kkit": + poolinfo.x = posWrtComp.x() + poolinfo.y = posWrtComp.y() + view.emit(QtCore.SIGNAL("dropped"),poolObj) + setupItem(modelpath.path,layoutPt.srcdesConnection) + layoutPt.drawLine_arrow(False) + #Dropping is on compartment then update Compart size + if isinstance(mobj,moose.ChemCompt): + compt = layoutPt.qGraCompt[moose.element(mobj)] + updateCompartmentSize(compt) + + elif string == "Reac": + posWrtComp = (itemAtView.mapFromScene(pos)).toPoint() + reacObj = moose.Reac(mobj.path+'/'+string_num) + reacinfo = moose.Annotator(reacObj.path+'/info') + qGItem = ReacItem(reacObj,itemAtView) + qGItem.setDisplayProperties(posWrtComp.x(),posWrtComp.y(),"white", "white") + if mType == "new_kkit": + reacinfo.x = posWrtComp.x() + reacinfo.y = posWrtComp.y() + layoutPt.mooseId_GObj[reacObj] = qGItem + view.emit(QtCore.SIGNAL("dropped"),reacObj) + setupItem(modelpath.path,layoutPt.srcdesConnection) + layoutPt.drawLine_arrow(False) + #Dropping is on compartment then update Compart size + if isinstance(mobj,moose.ChemCompt): + compt = layoutPt.qGraCompt[moose.element(mobj)] + updateCompartmentSize(compt) + + elif string == "StimulusTable": + posWrtComp = (itemAtView.mapFromScene(pos)).toPoint() + tabObj = moose.StimulusTable(mobj.path+'/'+string_num) + tabinfo = moose.Annotator(tabObj.path+'/info') + qGItem = TableItem(tabObj,itemAtView) + qGItem.setDisplayProperties(posWrtComp.x(),posWrtComp.y(),QtGui.QColor('white'),QtGui.QColor('white')) + if mType == "new_kkit": + tabinfo.x = posWrtComp.x() + tabinfo.y = posWrtComp.y() + layoutPt.mooseId_GObj[tabObj] = qGItem + view.emit(QtCore.SIGNAL("dropped"),tabObj) + setupItem(modelpath.path,layoutPt.srcdesConnection) + layoutPt.drawLine_arrow(False) + #Dropping is on compartment then update Compart size + if isinstance(mobj,moose.ChemCompt): + compt = layoutPt.qGraCompt[moose.element(mobj)] + updateCompartmentSize(compt) + elif string == "Function": + posWrtComp = (itemAtView.mapFromScene(pos)).toPoint() + + funcObj = moose.Function(mobj.path+'/'+string_num) + funcinfo = moose.Annotator(funcObj.path+'/info') + moose.connect( funcObj, 'valueOut', mobj ,'setN' ) + funcParent = layoutPt.mooseId_GObj[element(mobj.path)] + qGItem = FuncItem(funcObj,funcParent) + #print " function ", posWrtComp.x(),posWrtComp.y() + qGItem.setDisplayProperties(posWrtComp.x(),posWrtComp.y(),QtGui.QColor('red'),QtGui.QColor('green')) + layoutPt.mooseId_GObj[funcObj] = qGItem + if mType == "new_kkit": + funcinfo.x = posWrtComp.x() + funcinfo.y = posWrtComp.y() + view.emit(QtCore.SIGNAL("dropped"),funcObj) + setupItem(modelpath.path,layoutPt.srcdesConnection) + layoutPt.drawLine_arrow(False) + #Dropping is on compartment then update Compart size + mooseCmpt = findCompartment(mobj) + if isinstance(mooseCmpt,moose.ChemCompt): + compt = layoutPt.qGraCompt[moose.element(mooseCmpt)] + updateCompartmentSize(compt) + + elif string == "Enz" or string == "MMenz": + #If 2 enz has same pool parent, then pos of the 2nd enz shd be displaced by some position, need to check how to deal with it + posWrtComp = pos + enzPool = layoutPt.mooseId_GObj[mobj] + if ((mobj.parent).className == "Enz"): + QtGui.QMessageBox.information(None,'Drop Not possible','\'{newString}\' has to have Pool as its parent and not Enzyme Complex'.format(newString =string),QtGui.QMessageBox.Ok) + return + else: + enzparent = findCompartment(mobj) + parentcompt = layoutPt.qGraCompt[enzparent] + if string == "Enz": + enzObj = moose.Enz(moose.element(mobj).path+'/'+string_num) + enzinfo = moose.Annotator(enzObj.path+'/info') + moose.connect( enzObj, 'enz', mobj, 'reac' ) + qGItem = EnzItem(enzObj,parentcompt) + layoutPt.mooseId_GObj[enzObj] = qGItem + posWrtComp = pos + bgcolor = getRandColor() + qGItem.setDisplayProperties(posWrtComp.x(),posWrtComp.y()-40,QtGui.QColor('green'),bgcolor) + if mType == "new_kkit": + enzinfo.x = posWrtComp.x() + enzinfo.y = posWrtComp.y() + enzinfo.color = str(bgcolor.name()) + e = moose.Annotator(enzinfo) + #e.x = posWrtComp.x() + #e.y = posWrtComp.y() + Enz_cplx = enzObj.path+'/'+string_num+'_cplx'; + cplxItem = moose.Pool(Enz_cplx) + cplxinfo = moose.Annotator(cplxItem.path+'/info') + qGEnz = layoutPt.mooseId_GObj[enzObj] + qGItem = CplxItem(cplxItem,qGEnz) + layoutPt.mooseId_GObj[cplxItem] = qGItem + enzboundingRect = qGEnz.boundingRect() + moose.connect( enzObj, 'cplx', cplxItem, 'reac' ) + qGItem.setDisplayProperties(enzboundingRect.height()/2,enzboundingRect.height()-40,QtGui.QColor('white'),QtGui.QColor('white')) + cplxinfo.x = enzboundingRect.height()/2 + cplxinfo.y = enzboundingRect.height()-60 + view.emit(QtCore.SIGNAL("dropped"),enzObj) + + else: + enzObj = moose.MMenz(mobj.path+'/'+string_num) + enzinfo = moose.Annotator(enzObj.path+'/info') + moose.connect(mobj,"nOut",enzObj,"enzDest") + qGItem = MMEnzItem(enzObj,parentcompt) + posWrtComp = pos + bgcolor = getRandColor() + qGItem.setDisplayProperties(posWrtComp.x(),posWrtComp.y()-30,QtGui.QColor('green'),bgcolor) + enzinfo.x = posWrtComp.x() + enzinfo.y = posWrtComp.y() + enzinfo.color = str(bgcolor.name()) + layoutPt.mooseId_GObj[enzObj] = qGItem + view.emit(QtCore.SIGNAL("dropped"),enzObj) + setupItem(modelpath.path,layoutPt.srcdesConnection) + layoutPt.drawLine_arrow(False) + #Dropping is on compartment then update Compart size + if isinstance(enzparent,moose.ChemCompt): + updateCompartmentSize(parentcompt) + if view.iconScale != 1: + view.updateScale(view.iconScale) + +def createObj(scene,view,modelpath,string,pos,layoutPt): + event_pos = pos + num = 0 + ret_string = " " + pos = view.mapToScene(event_pos) + itemAt = view.sceneContainerPt.itemAt(pos) + chemMesh = moose.wildcardFind(modelpath+'/##[ISA=ChemCompt]') + deleteSolver(modelpath) + mobj = "" + + if itemAt != None: + itemAtView = view.sceneContainerPt.itemAt(view.mapToScene(event_pos)) + itemClass = type(itemAtView).__name__ + if ( itemClass == 'QGraphicsRectItem'): + mobj = itemAtView.parentItem().mobj + elif(itemClass == 'QGraphicsSvgItem'): + mobj = itemAtView.parent().mobj + else: + mobj = itemAtView.mobj + + if string == "CubeMesh" or string == "CylMesh": + ret_string,num = findUniqId(moose.element(modelpath),"Compartment",0) + comptexist = moose.wildcardFind(modelpath+'/##[ISA=ChemCompt]') + if not len(comptexist): + if itemAt != None: + QtGui.QMessageBox.information(None,'Drop Not possible','\'{newString}\' currently single compartment model building is allowed'.format(newString =string),QtGui.QMessageBox.Ok) + return + else: + mobj = moose.element(modelpath) + else: + QtGui.QMessageBox.information(None,'Drop Not possible','\'{newString}\' currently single compartment model building is allowed'.format(newString =string),QtGui.QMessageBox.Ok) + return + + elif string == "Pool" or string == "BufPool" or string == "Reac" or string == "StimulusTable": + if itemAt == None: + QtGui.QMessageBox.information(None,'Drop Not possible','\'{newString}\' has to have compartment as its parent'.format(newString =string),QtGui.QMessageBox.Ok) + return + else: + mobj = findCompartment(mobj) + ret_string,num = findUniqId(mobj,string,num) + + elif string == "Function": + if itemAt != None: + if ((mobj).className != "BufPool"): + QtGui.QMessageBox.information(None,'Drop Not possible','\'{newString}\' has to have BufPool as its parent'.format(newString =string),QtGui.QMessageBox.Ok) + return + else: + ret_string,num = findUniqId(mobj,string,num) + else: + QtGui.QMessageBox.information(None,'Drop Not possible','\'{newString}\' has to have BufPool as its parent'.format(newString =string),QtGui.QMessageBox.Ok) + return + + elif string == "Enz" or string == "MMenz": + if itemAt != None: + if ((mobj).className != "Pool" and (mobj).className != "BufPool"): + QtGui.QMessageBox.information(None,'Drop Not possible','\'{newString}\' has to have Pool as its parent'.format(newString =string),QtGui.QMessageBox.Ok) + return + else: + ret_string,num = findUniqId(mobj,string,num) + else: + QtGui.QMessageBox.information(None,'Drop Not possible','\'{newString}\' has to have Pool as its parent'.format(newString =string),QtGui.QMessageBox.Ok) + return + + if ret_string != " ": + checkCreate(scene,view,modelpath,mobj,string,ret_string,num,event_pos,layoutPt) + +def findUniqId(mobj,string,num): + if num == 0: + path = mobj.path+'/'+string; + else: + path = mobj.path+'/'+string+str(num); + if not moose.exists(path): + return(string,num) + else: + num +=1; + return(findUniqId(mobj,string,num)) + +def findCompartment(mooseObj): + if mooseObj.path == '/': + return None + elif isinstance(mooseObj,ChemCompt): + return (mooseObj) + else: + return findCompartment(moose.element(mooseObj.parent)) \ No newline at end of file diff --git a/moose-gui/plugins/setsolver.py b/moose-gui/plugins/setsolver.py new file mode 100644 index 0000000000000000000000000000000000000000..ae6fb418d053a7de93f02281bbeadedcf6e1c7f6 --- /dev/null +++ b/moose-gui/plugins/setsolver.py @@ -0,0 +1,74 @@ +import moose + +def deleteSolver(modelRoot): + compts = moose.wildcardFind(modelRoot+'/##[ISA=ChemCompt]') + for compt in compts: + if moose.exists(compt.path+'/stoich'): + st = moose.element(compt.path+'/stoich') + st_ksolve = st.ksolve + moose.delete(st) + if moose.exists((st_ksolve).path): + moose.delete(st_ksolve) + +def addSolver(modelRoot,solver): + compt = moose.wildcardFind(modelRoot+'/##[ISA=ChemCompt]') + if compt: + comptinfo = moose.Annotator(moose.element(compt[0]).path+'/info') + previousSolver = comptinfo.solver + currentSolver = previousSolver + if solver == "Gillespie": + currentSolver = "gssa" + elif solver == "Runge Kutta": + currentSolver = "gsl" + elif solver == "Exponential Euler": + currentSolver = "ee" + + if previousSolver != currentSolver: + # if previousSolver != currentSolver + comptinfo.solver = currentSolver + if (moose.exists(compt[0].path+'/stoich')): + # "A: and stoich exists then delete the stoich add solver" + deleteSolver(modelRoot) + setCompartmentSolver(modelRoot,currentSolver) + return True + else: + # " B: stoich doesn't exists then addSolver, this is when object is deleted which delete's the solver " + # " and solver is also changed, then add addsolver " + setCompartmentSolver(modelRoot,currentSolver) + return True + else: + if moose.exists(compt[0].path+'/stoich'): + # " stoich exist, doing nothing" + return False + else: + # "but stoich doesn't exist,this is when object is deleted which deletes the solver + # " but solver are not changed, then also call addSolver" + setCompartmentSolver(modelRoot,currentSolver) + return True + return False + +def setCompartmentSolver(modelRoot,solver): + compts = moose.wildcardFind(modelRoot+'/##[ISA=ChemCompt]') + for compt in compts: + if ( solver == 'gsl' ) or (solver == 'Runge Kutta'): + ksolve = moose.Ksolve( compt.path+'/ksolve' ) + if ( solver == 'gssa' ) or (solver == 'Gillespie'): + ksolve = moose.Gsolve( compt.path+'/gsolve' ) + if ( solver != 'ee' ): + stoich = moose.Stoich( compt.path+'/stoich' ) + stoich.compartment = compt + stoich.ksolve = ksolve + if moose.exists(compt.path): + stoich.path = compt.path+"/##" + stoichList = moose.wildcardFind(modelRoot+'/##[ISA=Stoich]') + if len( stoichList ) == 2: + stoichList[1].buildXreacs( stoichList[0] ) + if len( stoichList ) == 3: + stoichList[1].buildXreacs (stoichList [0]) + stoichList[1].buildXreacs (stoichList [2]) + + for i in stoichList: + i.filterXreacs() + + for x in moose.wildcardFind( modelRoot+'/data/graph#/#' ): + x.tick = 18 \ No newline at end of file diff --git a/moose-gui/plugins/test_plotwidget.py b/moose-gui/plugins/test_plotwidget.py new file mode 100644 index 0000000000000000000000000000000000000000..72c0a33c0066fe77854a8d5e4c4afe591faa767b --- /dev/null +++ b/moose-gui/plugins/test_plotwidget.py @@ -0,0 +1,91 @@ +# test_plotwidget.py --- +# +# Filename: test_plotwidget.py +# Description: +# Author: +# Maintainer: +# Created: Tue Mar 12 12:17:23 2013 (+0530) +# Version: +# Last-Updated: Tue Mar 12 12:26:42 2013 (+0530) +# By: subha +# Update #: 31 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: +import sys +import os +import numpy as np +from PyQt4 import QtGui, QtCore +from PyQt4.Qt import Qt +from matplotlib import mlab +from matplotlib.figure import Figure +from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas +from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar +import unittest +sys.path.append('..') +from default import PlotWidget +import moose +import config + +class PlotWidgetTests(unittest.TestCase): + def setUp(self): + self.app = QtGui.QApplication([]) + QtGui.qApp = self.app + icon = QtGui.QIcon(os.path.join(config.KEY_ICON_DIR,'moose_icon.png')) + self.model = moose.loadModel('../../Demos/Genesis_files/acc68.g', '/acc68') + self.app.setWindowIcon(icon) + self.window = QtGui.QMainWindow() + self.window.setWindowTitle('Test plot widget') + self.mdiArea = QtGui.QMdiArea() + self.window.setCentralWidget(self.mdiArea) + self.widget = PlotWidget() + self.widget.setDataRoot(self.model.path) + self.mdiArea.addSubWindow(self.widget) + self.window.show() + + def testPlotAllData(self): + """Test plot function""" + self.widget.plotAllData() + + def tearDown(self): + self.app.exec_() + +if __name__ == '__main__': + unittest.main() + + + +# +# test_plotwidget.py ends here diff --git a/moose-gui/scishell.py b/moose-gui/scishell.py new file mode 100644 index 0000000000000000000000000000000000000000..a9a63ded2b6b938924b65f707e9d2ec8b71cbbc9 --- /dev/null +++ b/moose-gui/scishell.py @@ -0,0 +1,683 @@ +# -*- python -*- +# +# OpenAlea.Visualea: OpenAlea graphical user interface +# +# Copyright 2006 INRIA - CIRAD - INRA +# +# File author(s): Samuel Dufour-Kowalski <samuel.dufour@sophia.inria.fr> +# Christophe Pradal <christophe.prada@cirad.fr> +# +# Distributed under the CeCILL v2 License. +# See accompanying file LICENSE.txt or copy at +# http://www.cecill.info/licences/Licence_CeCILL_V2-en.html +# +# OpenAlea WebSite : http://openalea.gforge.inria.fr +# +# Fri Mar 15 15:10:58 IST 2013: This file was obtained from: +# http://obswww.unige.ch/~revaz/git/old.glups-4.0/glups/scishell.py - +# Subhasis Ray + +__doc__=""" +This module implements a QT4 python interpreter widget. +It is inspired bu PyCute : http://gerard.vermeulen.free.fr +""" + +__license__= "CeCILL V2" +__revision__=" $Id: scishell.py 579 2007-06-13 10:27:57Z dufourko $" + + +import os, sys +from PyQt4 import QtCore, QtGui +from PyQt4.QtCore import Qt + +from PyQt4.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs + +class History: + """ Backup and restore history between sessions + Class added to initial files. Only 3 lines modified to original files. + Look for "Added by vb" comments + Beware: The backup file will grow without limit. You must clean it manually. + """ + def __init__(self, file): + if os.path.isfile(file): # Le fichier existe + self.f = open(file, 'r+') + self.history = self.f.readlines() + else: # Le fichier existe pas + self.f = open(file, 'w') + self.history = [] + + def load(self, trunk = None): + r = [str[:-1] for str in self.history] + if not trunk: + return r + else: + return r[-trunk:] + + def append(self, word): + self.history.append(word) + self.f.write(word + '\n') + self.f.flush() + + + +class MultipleRedirection: + """ Dummy file which redirects stream to multiple file """ + + def __init__(self, files): + """ The stream is redirect to the file list 'files' """ + + self.files = files + + def write(self, str): + """ Emulate write function """ + + for f in self.files: + f.write(str) + +class SciShell(QsciScintilla): + """ + SciShell is a Python shell based in QScintilla. + """ + + def __init__(self, interpreter, message="", log='', parent=None): + """Constructor. + @param interpreter : InteractiveInterpreter in which + the code will be executed + + @param message : welcome message string + + @param 'parent' : specifies the parent widget. + If no parent widget has been specified, it is possible to + exit the interpreter by Ctrl-D. + """ + + QsciScintilla.__init__(self, parent) + self.interpreter = interpreter + + # user interface setup + self.setAutoIndent(True) + self.setAutoCompletionThreshold(4) + self.setAutoCompletionSource(QsciScintilla.AcsDocument) + # Lexer + self.setLexer(QsciLexerPython(self)) + + # Search + self.incrementalSearchString = "" + self.incrementalSearchActive = False + self.inRawMode = False + self.echoInput = True + + # Initialize history + self.historyLists = {} + self.maxHistoryEntries = 1000 + self.H = History("%s/.ghist"%os.environ['HOME']) # Added by vb + self.history = self.H.load(self.maxHistoryEntries) # Added by vb +# self.history = [] + self.histidx = -1 + + # # capture all interactive input/output + sys.stdout = self + sys.stderr = MultipleRedirection((sys.stderr, self)) + sys.stdin = self + + self.reading = 0 + # interpreter prompt. + try: + sys.ps1 + except AttributeError: + sys.ps1 = ">>> " + try: + sys.ps2 + except AttributeError: + sys.ps2 = "... " + + #self.completionText = "" + # Excecution Status + self.more = False + # Multi line execution Buffer + self.execlines = [] + + # interpreter banner + self.write('The shell running Python %s on %s.\n' % + (sys.version, sys.platform)) + self.write('Type "copyright", "credits" or "license"' + ' for more information on Python.\n') + self.write(message+'\n\n') + self.write(sys.ps1) + + + #self.standardCommands().clearKeys() + self.keymap = { + Qt.Key_Backspace : self.__QScintillaDeleteBack, + Qt.Key_Delete : self.__QScintillaDelete, + Qt.Key_Return : self.__QScintillaNewline, + Qt.Key_Enter : self.__QScintillaNewline, + Qt.Key_Tab : self.__QScintillaTab, + Qt.Key_Left : self.__QScintillaCharLeft, + Qt.Key_Right : self.__QScintillaCharRight, + Qt.Key_Up : self.__QScintillaLineUp, + Qt.Key_Down : self.__QScintillaLineDown, + Qt.Key_Home : self.__QScintillaVCHome, + Qt.Key_End : self.__QScintillaLineEnd, + } + + self.connect(self, QtCore.SIGNAL('userListActivated(int, const QString)'), + self.__completionListSelected) + + def get_interpreter(self): + """ Return the interpreter object """ + + return self.interpreter + + + def flush(self): + """ + Simulate stdin, stdout, and stderr. + """ + pass + + + def isatty(self): + """ + Simulate stdin, stdout, and stderr. + """ + return 1 + + + def readline(self): + """ + Simulate stdin, stdout, and stderr. + """ + self.reading = 1 + line, col = self.__getEndPos() + self.setCursorPosition(line, col) + + buf = "" + + if len(buf) == 0: + return '\n' + else: + return buf + + + def write(self, s): + """ + Simulate stdin, stdout, and stderr. + """ + + line, col = self.__getEndPos() + self.setCursorPosition(line, col) + self.insert(s) + + line, col = self.__getEndPos() + self.setCursorPosition(line, col) + + self.prline, self.prcol = self.getCursorPosition() + + self.ensureCursorVisible() + self.ensureLineVisible(line) + + + ########################################### + + def __getEndPos(self): + """ + Private method to return the line and column of the last character. + + @return tuple of two values (int, int) giving the line and column + """ + line = self.lines() - 1 + return (line, self.lineLength(line)) + + + def paste(self): + """ + Reimplemented slot to handle the paste action. + """ + lines = unicode(QApplication.clipboard().text()) + self.__executeLines(lines) + + + def __middleMouseButton(self): + """ + Private method to handle the middle mouse button press. + """ + lines = unicode(QApplication.clipboard().text(QClipboard.Selection)) + self.__executeLines(lines) + + + def __executeLines(self, lines): + """ + Private method to execute a set of lines as multiple commands. + @param lines multiple lines of text to be executed as single + commands (string) + """ + for line in lines.splitlines(True): + if line.endswith("\r\n"): + fullline = True + cmd = line[:-2] + elif line.endswith("\r") or line.endswith("\n"): + fullline = True + cmd = line[:-1] + else: + fullline = False + + self.__insertTextAtEnd(line) + if fullline: + self.__executeCommand(cmd) + + + def __executeCommand(self, cmd): + """ + Private slot to execute a command. + + @param cmd command to be executed by debug client (string) + """ + + if not cmd: cmd = '' + else: + if len(self.history) == self.maxHistoryEntries: + del self.history[0] + self.history.append(QtCore.QString(cmd)) + self.H.append(QtCore.QString(cmd)) # Added by vb + self.histidx = -1 + + # Execute command + self.execlines.append(str(cmd)) + source = '\n'.join(self.execlines) + self.more = self.interpreter.runsource(source) + + if self.more: + self.write(sys.ps2) + else: + self.write(sys.ps1) + self.execlines = [] + + + def __insertText(self, s): + """ + Insert text at the current cursor position. + """ + + line, col = self.getCursorPosition() + self.insertAt(s, line, col) + self.setCursorPosition(line, col + len(str(s))) + + + def __insertTextAtEnd(self, s): + """ + Private method to insert some text at the end of the command line. + @param s text to be inserted (string or QString) + """ + line, col = self.__getEndPos() + self.setCursorPosition(line, col) + self.insert(s) + self.prline, self.prcol = self.__getEndPos() + self.setCursorPosition(self.prline, self.prcol) + + + def __isCursorOnLastLine(self): + """ + Private method to check, if the cursor is on the last line. + """ + cline, ccol = self.getCursorPosition() + return cline == self.lines() - 1 + + + def keyPressEvent(self, ev): + """ + Re-implemented to handle the user input a key at a time. + + @param ev key event (QKeyEvent) + """ + txt = ev.text() + key = ev.key() + + ctrl = ev.modifiers() & Qt.ControlModifier + + if(ctrl): + QsciScintilla.keyPressEvent(self, ev) + + elif(self.keymap.has_key(key)): + self.keymap[key]() + + # See it is text to insert. + elif self.__isCursorOnLastLine() and txt.length() : + + QsciScintilla.keyPressEvent(self, ev) + self.incrementalSearchActive = True + + if(txt == '.'): + self.__showDynCompletion() + + else: + ev.ignore() + + + def __QScintillaTab(self): + """ + Private method to handle the Tab key. + """ + if self.isListActive(): + self.SendScintilla(QsciScintilla.SCI_TAB) + elif self.__isCursorOnLastLine(): + line, index = self.getCursorPosition() + buf = unicode(self.text(line)).replace(sys.ps1, "").replace(sys.ps2, "") + if self.more and not buf[:index-len(sys.ps2)].strip(): + self.SendScintilla(QsciScintilla.SCI_TAB) + + + def __QScintillaDeleteBack(self): + """ + Private method to handle the Backspace key. + """ + if self.__isCursorOnLastLine(): + line, col = self.getCursorPosition() + ac = self.isListActive() + oldLength = self.text(line).length() + + if self.text(line).startsWith(sys.ps1): + if col > len(sys.ps1): + self.SendScintilla(QsciScintilla.SCI_DELETEBACK) + + elif self.text(line).startsWith(sys.ps2): + if col > len(sys.ps2): + self.SendScintilla(QsciScintilla.SCI_DELETEBACK) + + elif col > 0: + self.SendScintilla(QsciScintilla.SCI_DELETEBACK) + + + def __QScintillaDelete(self): + """ + Private method to handle the delete command. + """ + if self.__isCursorOnLastLine(): + if self.hasSelectedText(): + lineFrom, indexFrom, lineTo, indexTo = self.getSelection() + if self.text(lineFrom).startsWith(sys.ps1): + if indexFrom >= len(sys.ps1): + self.SendScintilla(QsciScintilla.SCI_CLEAR) + + elif self.text(lineFrom).startsWith(sys.ps2): + if indexFrom >= len(sys.ps2): + self.SendScintilla(QsciScintilla.SCI_CLEAR) + + elif indexFrom >= 0: + self.SendScintilla(QsciScintilla.SCI_CLEAR) + + self.setSelection(lineTo, indexTo, lineTo, indexTo) + else: + self.SendScintilla(QsciScintilla.SCI_CLEAR) + + + + def __QScintillaNewline(self): + """ + Private method to handle the Return key. + """ + if self.__isCursorOnLastLine(): + if self.isListActive(): + self.SendScintilla(QsciScintilla.SCI_NEWLINE) + elif self.reading: + self.reading = 0 + + else: + self.incrementalSearchString = "" + self.incrementalSearchActive = False + line, col = self.__getEndPos() + self.setCursorPosition(line,col) + buf = unicode(self.text(line)).replace(sys.ps1, "").replace(sys.ps2, "") + self.insert('\n') + self.__executeCommand(buf) + + # add and run selection + else: + s= self.selectedText() + self.__insertTextAtEnd(s) + + + def __QScintillaCharLeft(self, allLinesAllowed = False): + """ + Private method to handle the Cursor Left command. + """ + + if self.__isCursorOnLastLine() or allLinesAllowed: + line, col = self.getCursorPosition() + if self.text(line).startsWith(sys.ps1): + if col > len(sys.ps1): + self.SendScintilla(QsciScintilla.SCI_CHARLEFT) + + elif self.text(line).startsWith(sys.ps2): + if col > len(sys.ps2): + + self.SendScintilla(QsciScintilla.SCI_CHARLEFT) + elif col > 0: + + self.SendScintilla(QsciScintilla.SCI_CHARLEFT) + + + def __QScintillaCharRight(self): + """ + Private method to handle the Cursor Right command. + """ + if self.__isCursorOnLastLine(): + self.SendScintilla(QsciScintilla.SCI_CHARRIGHT) + + + def __QScintillaVCHome(self): + """ + Private method to handle the Home key. + """ + if self.isListActive(): + self.SendScintilla(QsciScintilla.SCI_VCHOME) + elif self.__isCursorOnLastLine(): + line, col = self.getCursorPosition() + if self.text(line).startsWith(sys.ps1): + col = len(sys.ps1) + elif self.text(line).startsWith(sys.ps2): + col = len(sys.ps2) + else: + col = 0 + self.setCursorPosition(line, col) + + + def __QScintillaLineEnd(self): + """ + Private method to handle the End key. + """ + if self.isListActive(): + self.SendScintilla(QsciScintilla.SCI_LINEEND) + elif self.__isCursorOnLastLine(): + self.SendScintilla(QsciScintilla.SCI_LINEEND) + + + def __QScintillaLineUp(self): + """ + Private method to handle the Up key. + """ + if self.isListActive(): + self.SendScintilla(QsciScintilla.SCI_LINEUP) + else: + line, col = self.__getEndPos() + buf = unicode(self.text(line)).replace(sys.ps1, "").replace(sys.ps2, "") + if buf and self.incrementalSearchActive: + if self.incrementalSearchString: + idx = self.__rsearchHistory(self.incrementalSearchString, + self.histidx) + if idx >= 0: + self.histidx = idx + self.__useHistory() + else: + idx = self.__rsearchHistory(buf) + if idx >= 0: + self.histidx = idx + self.incrementalSearchString = buf + self.__useHistory() + else: + if self.histidx < 0: + self.histidx = len(self.history) + if self.histidx > 0: + self.histidx = self.histidx - 1 + self.__useHistory() + + + def __QScintillaLineDown(self): + """ + Private method to handle the Down key. + """ + if self.isListActive(): + self.SendScintilla(QsciScintilla.SCI_LINEDOWN) + else: + line, col = self.__getEndPos() + buf = unicode(self.text(line)).replace(sys.ps1, "").replace(sys.ps2, "") + if buf and self.incrementalSearchActive: + if self.incrementalSearchString: + idx = self.__searchHistory(self.incrementalSearchString, self.histidx) + if idx >= 0: + self.histidx = idx + self.__useHistory() + else: + idx = self.__searchHistory(buf) + if idx >= 0: + self.histidx = idx + self.incrementalSearchString = buf + self.__useHistory() + else: + if self.histidx >= 0 and self.histidx < len(self.history): + self.histidx += 1 + self.__useHistory() + + + def __useHistory(self): + """ + Private method to display a command from the history. + """ + if self.histidx < len(self.history): + cmd = self.history[self.histidx] + else: + cmd = QtCore.QString() + self.incrementalSearchString = "" + self.incrementalSearchActive = False + + self.setCursorPosition(self.prline, self.prcol + len(self.more and sys.ps1 or sys.ps2)) + self.setSelection(self.prline,self.prcol,\ + self.prline,self.lineLength(self.prline)) + self.removeSelectedText() + self.__insertText(cmd) + + + def __searchHistory(self, txt, startIdx = -1): + """ + Private method used to search the history. + + @param txt text to match at the beginning (string or QString) + @param startIdx index to start search from (integer) + @return index of + """ + if startIdx == -1: + idx = 0 + else: + idx = startIdx + 1 + while idx < len(self.history) and \ + not self.history[idx].startsWith(txt): + idx += 1 + return idx + + + def __rsearchHistory(self, txt, startIdx = -1): + """ + Private method used to reverse search the history. + + @param txt text to match at the beginning (string or QString) + @param startIdx index to start search from (integer) + @return index of + """ + if startIdx == -1: + idx = len(self.history) - 1 + else: + idx = startIdx - 1 + while idx >= 0 and \ + not self.history[idx].startsWith(txt): + idx -= 1 + return idx + + + def focusNextPrevChild(self, next): + """ + Reimplemented to stop Tab moving to the next window. + + While the user is entering a multi-line command, the movement to + the next window by the Tab key being pressed is suppressed. + + @param next next window + @return flag indicating the movement + """ + if next and self.more: + return False + + return QsciScintilla.focusNextPrevChild(self,next) + + + def __showDynCompletion(self): + """ + Display a completion list based on the last token + """ + + # get line + line, col = self.__getEndPos() + self.setCursorPosition(line,col) + buf = unicode(self.text(line)).replace(sys.ps1, "").replace(sys.ps2, "") + + text = buf.split()[-1][:-1] + try: + locals = self.interpreter.locals + obj = eval(text, globals(), self.interpreter.locals) + l = dir(obj) + l = filter(lambda x : not x.startswith('__'), l) + self.__showCompletions(l, text) + except : pass + + + def __showCompletions(self, completions, text): + """ + Private method to display the possible completions. + """ + if len(completions) == 0: + return + + if len(completions) > 1: + completions.sort() + comps = QtCore.QStringList() + for comp in completions: + comps.append(comp) + self.showUserList(1, comps) + #self.completionText = text + else: + txt = completions[0] + if text != "": + txt = txt.replace(text, "") + self.__insertText(txt) + #self.completionText = "" + + + def __completionListSelected(self, id, txt): + """ + Private slot to handle the selection from the completion list. + + @param id the ID of the user list (should be 1) (integer) + @param txt the selected text (QString) + """ + + # Remove already written characters + line, col = self.__getEndPos() + self.setCursorPosition(line,col) + buf = unicode(self.text(line)) + ind = len(buf) - buf.rfind(".") - 1 + + if id == 1: + txt = unicode(txt[ind:]) + #if self.completionText != "": + # txt = txt.replace(self.completionText, "") + self.__insertText(txt) + #self.completionText = "" diff --git a/moose-gui/shell.py b/moose-gui/shell.py new file mode 100644 index 0000000000000000000000000000000000000000..2eeafb5f9e743b03d08096c6ba887c48a03833c4 --- /dev/null +++ b/moose-gui/shell.py @@ -0,0 +1,523 @@ +# -*- python -*- +# +# OpenAlea.Visualea: OpenAlea graphical user interface +# +# Copyright 2006 INRIA - CIRAD - INRA +# +# File author(s): Samuel Dufour-Kowalski <samuel.dufour@sophia.inria.fr> +# Christophe Pradal <christophe.prada@cirad.fr> +# +# Distributed under the CeCILL v2 License. +# See accompanying file LICENSE.txt or copy at +# http://www.cecill.info/licences/Licence_CeCILL_V2-en.html +# +# OpenAlea WebSite : http://openalea.gforge.inria.fr +# +# Fri Mar 15 15:10:58 IST 2013: This file was obtained from: +# http://obswww.unige.ch/~revaz/git/old.glups-4.0/glups/shell.py - +# Subhasis Ray + +__doc__=""" +This module implements a QT4 python interpreter widget. +It is inspired bu PyCute : http://gerard.vermeulen.free.fr +""" + +__license__= "CeCILL V2" +__revision__=" $Id: shell.py 579 2007-06-13 10:27:57Z dufourko $" + + +import os, sys +from PyQt4 import QtCore, QtGui +from PyQt4.QtGui import QTextEdit, QTextCursor +from PyQt4.QtCore import Qt + + +class History: + """ Backup and restore history between sessions + Class added to initial files. Only 3 lines modified to original files. + Look for "Added by vb" comments + Beware: The backup file will grow without limit. You must clean it manually. + """ + def __init__(self, file): + if os.path.isfile(file): # Le fichier existe + self.f = open(file, 'r+') + self.history = self.f.readlines() + else: # Le fichier existe pas + self.f = open(file, 'w') + self.history = [] + + def load(self, trunk = None): + r = [str[:-1] for str in self.history] + if not trunk: + return r + else: + return r[-trunk:] + + def append(self, word): + self.history.append(word) + self.f.write(word + '\n') + self.f.flush() + + + +def get_shell_class(): + """ Return the shell class to instantiate """ + + # Test QScintilla + try: + from scishell import SciShell + return SciShell + + except ImportError: + return PyCutExt + + + +class MultipleRedirection: + """ Dummy file which redirects stream to multiple file """ + + def __init__(self, files): + """ The stream is redirect to the file list 'files' """ + + self.files = files + + def write(self, str): + """ Emulate write function """ + + for f in self.files: + f.write(str) + + +class PyCutExt(QTextEdit): + + """ + PyCute is a Python shell for PyQt. + + Creating, displaying and controlling PyQt widgets from the Python command + line interpreter is very hard, if not, impossible. PyCute solves this + problem by interfacing the Python interpreter to a PyQt widget. + + """ + + def __init__(self, interpreter, message="", log='', parent=None): + """Constructor. + @param interpreter : InteractiveInterpreter in which + the code will be executed + + @param message : welcome message string + + @param 'log' : specifies the file in which the + interpreter session is to be logged. + + @param 'parent' : specifies the parent widget. + If no parent widget has been specified, it is possible to + exit the interpreter by Ctrl-D. + """ + + QTextEdit.__init__(self, parent) + self.interpreter = interpreter + self.colorizer = SyntaxColor() + + # session log + self.log = log or '' + + # to exit the main interpreter by a Ctrl-D if PyCute has no parent + if parent is None: + self.eofKey = Qt.Key_D + else: + self.eofKey = None + + # capture all interactive input/output + sys.stdout = self + sys.stderr = MultipleRedirection((sys.stderr, self)) + sys.stdin = self + + + # last line + last incomplete lines + self.line = QtCore.QString() + self.lines = [] + # the cursor position in the last line + self.point = 0 + # flag: the interpreter needs more input to run the last lines. + self.more = 0 + # flag: readline() is being used for e.g. raw_input() and input() + self.reading = 0 + # history + self.maxHistoryEntries = 1000 # Added by yr + self.H = History("%s/.ghist"%os.environ['HOME']) # Added by yr + self.history = self.H.load(self.maxHistoryEntries) # Added by yr + #self.history = [] + self.pointer = 0 + self.cursor_pos = 0 + + # user interface setup + #self.setTextFormat(Qt.PlainText) + self.setLineWrapMode(QTextEdit.NoWrap) + #self.setCaption('Python Shell') + +# # font +# if os.name == 'posix': +# font = QtGui.QFont("Fixed", 8) +# elif os.name == 'nt' or os.name == 'dos': +# font = QtGui.QFont("Courier New", 8) +# else: +# raise SystemExit, "FIXME for 'os2', 'mac', 'ce' or 'riscos'" +# font.setFixedPitch(1) +# self.setFont(font) + +# # geometry +# height = 40*QtGui.QFontMetrics(font).lineSpacing() +# request = QtCore.QSize(600, height) +# if parent is not None: +# request = request.boundedTo(parent.size()) +# self.resize(request) + + # interpreter prompt. + try: + sys.ps1 + except AttributeError: + sys.ps1 = ">>> " + try: + sys.ps2 + except AttributeError: + sys.ps2 = "... " + + # interpreter banner + self.write('The shell running Python %s on %s.\n' % + (sys.version, sys.platform)) + self.write('Type "copyright", "credits" or "license"' + ' for more information on Python.\n') + self.write(message+'\n\n') + self.write('This is the standard Shell.\n'+ + 'Autocompletion is not available unless QScintilla is installed:\n'+ + 'See http://www.riverbankcomputing.co.uk/qscintilla.\n\n') + self.write(sys.ps1) + + + def get_interpreter(self): + """ Return the interpreter object """ + + return self.interpreter + + + def moveCursor(self, operation, mode=QTextCursor.MoveAnchor): + """ + Convenience function to move the cursor + This function will be present in PyQT4.2 + """ + cursor = self.textCursor() + cursor.movePosition(operation, mode) + self.setTextCursor(cursor) + + + def flush(self): + """ + Simulate stdin, stdout, and stderr. + """ + pass + + + def isatty(self): + """ + Simulate stdin, stdout, and stderr. + """ + return 1 + + + def readline(self): + """ + Simulate stdin, stdout, and stderr. + """ + self.reading = 1 + self.__clearLine() + self.moveCursor(QTextCursor.End) + while self.reading: + qApp.processOneEvent() + if self.line.length() == 0: + return '\n' + else: + return str(self.line) + + + def write(self, text): + """ + Simulate stdin, stdout, and stderr. + """ + # The output of self.append(text) contains to many newline characters, + # so work around QTextEdit's policy for handling newline characters. + + cursor = self.textCursor() + + cursor.movePosition(QTextCursor.End) + + pos1 = cursor.position() + cursor.insertText(text) + + self.cursor_pos = cursor.position() + self.setTextCursor(cursor) + self.ensureCursorVisible () + + # Set the format + cursor.setPosition(pos1, QTextCursor.KeepAnchor) + format = cursor.charFormat() + format.setForeground( QtGui.QBrush(QtGui.QColor(0,0,0))) + cursor.setCharFormat(format) + + + def writelines(self, text): + """ + Simulate stdin, stdout, and stderr. + """ + map(self.write, text) + + + def fakeUser(self, lines): + """ + Simulate a user: lines is a sequence of strings, (Python statements). + """ + for line in lines: + self.line = QtCore.QString(line.rstrip()) + self.write(self.line) + self.write('\n') + self.__run() + + + def __run(self): + """ + Append the last line to the history list, let the interpreter execute + the last line(s), and clean up accounting for the interpreter results: + (1) the interpreter succeeds + (2) the interpreter fails, finds no errors and wants more line(s) + (3) the interpreter fails, finds errors and writes them to sys.stderr + """ + self.pointer = 0 + self.history.append(QtCore.QString(self.line)) + self.H.append(QtCore.QString(self.line)) # Added by yr + try: + self.lines.append(str(self.line)) + except Exception,e: + print e + + source = '\n'.join(self.lines) + self.more = self.interpreter.runsource(source) + + if self.more: + self.write(sys.ps2) + else: + self.write(sys.ps1) + self.lines = [] + self.__clearLine() + + + def __clearLine(self): + """ + Clear input line buffer + """ + self.line.truncate(0) + self.point = 0 + + + def __insertText(self, text): + """ + Insert text at the current cursor position. + """ + self.line.insert(self.point, text) + #self.point += text.length() + self.point += len(text) #Added by yr + + cursor = self.textCursor() + cursor.insertText(text) + self.color_line() + + + def keyPressEvent(self, e): + """ + Handle user input a key at a time. + """ + text = e.text() + key = e.key() + + if key == Qt.Key_Backspace: + if self.point: + cursor = self.textCursor() + cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor) + cursor.removeSelectedText() + self.color_line() + + self.point -= 1 + self.line.remove(self.point, 1) + + elif key == Qt.Key_Delete: + cursor = self.textCursor() + cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) + cursor.removeSelectedText() + self.color_line() + + self.line.remove(self.point, 1) + + elif key == Qt.Key_Return or key == Qt.Key_Enter: + self.write('\n') + if self.reading: + self.reading = 0 + else: + self.__run() + + elif key == Qt.Key_Tab: + self.__insertText(text) + elif key == Qt.Key_Left: + if self.point : + self.moveCursor(QTextCursor.Left) + self.point -= 1 + elif key == Qt.Key_Right: + if self.point < self.line.length(): + self.moveCursor(QTextCursor.Right) + self.point += 1 + + elif key == Qt.Key_Home: + cursor = self.textCursor () + cursor.setPosition(self.cursor_pos) + self.setTextCursor (cursor) + self.point = 0 + + elif key == Qt.Key_End: + self.moveCursor(QTextCursor.EndOfLine) + self.point = self.line.length() + + elif key == Qt.Key_Up: + + if len(self.history): + if self.pointer == 0: + self.pointer = len(self.history) + self.pointer -= 1 + self.__recall() + + elif key == Qt.Key_Down: + if len(self.history): + self.pointer += 1 + if self.pointer == len(self.history): + self.pointer = 0 + self.__recall() + + elif text.length(): + self.__insertText(text) + return + + else: + e.ignore() + + + def __recall(self): + """ + Display the current item from the command history. + """ + cursor = self.textCursor () + cursor.select( QtGui.QTextCursor.LineUnderCursor ) + cursor.removeSelectedText() + + if self.more: + self.write(sys.ps2) + else: + self.write(sys.ps1) + + + self.__clearLine() + self.__insertText(self.history[self.pointer]) + + +# def focusNextPrevChild(self, next): +# """ +# Suppress tabbing to the next window in multi-line commands. +# """ +# if next and self.more: +# return 0 +# return QTextEdit.focusNextPrevChild(self, next) + + def mousePressEvent(self, e): + """ + Keep the cursor after the last prompt. + """ + if e.button() == Qt.LeftButton: + self.moveCursor(QTextCursor.End) + + + def contentsContextMenuEvent(self,ev): + """ + Suppress the right button context menu. + """ + pass + + + def color_line(self): + """ Color the current line """ + + cursor = self.textCursor() + cursor.movePosition(QTextCursor.StartOfLine) + + newpos = cursor.position() + pos = -1 + + while(newpos != pos): + cursor.movePosition(QTextCursor.NextWord) + + pos = newpos + newpos = cursor.position() + + cursor.select(QTextCursor.WordUnderCursor) + word = str(cursor.selectedText ().toAscii()) + + if(not word) : continue + + (R,G,B) = self.colorizer.get_color(word) + + format = cursor.charFormat() + format.setForeground( QtGui.QBrush(QtGui.QColor(R,G,B))) + cursor.setCharFormat(format) + + + + + +class SyntaxColor: + """ Allow to color python keywords """ + + keywords = set(["and", "del", "from", "not", "while", + "as", "elif", "global", "or", "with", + "assert", "else", "if", "pass", "yield", + "break", "except", "import", "print", + "class", "exec", "in", "raise", + "continue", "finally", "is", "return", + "def", "for", "lambda", "try"]) + + def __init__(self): + pass + + + def get_color(self, word): + """ Return a color tuple (R,G,B) depending of the string word """ + + stripped = word.strip() + + if(stripped in self.keywords): + return (255, 132,0) # orange + + elif(self.is_python_string(stripped)): + return (61, 120, 9) # dark green + + else: + return (0,0,0) + + def is_python_string(self, str): + """ Return True if str is enclosed by a string mark """ + +# return ( +# (str.startswith("'''") and str.endswith("'''")) or +# (str.startswith('"""') and str.endswith('"""')) or +# (str.startswith("'") and str.endswith("'")) or +# (str.startswith('"') and str.endswith('"')) +# ) + return False + + + + + diff --git a/moose-gui/sidebar.py b/moose-gui/sidebar.py new file mode 100644 index 0000000000000000000000000000000000000000..c989528a28b38f1da385e7fe2d837133b5a7530b --- /dev/null +++ b/moose-gui/sidebar.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from __future__ import print_function + +"""Sidebar for plugins. The sidebar comprises of actions. +Currently mode, connect and settings are defined. +""" + +__author__ = "Aviral Goel" +__credits__ = ["Upi Lab"] +__license__ = "GPL3" +__version__ = "1.0.0" +__maintainer__ = "Aviral Goel" +__email__ = "goel.aviral@gmail.com" +__status__ = "Development" + + +import sys +import os +import SettingsDialog +from PyQt4 import QtGui, Qt +from PyQt4.QtGui import QDialog +from PyQt4.QtGui import QHBoxLayout +from PyQt4.QtGui import QPixmap +from PyQt4.QtGui import QIcon +from PyQt4.QtGui import QPushButton +from PyQt4.QtGui import QAction + + + +ICON_DIRECTORY = "icons" +HAND_ICON_FILENAME = "hand.png" +CONNECTOR_ICON_FILENAME = "straight_connector_with_filled_circles.png" +WRENCH_ICON_FILENAME = "wrench.png" +DELETE_GRAPH_ICON_FILENAME = "add_graph.png" +ADD_GRAPH_ICON_FILENAME = "delete_graph.png" +LIST_ICON_FILENAME = "list.png" + + +def create_action( parent + , callback + , text + , checkable + , checked + , icon_path + ): + pixmap = QPixmap(icon_path) + icon = QIcon(pixmap) + action = QAction(icon, text, parent) + # action.setIcon(icon) + # action.setIconText(text) + action.triggered.connect(callback) + action.setCheckable(checkable) + action.setChecked(checked) + return action + + +def mode_action( parent + , callback = (lambda event: print("Mode Clicked!")) + , text = "Mode" + , checkable = True + , checked = True + , icon_path = os.path.join( ICON_DIRECTORY + , HAND_ICON_FILENAME + ) + ): + return create_action( parent + , callback + , text + , checkable + , checked + , icon_path + ) + +def add_graph_action( parent + , callback = (lambda event: print("Add Graph Clicked!")) + , text = "Add Graph" + , checkable = False + , checked = False + , icon_path = os.path.join( ICON_DIRECTORY + , ADD_GRAPH_ICON_FILENAME + ) + ): + return create_action( parent + , callback + , text + , checkable + , checked + , icon_path + ) + +def delete_graph_action( parent + , callback = (lambda event: print("Delete Graph Clicked!")) + , text = "Delete Graph" + , checkable = False + , checked = False + , icon_path = os.path.join( ICON_DIRECTORY + , DELETE_GRAPH_ICON_FILENAME + ) + ): + return create_action( parent + , callback + , text + , checkable + , checked + , icon_path + ) + +def list_action( parent + , callback = (lambda event: print("List Clicked!")) + , text = "Show List" + , checkable = False + , checked = False + , icon_path = os.path.join( ICON_DIRECTORY + , LIST_ICON_FILENAME + ) + ): + return create_action( parent + , callback + , text + , checkable + , checked + , icon_path + ) + +def connector_action( parent + , callback = (lambda event: print("Connector Clicked!")) + , text = "Mode" + , checkable = True + , checked = False + , icon_path = os.path.join( ICON_DIRECTORY + , CONNECTOR_ICON_FILENAME + ) + ): + return create_action( parent + , callback + , text + , checkable + , checked + , icon_path + ) + +def settings_action( parent + , callback = (lambda event: print("Settings Clicked")) + , text = "Mode" + , checkable = False + , checked = False + , icon_path = os.path.join( ICON_DIRECTORY + , WRENCH_ICON_FILENAME + ) + ): + return create_action( parent + , callback + , text + , checkable + , checked + , icon_path + ) + + + # actions + # , left_spacer = False + # , right_spacer = False + +def sidebar(): + return QtGui.QToolBar() + # bar.setOrientation(Qt.Qt.Vertical) + # return bar + # if left_spacer: + # left_spacer = QWidget() + # left_spacer.setSizePolicy( QtGui.QSizePolicy.Expanding + # , QtGui.QSizePolicy.Expanding + # ) + # toolbar.addWidget(left_spacer) + + # for action in actions: + # toolbar.addAction(action(toolbar)) + + # if right_spacer: + # right_spacer = QWidget() + # right_spacer.setSizePolicy( QtGui.QSizePolicy.Expanding + # , QtGui.QSizePolicy.Expanding + # ) + # toolbar.addWidget(right_spacer) + + # return toolbar + + + + +# def connect_action(): + +# def settings_action(): + + + +def main(): + app = QtGui.QApplication(sys.argv) + window = QtGui.QMainWindow() + widget = SettingsDialog.SettingsWidget({ + 'LeakyIaF':['Vm'], + 'Compartment':['Vm','Im'], + 'HHChannel':['Ik','Gk'], + 'ZombiePool':['n','conc'], + 'ZombieBufPool':['n','conc'], + 'HHChannel2D':['Ik','Gk'], + 'CaConc':['Ca'] + }) + d = QDialog() + l = QHBoxLayout() + d.setLayout(l) + l.addWidget(widget) + bar = sidebar() + bar.addAction(mode_action(bar)) + bar.addAction(connector_action(bar)) + bar.addAction(settings_action(bar, d.show)) + window.addToolBar(bar) + window.show() + sys.exit(app.exec_()) + + +if __name__ == "__main__": + main() + +# # spacer widget for left +# # spacer widget for right +# # you can't add the same widget to both left and right. you need two different widgets. +# right_spacer = QtGui.QWidget() +# right_spacer.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + +# # here goes the left one +# # toolbar.addWidget(left_spacer) +# # some dummy actions + + + +# ################################################################################ +# # Hand Tool +# ################################################################################ + + + + + diff --git a/moose-gui/utils.py b/moose-gui/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..6873a9c245b3262c2b7d031d1ed233abb8d6dc53 --- /dev/null +++ b/moose-gui/utils.py @@ -0,0 +1,140 @@ +# utils.py --- +# +# Filename: utils.py +# Description: +# Author: +# Maintainer: +# Created: Sat Sep 22 15:19:09 2012 (+0530) +# Version: +# Last-Updated: Wed Sep 26 16:35:38 2012 (+0530) +# By: subha +# Update #: 50 +# URL: +# Keywords: +# Compatibility: +# +# + +# Commentary: +# +# +# +# + +# Change log: +# +# +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth +# Floor, Boston, MA 02110-1301, USA. +# +# + +# Code: + +import shutil +import os +from PyQt4 import QtGui, QtCore + +def resizeWidthToContents(lineEdit): + """Resize a QLineEdit object to fit its content.""" + text = lineEdit.text() + fm = lineEdit.fontMetrics() + w = fm.boundingRect(text).width() + lineEdit.resize(w, lineEdit.height()) + +def copyTree(src, dst, progressDialog=None): + """Copy the contents of source directory recursively into + destination directory recursively. Display the progress in + progressDialog. This does not overwrite any existing files or + directories. + + Parameters + ---------- + src: str + path of the source directory + + dst: str + path of the destination directory + + progressDialog: QProgressDialog + Qt object to display the progress of the copying. + + Return + ------ + list containing all the errors encountered while copying. + + """ + src = src.strip() + dst = dst.strip() + errors = [] + if not os.access(src, os.R_OK + os.X_OK): + print 'Failed to access directory', src + return + print 'Copying %s to : %s' % (src, dst) + if not os.access(src, os.R_OK + os.X_OK): + try: + os.makedirs(dst) + except OSError, e: + # print e + errors.append(e) + totalsize = 0 + for dirpath, dirnames, filenames in os.walk(src): + for fname in filenames: + srcname = os.path.join(dirpath, fname) + try: + totalsize += os.path.getsize(srcname) + except OSError, e: + # print e + errors.append(e) + if progressDialog: + progressDialog.setMaximum(totalsize) + size = 0 + for dirpath, dirnames, filenames in os.walk(src): + dstdir = os.path.join(dst, dirpath[len(src)+1:]) + # print 'Destination dir', dstdir, dirpath[len(src)+1:] + try: + os.makedirs(dstdir) + except OSError, e: + # print e + errors.append(e) + # print 'Copying files from %s to %s' % (dirpath, dstdir) + for fname in filenames: + srcname = os.path.join(dirpath, fname) + dstname = os.path.join(dstdir, fname) + # print 'Copying:', srcname, 'to', dstname + try: + shutil.copy2(srcname, dstname) + except IOError, e: + # print e + errors.append(e) + size += os.path.getsize(srcname) + if progressDialog: + progressDialog.setValue(size) + if progressDialog.wasCanceled(): + return errors + else: + print 'Copied %d bytes of %d.' % (size, totalsize) + if progressDialog: + progressDialog.close() + else: + print 'Finished.' + return errors + + + +# +# utils.py ends here