From 31bf7c6aa42fb2fd40b6af0d6b07c6d73859eda7 Mon Sep 17 00:00:00 2001 From: Guillermo Date: Fri, 9 Oct 2026 14:40:35 +0200 Subject: [PATCH 1/6] changed CellModeller to cellmodeller and fixed all related imports --- Scripts/batch.py | 2 +- Scripts/batch_file.py | 4 ++-- Scripts/batch_iter.py | 2 +- Scripts/cell_modeller_gui.py | 8 ++++---- Scripts/contact_graph.py | 4 ++-- Scripts/length_histogram.py | 2 +- Scripts/multi_batch.py | 2 +- Scripts/print_timing.py | 2 +- Scripts/spatial_analyze.py | 2 +- .../Regulation/ModuleRegulator.py | 0 {CellModeller => cellmodeller}/Regulation/SBMLImport.py | 0 {CellModeller => cellmodeller}/Regulation/__init__.py | 0 {CellModeller => cellmodeller}/__init__.py | 0 {CellModeller => cellmodeller}/cell_state.py | 0 {CellModeller => cellmodeller}/gui/__init__.py | 0 {CellModeller => cellmodeller}/gui/py_gl_cm_viewer.py | 6 +++--- {CellModeller => cellmodeller}/gui/py_gl_gui.ui | 2 +- {CellModeller => cellmodeller}/gui/py_gl_widget.py | 0 {CellModeller => cellmodeller}/gui/renderers.py | 0 {CellModeller => cellmodeller}/simulator.py | 2 +- setup.py | 8 ++++---- 21 files changed, 23 insertions(+), 23 deletions(-) rename {CellModeller => cellmodeller}/Regulation/ModuleRegulator.py (100%) rename {CellModeller => cellmodeller}/Regulation/SBMLImport.py (100%) rename {CellModeller => cellmodeller}/Regulation/__init__.py (100%) rename {CellModeller => cellmodeller}/__init__.py (100%) rename {CellModeller => cellmodeller}/cell_state.py (100%) rename {CellModeller => cellmodeller}/gui/__init__.py (100%) rename {CellModeller => cellmodeller}/gui/py_gl_cm_viewer.py (98%) rename {CellModeller => cellmodeller}/gui/py_gl_gui.ui (99%) rename {CellModeller => cellmodeller}/gui/py_gl_widget.py (100%) rename {CellModeller => cellmodeller}/gui/renderers.py (100%) rename {CellModeller => cellmodeller}/simulator.py (99%) diff --git a/Scripts/batch.py b/Scripts/batch.py index 6d618d2f..b80992e6 100644 --- a/Scripts/batch.py +++ b/Scripts/batch.py @@ -4,7 +4,7 @@ import string import shutil -from CellModeller.simulator import Simulator +from cellmodeller.simulator import Simulator max_cells = 50000 cell_buffer = 256 diff --git a/Scripts/batch_file.py b/Scripts/batch_file.py index 5b11c171..e66c7c58 100644 --- a/Scripts/batch_file.py +++ b/Scripts/batch_file.py @@ -6,13 +6,13 @@ import time from exceptions import OSError -from CellModeller.simulator import Simulator +from cellmodeller.simulator import Simulator sys.path.append('./') print((os.getcwd())) -import CellModeller.AdaptiveSimulator +import cellmodeller.AdaptiveSimulator sys.path.append('Models') diff --git a/Scripts/batch_iter.py b/Scripts/batch_iter.py index 05611dab..5d87dc4e 100644 --- a/Scripts/batch_iter.py +++ b/Scripts/batch_iter.py @@ -4,7 +4,7 @@ import string import shutil -from CellModeller.simulator import Simulator +from cellmodeller.simulator import Simulator sys.path.append('../../Models') diff --git a/Scripts/cell_modeller_gui.py b/Scripts/cell_modeller_gui.py index b91d5fcb..3763764f 100644 --- a/Scripts/cell_modeller_gui.py +++ b/Scripts/cell_modeller_gui.py @@ -10,9 +10,9 @@ from PyQt5 import uic from PyQt5.QtCore import * -import CellModeller.gui.renderers -from CellModeller import simulator -from CellModeller.gui.py_gl_cm_viewer import PyGLCMViewer, RenderInfo +import cellmodeller.gui.renderers +from cellmodeller import simulator +from cellmodeller.gui.py_gl_cm_viewer import PyGLCMViewer, RenderInfo from pkg_resources import resource_stream import os @@ -22,7 +22,7 @@ qapp = QApplication([]) # The UI -uifile = resource_stream('CellModeller.gui', 'py_gl_gui.ui') +uifile = resource_stream('cellmodeller.gui', 'py_gl_gui.ui') ui = uic.loadUi(uifile) ui.show() ui.raise_() diff --git a/Scripts/contact_graph.py b/Scripts/contact_graph.py index b57f7e3a..18360004 100644 --- a/Scripts/contact_graph.py +++ b/Scripts/contact_graph.py @@ -3,11 +3,11 @@ import math import numpy as np import pickle -import CellModeller +import cellmodeller import subprocess import string import shutil -from CellModeller.simulator import Simulator +from cellmodeller.simulator import Simulator import networkx from reportlab.pdfgen.canvas import Canvas from reportlab.lib import units diff --git a/Scripts/length_histogram.py b/Scripts/length_histogram.py index 7253bcfd..c0c591bc 100644 --- a/Scripts/length_histogram.py +++ b/Scripts/length_histogram.py @@ -4,7 +4,7 @@ import numpy as np sys.path.append('.') import pickle -import CellModeller +import cellmodeller #import matplotlib.pyplot as plt file = sys.argv[1] #select pickle file in command line diff --git a/Scripts/multi_batch.py b/Scripts/multi_batch.py index c0cba510..9ec3cfdb 100644 --- a/Scripts/multi_batch.py +++ b/Scripts/multi_batch.py @@ -4,7 +4,7 @@ import string import shutil -from CellModeller.simulator import Simulator +from cellmodeller.simulator import Simulator max_cells = 100000 cell_buffer = 256 diff --git a/Scripts/print_timing.py b/Scripts/print_timing.py index f6f3996c..055e9957 100644 --- a/Scripts/print_timing.py +++ b/Scripts/print_timing.py @@ -2,7 +2,7 @@ import os sys.path.append('.') import pickle -import CellModeller +import cellmodeller dir = os.path.join('data', sys.argv[1]) diff --git a/Scripts/spatial_analyze.py b/Scripts/spatial_analyze.py index 15b86ecb..affcc4b7 100644 --- a/Scripts/spatial_analyze.py +++ b/Scripts/spatial_analyze.py @@ -4,7 +4,7 @@ import numpy as np sys.path.append('.') import pickle -import CellModeller +import cellmodeller import matplotlib.pyplot as plt pname= sys.argv[1] diff --git a/CellModeller/Regulation/ModuleRegulator.py b/cellmodeller/Regulation/ModuleRegulator.py similarity index 100% rename from CellModeller/Regulation/ModuleRegulator.py rename to cellmodeller/Regulation/ModuleRegulator.py diff --git a/CellModeller/Regulation/SBMLImport.py b/cellmodeller/Regulation/SBMLImport.py similarity index 100% rename from CellModeller/Regulation/SBMLImport.py rename to cellmodeller/Regulation/SBMLImport.py diff --git a/CellModeller/Regulation/__init__.py b/cellmodeller/Regulation/__init__.py similarity index 100% rename from CellModeller/Regulation/__init__.py rename to cellmodeller/Regulation/__init__.py diff --git a/CellModeller/__init__.py b/cellmodeller/__init__.py similarity index 100% rename from CellModeller/__init__.py rename to cellmodeller/__init__.py diff --git a/CellModeller/cell_state.py b/cellmodeller/cell_state.py similarity index 100% rename from CellModeller/cell_state.py rename to cellmodeller/cell_state.py diff --git a/CellModeller/gui/__init__.py b/cellmodeller/gui/__init__.py similarity index 100% rename from CellModeller/gui/__init__.py rename to cellmodeller/gui/__init__.py diff --git a/CellModeller/gui/py_gl_cm_viewer.py b/cellmodeller/gui/py_gl_cm_viewer.py similarity index 98% rename from CellModeller/gui/py_gl_cm_viewer.py rename to cellmodeller/gui/py_gl_cm_viewer.py index e6e34eea..6cf63bfa 100644 --- a/CellModeller/gui/py_gl_cm_viewer.py +++ b/cellmodeller/gui/py_gl_cm_viewer.py @@ -7,9 +7,9 @@ from OpenGL.GL import * from OpenGL.GLU import * -from CellModeller.Regulation import ModuleRegulator -from CellModeller.simulator import Simulator -from CellModeller.cell_state import CellState +from cellmodeller.Regulation import ModuleRegulator +from cellmodeller.simulator import Simulator +from cellmodeller.cell_state import CellState import os import sys import pickle diff --git a/CellModeller/gui/py_gl_gui.ui b/cellmodeller/gui/py_gl_gui.ui similarity index 99% rename from CellModeller/gui/py_gl_gui.ui rename to cellmodeller/gui/py_gl_gui.ui index 24b43045..f9d0d5f4 100644 --- a/CellModeller/gui/py_gl_gui.ui +++ b/cellmodeller/gui/py_gl_gui.ui @@ -158,7 +158,7 @@ PyGLCMViewer QWidget -
CellModeller.gui.py_gl_cm_viewer
+
cellmodeller.gui.py_gl_cm_viewer
setSavePicklesToggle(bool) load() diff --git a/CellModeller/gui/py_gl_widget.py b/cellmodeller/gui/py_gl_widget.py similarity index 100% rename from CellModeller/gui/py_gl_widget.py rename to cellmodeller/gui/py_gl_widget.py diff --git a/CellModeller/gui/renderers.py b/cellmodeller/gui/renderers.py similarity index 100% rename from CellModeller/gui/renderers.py rename to cellmodeller/gui/renderers.py diff --git a/CellModeller/simulator.py b/cellmodeller/simulator.py similarity index 99% rename from CellModeller/simulator.py rename to cellmodeller/simulator.py index 57ca5ac4..4f777b18 100644 --- a/CellModeller/simulator.py +++ b/cellmodeller/simulator.py @@ -66,7 +66,7 @@ def __init__(self, \ if "CMPATH" in os.environ: self.cfg_file = os.path.join(os.environ["CMPATH"], 'CMconfig.cfg') else: - self.cfg_file = 'CellModeller/CMconfig.cfg' + self.cfg_file = 'cellmodeller/CMconfig.cfg' if not self.init_cl(platnum=clPlatformNum, devnum=clDeviceNum): print("Couldn't initialise OpenCL context") return diff --git a/setup.py b/setup.py index cfb4e15a..8fd11288 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ from setuptools import setup import subprocess -version_py = os.path.join(os.path.dirname(__file__), 'CellModeller/version.py') +version_py = os.path.join(os.path.dirname(__file__), 'cellmodeller/version.py') try: version_git = subprocess.check_output(["git", "describe"], text=True).strip() @@ -24,9 +24,9 @@ 'setuptools>=70,<82', ], packages=[ - 'CellModeller', - 'CellModeller.Regulation', - 'CellModeller.gui' + 'cellmodeller', + 'cellmodeller.Regulation', + 'cellmodeller.gui' ], package_data={'': ['*.cl', '*.ui']}, python_requires='>=3', From ce14c52147cb2d6d618b8a29792f6a669f7b714b Mon Sep 17 00:00:00 2001 From: Guillermo Date: Fri, 9 Oct 2026 15:01:07 +0200 Subject: [PATCH 2/6] removed unused ModuleRegulator import from viewer --- cellmodeller/gui/py_gl_cm_viewer.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cellmodeller/gui/py_gl_cm_viewer.py b/cellmodeller/gui/py_gl_cm_viewer.py index 6cf63bfa..10ea647a 100644 --- a/cellmodeller/gui/py_gl_cm_viewer.py +++ b/cellmodeller/gui/py_gl_cm_viewer.py @@ -7,7 +7,6 @@ from OpenGL.GL import * from OpenGL.GLU import * -from cellmodeller.Regulation import ModuleRegulator from cellmodeller.simulator import Simulator from cellmodeller.cell_state import CellState import os From 4e614db94ead5382889613544b7119ee67356766 Mon Sep 17 00:00:00 2001 From: Guillermo Date: Fri, 9 Oct 2026 15:01:24 +0200 Subject: [PATCH 3/6] renamed Regulation folder and files to snake_case --- cellmodeller/{Regulation => regulation}/SBMLImport.py | 0 cellmodeller/{Regulation => regulation}/__init__.py | 0 .../ModuleRegulator.py => regulation/module_regulator.py} | 0 setup.py | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) rename cellmodeller/{Regulation => regulation}/SBMLImport.py (100%) rename cellmodeller/{Regulation => regulation}/__init__.py (100%) rename cellmodeller/{Regulation/ModuleRegulator.py => regulation/module_regulator.py} (100%) diff --git a/cellmodeller/Regulation/SBMLImport.py b/cellmodeller/regulation/SBMLImport.py similarity index 100% rename from cellmodeller/Regulation/SBMLImport.py rename to cellmodeller/regulation/SBMLImport.py diff --git a/cellmodeller/Regulation/__init__.py b/cellmodeller/regulation/__init__.py similarity index 100% rename from cellmodeller/Regulation/__init__.py rename to cellmodeller/regulation/__init__.py diff --git a/cellmodeller/Regulation/ModuleRegulator.py b/cellmodeller/regulation/module_regulator.py similarity index 100% rename from cellmodeller/Regulation/ModuleRegulator.py rename to cellmodeller/regulation/module_regulator.py diff --git a/setup.py b/setup.py index 8fd11288..d0a961e6 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ ], packages=[ 'cellmodeller', - 'cellmodeller.Regulation', + 'cellmodeller.regulation', 'cellmodeller.gui' ], package_data={'': ['*.cl', '*.ui']}, From 11cc3548315167b91a0af62de6b26fe0ad2e8292 Mon Sep 17 00:00:00 2001 From: Guillermo Date: Fri, 9 Oct 2026 15:04:35 +0200 Subject: [PATCH 4/6] renamed Scripts folder to scripts --- {Scripts => scripts}/batch.py | 0 {Scripts => scripts}/batch_file.py | 0 {Scripts => scripts}/batch_iter.py | 0 {Scripts => scripts}/cell_modeller_gui.py | 0 {Scripts => scripts}/contact_graph.py | 0 {Scripts => scripts}/contact_video.sh | 2 +- {Scripts => scripts}/draw_2d_pdf.py | 0 {Scripts => scripts}/git_publish.sh | 0 {Scripts => scripts}/length_histogram.py | 0 {Scripts => scripts}/multi_batch.py | 0 {Scripts => scripts}/print_timing.py | 0 {Scripts => scripts}/spatial_analyze.py | 0 {Scripts => scripts}/video.sh | 2 +- 13 files changed, 2 insertions(+), 2 deletions(-) rename {Scripts => scripts}/batch.py (100%) rename {Scripts => scripts}/batch_file.py (100%) rename {Scripts => scripts}/batch_iter.py (100%) rename {Scripts => scripts}/cell_modeller_gui.py (100%) rename {Scripts => scripts}/contact_graph.py (100%) rename {Scripts => scripts}/contact_video.sh (91%) rename {Scripts => scripts}/draw_2d_pdf.py (100%) rename {Scripts => scripts}/git_publish.sh (100%) rename {Scripts => scripts}/length_histogram.py (100%) rename {Scripts => scripts}/multi_batch.py (100%) rename {Scripts => scripts}/print_timing.py (100%) rename {Scripts => scripts}/spatial_analyze.py (100%) rename {Scripts => scripts}/video.sh (91%) diff --git a/Scripts/batch.py b/scripts/batch.py similarity index 100% rename from Scripts/batch.py rename to scripts/batch.py diff --git a/Scripts/batch_file.py b/scripts/batch_file.py similarity index 100% rename from Scripts/batch_file.py rename to scripts/batch_file.py diff --git a/Scripts/batch_iter.py b/scripts/batch_iter.py similarity index 100% rename from Scripts/batch_iter.py rename to scripts/batch_iter.py diff --git a/Scripts/cell_modeller_gui.py b/scripts/cell_modeller_gui.py similarity index 100% rename from Scripts/cell_modeller_gui.py rename to scripts/cell_modeller_gui.py diff --git a/Scripts/contact_graph.py b/scripts/contact_graph.py similarity index 100% rename from Scripts/contact_graph.py rename to scripts/contact_graph.py diff --git a/Scripts/contact_video.sh b/scripts/contact_video.sh similarity index 91% rename from Scripts/contact_video.sh rename to scripts/contact_video.sh index 09ef0233..bbb3e25f 100755 --- a/Scripts/contact_video.sh +++ b/scripts/contact_video.sh @@ -7,7 +7,7 @@ # Run Draw2DPDF to generate pdf files for f in $( ls *.pickle ); do echo Processing: $f - $CMPATH/bin/cmpython $CMPATH/Scripts/contact_graph.py $f + $CMPATH/bin/cmpython $CMPATH/scripts/contact_graph.py $f done # Convert and resize etc. pdf files into jpegs diff --git a/Scripts/draw_2d_pdf.py b/scripts/draw_2d_pdf.py similarity index 100% rename from Scripts/draw_2d_pdf.py rename to scripts/draw_2d_pdf.py diff --git a/Scripts/git_publish.sh b/scripts/git_publish.sh similarity index 100% rename from Scripts/git_publish.sh rename to scripts/git_publish.sh diff --git a/Scripts/length_histogram.py b/scripts/length_histogram.py similarity index 100% rename from Scripts/length_histogram.py rename to scripts/length_histogram.py diff --git a/Scripts/multi_batch.py b/scripts/multi_batch.py similarity index 100% rename from Scripts/multi_batch.py rename to scripts/multi_batch.py diff --git a/Scripts/print_timing.py b/scripts/print_timing.py similarity index 100% rename from Scripts/print_timing.py rename to scripts/print_timing.py diff --git a/Scripts/spatial_analyze.py b/scripts/spatial_analyze.py similarity index 100% rename from Scripts/spatial_analyze.py rename to scripts/spatial_analyze.py diff --git a/Scripts/video.sh b/scripts/video.sh similarity index 91% rename from Scripts/video.sh rename to scripts/video.sh index feb681c7..ee880a1f 100755 --- a/Scripts/video.sh +++ b/scripts/video.sh @@ -7,7 +7,7 @@ # Run Draw2DPDF to generate pdf files for f in $( ls *.pickle ); do echo Processing: $f - python $HOME/Code/CellModeller/Scripts/draw_2d_pdf.py $f + python $HOME/Code/CellModeller/scripts/draw_2d_pdf.py $f done # Convert and resize etc. pdf files into jpegs From c3bae9ff2498922b76a63efca323b4e704f88192 Mon Sep 17 00:00:00 2001 From: Guillermo Date: Fri, 9 Oct 2026 15:07:40 +0200 Subject: [PATCH 5/6] renamed Community folder to community --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 16cc3e30..6ffe5f65 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # CellModeller -[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](Community/code_of_conduct.md) +[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](community/code_of_conduct.md) ============= Multicellular modelling framework, created by Tim Rudge, PJ Steiner, and Jim Haseloff, University of Cambridge. -- [Contributing](Community/contributing.md) -- [Code of Conduct](Community/code_of_conduct.md) +- [Contributing](community/contributing.md) +- [Code of Conduct](community/code_of_conduct.md) From 52a0eb30dcf67aafd474dc6cf0dfdd539b2f4fd6 Mon Sep 17 00:00:00 2001 From: Tim Rudge Date: Sat, 10 Oct 2026 17:43:28 +0100 Subject: [PATCH 6/6] Black formatting --- cellmodeller/cell_state.py | 5 +- cellmodeller/gui/py_gl_cm_viewer.py | 200 +- cellmodeller/gui/py_gl_widget.py | 262 +- cellmodeller/gui/renderers.py | 2418 ++++++++++--------- cellmodeller/regulation/SBMLImport.py | 309 +-- cellmodeller/regulation/module_regulator.py | 9 +- cellmodeller/simulator.py | 266 +- scripts/batch.py | 28 +- scripts/batch_file.py | 22 +- scripts/batch_iter.py | 12 +- scripts/cell_modeller_gui.py | 5 +- scripts/contact_graph.py | 127 +- scripts/draw_2d_pdf.py | 161 +- scripts/length_histogram.py | 56 +- scripts/multi_batch.py | 25 +- scripts/print_timing.py | 14 +- scripts/spatial_analyze.py | 51 +- 17 files changed, 2086 insertions(+), 1884 deletions(-) diff --git a/cellmodeller/cell_state.py b/cellmodeller/cell_state.py index 4f155874..d70631c8 100644 --- a/cellmodeller/cell_state.py +++ b/cellmodeller/cell_state.py @@ -1,12 +1,11 @@ - class CellState: # Don't show these attributes in gui - excludeAttr = ['id', 'divideFlag', 'ends','cellAdh'] + excludeAttr = ["id", "divideFlag", "ends", "cellAdh"] def __init__(self, cid): self.id = cid self.growthRate = 1.0 - self.color = [0.5,0.5,0.5] + self.color = [0.5, 0.5, 0.5] self.divideFlag = False self.cellAge = 0 self.neighbours = [] diff --git a/cellmodeller/gui/py_gl_cm_viewer.py b/cellmodeller/gui/py_gl_cm_viewer.py index 10ea647a..ee8b5846 100644 --- a/cellmodeller/gui/py_gl_cm_viewer.py +++ b/cellmodeller/gui/py_gl_cm_viewer.py @@ -16,15 +16,16 @@ import importlib import numpy as np + class PyGLCMViewer(PyGLWidget): setSavePicklesToggle = pyqtSignal(bool) - selectedCell = pyqtSignal(str) #emit selected cell info + selectedCell = pyqtSignal(str) # emit selected cell info selectedName = -1 dt = 0.05 - def __init__(self, parent = None): - PyGLWidget.__init__(self,parent) + def __init__(self, parent=None): + PyGLWidget.__init__(self, parent) self.animTimer = QTimer() self.animTimer.timeout.connect(self.animate) self.animTimer.start(0) @@ -33,17 +34,17 @@ def __init__(self, parent = None): self.run = False self.frameNo = 0 self.loadingFromPickle = False - self.clPlatformNum=0 - self.clDeviceNum=0 + self.clPlatformNum = 0 + self.clDeviceNum = 0 # Initial view setup self.set_radius(32) - self.rotate([0,0,1],-45) - self.translate([0,0,20]) - self.rotate([1,0,0],-45) + self.rotate([0, 0, 1], -45) + self.translate([0, 0, 20]) + self.rotate([1, 0, 0], -45) # Assume no pixel scaling unless explicitly set - self.pix_ratio = 1. + self.pix_ratio = 1.0 def help(self): pass @@ -60,7 +61,7 @@ def setSimulator(self, sim): self.frameNo += 1 # Make GUI button match simulator state for saving pickles self.setSavePicklesToggle.emit(sim.saveOutput) - print('saveOutput ', sim.saveOutput) + print("saveOutput ", sim.saveOutput) # Get rid of any selected cell id self.selectedName = -1 @@ -68,21 +69,23 @@ def getOpenCLPlatDev(self): return self.getOpenCLPlatform() and self.getOpenCLDevice() def getOpenCLPlatform(self): - # Pop dialogs to get user to choose OpenCL platform + # Pop dialogs to get user to choose OpenCL platform platforms = cl.get_platforms() platlist = [str(p.name) for p in platforms] platdict = dict(list(zip(platlist, list(range(len(platlist)))))) - if len(platlist)==1: + if len(platlist) == 1: self.clPlatformNum = 0 return True - qsPlatformName, ok = QInputDialog.getItem(self, \ - 'Choose OpenCL platform', \ - 'Available platforms:', \ - platlist, \ - editable=False) + qsPlatformName, ok = QInputDialog.getItem( + self, + "Choose OpenCL platform", + "Available platforms:", + platlist, + editable=False, + ) if not ok: print("You didn't select a OpenCL platform...") return False @@ -97,16 +100,14 @@ def getOpenCLDevice(self): devlist = [str(d.name) for d in devices] devdict = dict(list(zip(devlist, list(range(len(devlist)))))) - - if len(devlist)==1: + + if len(devlist) == 1: self.clDeviceNum = 0 return True - - qsDeviceName, ok = QInputDialog.getItem(self, \ - 'Choose OpenCL device', \ - 'Available devices:', \ - devlist, \ - editable=False) + + qsDeviceName, ok = QInputDialog.getItem( + self, "Choose OpenCL device", "Available devices:", devlist, editable=False + ) if not ok: print("You didn't select a OpenCL device...") return False @@ -114,7 +115,6 @@ def getOpenCLDevice(self): self.clDeviceNum = devdict[qsDeviceName] return True - @pyqtSlot(bool) def toggleRun(self, run): self.run = run @@ -133,20 +133,24 @@ def reset(self): importlib.reload(self.sim.module) if self.loadingFromPickle: - sim = Simulator(self.modName, \ - self.dt, \ - moduleStr=self.moduleStr, \ - clPlatformNum=self.clPlatformNum, \ - clDeviceNum=self.clDeviceNum, \ - is_gui=True) - self.setSimulator(sim) + sim = Simulator( + self.modName, + self.dt, + moduleStr=self.moduleStr, + clPlatformNum=self.clPlatformNum, + clDeviceNum=self.clDeviceNum, + is_gui=True, + ) + self.setSimulator(sim) else: - sim = Simulator(self.modName, \ - self.dt, \ - clPlatformNum=self.clPlatformNum, \ - clDeviceNum=self.clDeviceNum, \ - is_gui=True) - self.setSimulator(sim) + sim = Simulator( + self.modName, + self.dt, + clPlatformNum=self.clPlatformNum, + clDeviceNum=self.clDeviceNum, + is_gui=True, + ) + self.setSimulator(sim) self.frameNo = 0 self.updateGL() @@ -154,11 +158,13 @@ def reset(self): def loadGeometry(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog - qs,_ = QFileDialog.getOpenFileName(self, 'Load geometry from pickle file', '', '*.pickle', options=options) + qs, _ = QFileDialog.getOpenFileName( + self, "Load geometry from pickle file", "", "*.pickle", options=options + ) if qs: filename = str(qs) print(filename) - data = pickle.load(open(filename,'rb')) + data = pickle.load(open(filename, "rb")) if isinstance(data, dict): self.sim.loadGeometryFromPickle(data) self.frameNo = self.sim.stepNum @@ -172,22 +178,26 @@ def loadGeometry(self): def loadPickle(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog - qs,_ = QFileDialog.getOpenFileName(self, 'Load pickle file', '', '*.pickle', options=options) + qs, _ = QFileDialog.getOpenFileName( + self, "Load pickle file", "", "*.pickle", options=options + ) if qs and self.getOpenCLPlatDev(): filename = str(qs) print(filename) - data = pickle.load(open(filename,'rb')) + data = pickle.load(open(filename, "rb")) if isinstance(data, dict): - self.modName = data['moduleName'] - self.moduleStr = data['moduleStr'] - self.frameNo = data['stepNum'] - sim = Simulator(self.modName, \ - self.dt, \ - moduleStr=self.moduleStr, \ - clPlatformNum=self.clPlatformNum, \ - clDeviceNum=self.clDeviceNum, \ - is_gui=True) - + self.modName = data["moduleName"] + self.moduleStr = data["moduleStr"] + self.frameNo = data["stepNum"] + sim = Simulator( + self.modName, + self.dt, + moduleStr=self.moduleStr, + clPlatformNum=self.clPlatformNum, + clDeviceNum=self.clDeviceNum, + is_gui=True, + ) + self.loadingFromPickle = True sim.loadFromPickle(data) self.setSimulator(sim) @@ -204,7 +214,9 @@ def loadPickle(self): def load(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog - qs,_ = QFileDialog.getOpenFileName(self, 'Load Python module', '', '*.py', options=options) + qs, _ = QFileDialog.getOpenFileName( + self, "Load Python module", "", "*.py", options=options + ) if qs: modfile = str(qs) print(modfile) @@ -212,20 +224,21 @@ def load(self): def loadModelFile(self, modname): if self.getOpenCLPlatDev(): - self.loadingFromPickle=False - (path,name) = os.path.split(modname) - self.modName = str(name).split('.')[0] + self.loadingFromPickle = False + path, name = os.path.split(modname) + self.modName = str(name).split(".")[0] sys.path.append(path) - sim = Simulator(self.modName, \ - self.dt, \ - clPlatformNum=self.clPlatformNum, \ - clDeviceNum=self.clDeviceNum, \ - is_gui=True) - + sim = Simulator( + self.modName, + self.dt, + clPlatformNum=self.clPlatformNum, + clDeviceNum=self.clDeviceNum, + is_gui=True, + ) + self.setSimulator(sim) self.updateGL() - def animate(self): if self.sim: if self.frameNo > self.sim.stepNum: @@ -233,25 +246,25 @@ def animate(self): self.updateSelectedCell() if self.run: self.frameNo += 1 - + def updateSelectedCell(self): if self.sim: states = self.sim.cellStates cid = self.selectedName - txt = '' + txt = "" if cid in states: - txt += 'Selected Cell (id = %d)
'%(cid) + txt += "Selected Cell (id = %d)
" % (cid) s = states[cid] - for (name,val) in list(s.__dict__.items()): + for name, val in list(s.__dict__.items()): if name not in CellState.excludeAttr: - txt += '' + name + ':\t' + txt += "" + name + ":\t" if type(val) in [float, np.float32, np.float64]: - txt += '%g'%val + txt += "%g" % val elif type(val) in [list, tuple, np.array]: - txt += ', '.join(['%g'%v for v in val]) + txt += ", ".join(["%g" % v for v in val]) else: txt += str(val) - txt += '
' + txt += "
" self.selectedCell.emit(txt) self.updateGL() @@ -264,7 +277,7 @@ def translate(self, _trans): cid = self.selectedName # Uncomment the condition below to enable movement of cells # currently the translation is not great due to the way PyGLWidget works - if False: #self.sim and self.sim.cellStates.has_key(cid): + if False: # self.sim and self.sim.cellStates.has_key(cid): self.sim.moveCell(cid, _trans) print("Called self.sim.moveCell") self.updateSelectedCell() @@ -284,12 +297,12 @@ def translate(self, _trans): def paintGL(self): PyGLWidget.paintGL(self) - glClearColor(0.5,0.5,0.5,0.0) + glClearColor(0.5, 0.5, 0.5, 0.0) glClear(GL_COLOR_BUFFER_BIT) glMatrixMode(GL_MODELVIEW) glPushMatrix() - #s = self.renderInfo.scale - #glScalef(s,s,s) + # s = self.renderInfo.scale + # glScalef(s,s,s) # Draw a grid in xy plane glEnable(GL_DEPTH_TEST) @@ -299,24 +312,24 @@ def paintGL(self): glLineWidth(1.0) glBegin(GL_LINES) for i in range(25): - glVertex(-120, (i-12)*10, 0) - glVertex(120, (i-12)*10, 0) - glVertex((i-12)*10, -120, 0) - glVertex((i-12)*10, 120, 0) + glVertex(-120, (i - 12) * 10, 0) + glVertex(120, (i - 12) * 10, 0) + glVertex((i - 12) * 10, -120, 0) + glVertex((i - 12) * 10, 120, 0) glEnd() # Draw x,y,z axes glDisable(GL_DEPTH_TEST) glBegin(GL_LINES) - glColor3f(1.0,0.0,0.0) - glVertex(0,0,0) - glVertex(25,0,0) - glColor3f(0.0,1.0,0.0) - glVertex(0,0,0) - glVertex(0,25,0) - glColor3f(0.0,0.0,1.0) - glVertex(0,0,0) - glVertex(0,0,25) + glColor3f(1.0, 0.0, 0.0) + glVertex(0, 0, 0) + glVertex(25, 0, 0) + glColor3f(0.0, 1.0, 0.0) + glVertex(0, 0, 0) + glVertex(0, 25, 0) + glColor3f(0.0, 0.0, 1.0) + glVertex(0, 0, 0) + glVertex(0, 0, 25) glEnd() glEnable(GL_DEPTH_TEST) glEnable(GL_LIGHTING) @@ -331,8 +344,8 @@ def paintGL(self): def drawWithNames(self): glMatrixMode(GL_MODELVIEW) glPushMatrix() - #s = self.renderInfo.scale - #glScalef(s,s,s) + # s = self.renderInfo.scale + # glScalef(s,s,s) if self.sim: for r in self.sim.renderers: if r: @@ -340,16 +353,17 @@ def drawWithNames(self): glPopMatrix() - class RenderInfo: def __init__(self): self.renderers = [] self.scale = 1.0 + def addRenderer(self, renderer): self.renderers.append(renderer) + def reset(self): self.renderers = [] self.scale = 1.0 + def setScale(self, s): self.scale = s - diff --git a/cellmodeller/gui/py_gl_widget.py b/cellmodeller/gui/py_gl_widget.py index e10c9d11..92b1fb38 100644 --- a/cellmodeller/gui/py_gl_widget.py +++ b/cellmodeller/gui/py_gl_widget.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -#=============================================================================== +# =============================================================================== # # PyGLWidget.py # @@ -30,17 +30,19 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -#=============================================================================== +# =============================================================================== from PyQt5 import QtCore, QtGui, QtOpenGL import math import numpy import numpy.linalg as linalg import OpenGL + OpenGL.ERROR_CHECKING = True from OpenGL.GL import * from OpenGL.GLU import * + class PyGLWidget(QtOpenGL.QGLWidget): # Qt signals @@ -48,30 +50,30 @@ class PyGLWidget(QtOpenGL.QGLWidget): rotationBeginEvent = QtCore.pyqtSignal() rotationEndEvent = QtCore.pyqtSignal() - def __init__(self, parent = None): + def __init__(self, parent=None): format = QtOpenGL.QGLFormat() format.setSampleBuffers(True) QtOpenGL.QGLWidget.__init__(self, format, parent) - #self.setCursor(QtCore.Qt.OpenHandCursor) + # self.setCursor(QtCore.Qt.OpenHandCursor) self.setMouseTracking(True) - self.modelview_matrix_ = [] - self.translate_vector_ = [0.0, 0.0, 0.0] - self.viewport_matrix_ = [] + self.modelview_matrix_ = [] + self.translate_vector_ = [0.0, 0.0, 0.0] + self.viewport_matrix_ = [] self.projection_matrix_ = [] - self.near_ = 0.1 - self.far_ = 100.0 - self.fovy_ = 45.0 + self.near_ = 0.1 + self.far_ = 100.0 + self.fovy_ = 45.0 self.radius_ = 5.0 self.last_point_2D_ = QtCore.QPoint() self.last_point_ok_ = False self.last_point_3D_ = [1.0, 0.0, 0.0] - self.isInRotation_ = False + self.isInRotation_ = False self.pickSize = 18 - self.pix_ratio = 1. + self.pix_ratio = 1.0 # connections - #self.signalGLMatrixChanged.connect(self.printModelViewMatrix) + # self.signalGLMatrixChanged.connect(self.printModelViewMatrix) @QtCore.pyqtSlot() def printModelViewMatrix(self): @@ -84,8 +86,8 @@ def initializeGL(self): self.reset_view() def resizeGL(self, width, height): - glViewport( 0, 0, width, height ); - self.set_projection( self.near_, self.far_, self.fovy_ ); + glViewport(0, 0, width, height) + self.set_projection(self.near_, self.far_, self.fovy_) self.updateGL() def paintGL(self): @@ -99,9 +101,14 @@ def set_projection(self, _near, _far, _fovy): self.far_ = _far self.fovy_ = _fovy self.makeCurrent() - glMatrixMode( GL_PROJECTION ) + glMatrixMode(GL_PROJECTION) glLoadIdentity() - gluPerspective( self.fovy_, float(self.width()) / float(self.height()), self.near_, self.far_ ) + gluPerspective( + self.fovy_, + float(self.width()) / float(self.height()), + self.near_, + self.far_, + ) self.updateGL() def set_pick_projection(self, x, y, _near, _far, _fovy): @@ -109,13 +116,24 @@ def set_pick_projection(self, x, y, _near, _far, _fovy): self.far_ = _far self.fovy_ = _fovy self.makeCurrent() - glMatrixMode( GL_PROJECTION ) + glMatrixMode(GL_PROJECTION) glLoadIdentity() viewport = glGetIntegerv(GL_VIEWPORT) - #gluPickMatrix(x, viewport[3]-y, self.pickSize, self.pickSize, viewport); - gluPickMatrix(x*self.pix_ratio, viewport[3]-y*self.pix_ratio, self.pickSize, self.pickSize, viewport); - gluPerspective( self.fovy_, float(self.width()) / float(self.height()), self.near_, self.far_ ) - + # gluPickMatrix(x, viewport[3]-y, self.pickSize, self.pickSize, viewport); + gluPickMatrix( + x * self.pix_ratio, + viewport[3] - y * self.pix_ratio, + self.pickSize, + self.pickSize, + viewport, + ) + gluPerspective( + self.fovy_, + float(self.width()) / float(self.height()), + self.near_, + self.far_, + ) + def set_center(self, _cog): self.center_ = _cog self.view_all() @@ -130,9 +148,9 @@ def set_radius(self, _radius): def reset_view(self): # scene pos and size - glMatrixMode( GL_MODELVIEW ) - glLoadIdentity(); - self.modelview_matrix_ = glGetDoublev( GL_MODELVIEW_MATRIX ) + glMatrixMode(GL_MODELVIEW) + glLoadIdentity() + self.modelview_matrix_ = glGetDoublev(GL_MODELVIEW_MATRIX) self.set_center([0.0, 0.0, 0.0]) def reset_rotation(self): @@ -142,7 +160,7 @@ def reset_rotation(self): glMatrixMode(GL_MODELVIEW) glLoadMatrixd(self.modelview_matrix_) self.updateGL() - + def translate(self, _trans): # Translate the object by _trans # Update modelview_matrix_ @@ -158,18 +176,20 @@ def translate(self, _trans): self.signalGLMatrixChanged.emit() def rotate(self, _axis, _angle): - t = [self.modelview_matrix_[0][0] * self.center_[0] + - self.modelview_matrix_[1][0] * self.center_[1] + - self.modelview_matrix_[2][0] * self.center_[2] + - self.modelview_matrix_[3][0], - self.modelview_matrix_[0][1] * self.center_[0] + - self.modelview_matrix_[1][1] * self.center_[1] + - self.modelview_matrix_[2][1] * self.center_[2] + - self.modelview_matrix_[3][1], - self.modelview_matrix_[0][2] * self.center_[0] + - self.modelview_matrix_[1][2] * self.center_[1] + - self.modelview_matrix_[2][2] * self.center_[2] + - self.modelview_matrix_[3][2]] + t = [ + self.modelview_matrix_[0][0] * self.center_[0] + + self.modelview_matrix_[1][0] * self.center_[1] + + self.modelview_matrix_[2][0] * self.center_[2] + + self.modelview_matrix_[3][0], + self.modelview_matrix_[0][1] * self.center_[0] + + self.modelview_matrix_[1][1] * self.center_[1] + + self.modelview_matrix_[2][1] * self.center_[2] + + self.modelview_matrix_[3][1], + self.modelview_matrix_[0][2] * self.center_[0] + + self.modelview_matrix_[1][2] * self.center_[1] + + self.modelview_matrix_[2][2] * self.center_[2] + + self.modelview_matrix_[3][2], + ] self.makeCurrent() glLoadIdentity() @@ -181,35 +201,49 @@ def rotate(self, _axis, _angle): self.signalGLMatrixChanged.emit() def view_all(self): - self.translate( [ -( self.modelview_matrix_[0][0] * self.center_[0] + - self.modelview_matrix_[0][1] * self.center_[1] + - self.modelview_matrix_[0][2] * self.center_[2] + - self.modelview_matrix_[0][3]), - -( self.modelview_matrix_[1][0] * self.center_[0] + - self.modelview_matrix_[1][1] * self.center_[1] + - self.modelview_matrix_[1][2] * self.center_[2] + - self.modelview_matrix_[1][3]), - -( self.modelview_matrix_[2][0] * self.center_[0] + - self.modelview_matrix_[2][1] * self.center_[1] + - self.modelview_matrix_[2][2] * self.center_[2] + - self.modelview_matrix_[2][3] + - self.radius_ / 2.0 )]) + self.translate( + [ + -( + self.modelview_matrix_[0][0] * self.center_[0] + + self.modelview_matrix_[0][1] * self.center_[1] + + self.modelview_matrix_[0][2] * self.center_[2] + + self.modelview_matrix_[0][3] + ), + -( + self.modelview_matrix_[1][0] * self.center_[0] + + self.modelview_matrix_[1][1] * self.center_[1] + + self.modelview_matrix_[1][2] * self.center_[2] + + self.modelview_matrix_[1][3] + ), + -( + self.modelview_matrix_[2][0] * self.center_[0] + + self.modelview_matrix_[2][1] * self.center_[1] + + self.modelview_matrix_[2][2] * self.center_[2] + + self.modelview_matrix_[2][3] + + self.radius_ / 2.0 + ), + ] + ) def map_to_sphere(self, _v2D): _v3D = [0.0, 0.0, 0.0] # inside Widget? - if (( _v2D.x() >= 0 ) and ( _v2D.x() <= self.width() ) and - ( _v2D.y() >= 0 ) and ( _v2D.y() <= self.height() ) ): + if ( + (_v2D.x() >= 0) + and (_v2D.x() <= self.width()) + and (_v2D.y() >= 0) + and (_v2D.y() <= self.height()) + ): # map Qt Coordinates to the centered unit square [-0.5..0.5]x[-0.5..0.5] - x = float( _v2D.x() - 0.5 * self.width()) / self.width() - y = float( 0.5 * self.height() - _v2D.y()) / self.height() + x = float(_v2D.x() - 0.5 * self.width()) / self.width() + y = float(0.5 * self.height() - _v2D.y()) / self.height() - _v3D[0] = x; - _v3D[1] = y; + _v3D[0] = x + _v3D[1] = y # use Pythagoras to comp z-coord (the sphere has radius sqrt(2.0*0.5*0.5)) - z2 = 2.0*0.5*0.5-x*x-y*y; + z2 = 2.0 * 0.5 * 0.5 - x * x - y * y # numerical robust sqrt - _v3D[2] = math.sqrt(max( z2, 0.0 )) + _v3D[2] = math.sqrt(max(z2, 0.0)) # normalize direction to unit sphere n = linalg.norm(_v3D) @@ -221,53 +255,63 @@ def map_to_sphere(self, _v2D): def wheelEvent(self, _event): # Use the mouse wheel to zoom in/out - d = - float(_event.angleDelta().y()) / 200.0 * self.radius_ + d = -float(_event.angleDelta().y()) / 200.0 * self.radius_ self.translate([0.0, 0.0, d]) self.updateGL() _event.accept() def selectName(self, point): - glSelectBuffer(500) # allocate a selection buffer of SIZE elements + glSelectBuffer(500) # allocate a selection buffer of SIZE elements glRenderMode(GL_SELECT) - - glMatrixMode( GL_PROJECTION ) + + glMatrixMode(GL_PROJECTION) glPushMatrix() - self.set_pick_projection( point.x(), point.y(), self.near_, self.far_, self.fovy_ ); - - #self.paintGL() + self.set_pick_projection( + point.x(), point.y(), self.near_, self.far_, self.fovy_ + ) + + # self.paintGL() self.drawWithNames() buf = glRenderMode(GL_RENDER) selectedName = -1 closest_z = 1.0 - print('buf ', buf) + print("buf ", buf) for hit_record in buf: min_depth, max_depth, names = hit_record - print('Names ', names) + print("Names ", names) if min_depth < closest_z: closest_z = min_depth for name in names: if name: selectedName = name - print('Selected name ', selectedName) - glMatrixMode( GL_PROJECTION ) + print("Selected name ", selectedName) + glMatrixMode(GL_PROJECTION) glPopMatrix() return selectedName - + def mousePressEvent(self, _event): self.last_point_2D_ = _event.pos() - self.last_point_ok_, self.last_point_3D_ = self.map_to_sphere(self.last_point_2D_) - if (_event.buttons() & QtCore.Qt.LeftButton) and (_event.modifiers() & QtCore.Qt.ShiftModifier): + self.last_point_ok_, self.last_point_3D_ = self.map_to_sphere( + self.last_point_2D_ + ) + if (_event.buttons() & QtCore.Qt.LeftButton) and ( + _event.modifiers() & QtCore.Qt.ShiftModifier + ): name = self.selectName(_event.pos()) self.postSelection(name) def mouseMoveEvent(self, _event): newPoint2D = _event.pos() - if ((newPoint2D.x() < 0) or (newPoint2D.x() > self.width()) or - (newPoint2D.y() < 0) or (newPoint2D.y() > self.height())): + if ( + (newPoint2D.x() < 0) + or (newPoint2D.x() > self.width()) + or (newPoint2D.y() < 0) + or (newPoint2D.y() > self.height()) + ): return - + # Left button: rotate around center_ # Middle button: translate object # Left & middle button: zoom in/out @@ -278,49 +322,60 @@ def mouseMoveEvent(self, _event): dx = float(newPoint2D.x() - self.last_point_2D_.x()) dy = float(newPoint2D.y() - self.last_point_2D_.y()) - w = float(self.width()) - h = float(self.height()) + w = float(self.width()) + h = float(self.height()) # enable GL context self.makeCurrent() # move in z direction - if (((_event.buttons() & QtCore.Qt.LeftButton) and (_event.buttons() & QtCore.Qt.MidButton)) - or (_event.buttons() & QtCore.Qt.LeftButton and _event.modifiers() & QtCore.Qt.ControlModifier)): + if ( + (_event.buttons() & QtCore.Qt.LeftButton) + and (_event.buttons() & QtCore.Qt.MidButton) + ) or ( + _event.buttons() & QtCore.Qt.LeftButton + and _event.modifiers() & QtCore.Qt.ControlModifier + ): print("translating in Z") value_y = self.radius_ * dy * 2.0 / h self.translate([0.0, 0.0, value_y]) # move in x,y direction - elif (_event.buttons() & QtCore.Qt.RightButton): - z = - (self.modelview_matrix_[0][2] * self.center_[0] + - self.modelview_matrix_[1][2] * self.center_[1] + - self.modelview_matrix_[2][2] * self.center_[2] + - self.modelview_matrix_[3][2]) / (self.modelview_matrix_[0][3] * self.center_[0] + - self.modelview_matrix_[1][3] * self.center_[1] + - self.modelview_matrix_[2][3] * self.center_[2] + - self.modelview_matrix_[3][3]) - fovy = 45.0 + elif _event.buttons() & QtCore.Qt.RightButton: + z = -( + self.modelview_matrix_[0][2] * self.center_[0] + + self.modelview_matrix_[1][2] * self.center_[1] + + self.modelview_matrix_[2][2] * self.center_[2] + + self.modelview_matrix_[3][2] + ) / ( + self.modelview_matrix_[0][3] * self.center_[0] + + self.modelview_matrix_[1][3] * self.center_[1] + + self.modelview_matrix_[2][3] * self.center_[2] + + self.modelview_matrix_[3][3] + ) + fovy = 45.0 aspect = w / h - n = 0.01 * self.radius_ - up = math.tan(fovy / 2.0 * math.pi / 180.0) * n - right = aspect * up + n = 0.01 * self.radius_ + up = math.tan(fovy / 2.0 * math.pi / 180.0) * n + right = aspect * up - self.translate( [2.0 * dx / w * right / n * z, - -2.0 * dy / h * up / n * z, - 0.0] ) + self.translate( + [2.0 * dx / w * right / n * z, -2.0 * dy / h * up / n * z, 0.0] + ) # rotate - elif (_event.buttons() & QtCore.Qt.LeftButton and (not _event.modifiers() & QtCore.Qt.ShiftModifier)): - if (not self.isInRotation_): + elif _event.buttons() & QtCore.Qt.LeftButton and ( + not _event.modifiers() & QtCore.Qt.ShiftModifier + ): + if not self.isInRotation_: self.isInRotation_ = True self.rotationBeginEvent.emit() - + axis = [0.0, 0.0, 0.0] angle = 0.0 - if (self.last_point_ok_ and newPoint_hitSphere): + if self.last_point_ok_ and newPoint_hitSphere: axis = numpy.cross(self.last_point_3D_, newPoint3D) cos_angle = numpy.dot(self.last_point_3D_, newPoint3D) - if (abs(cos_angle) < 1.0): + if abs(cos_angle) < 1.0: angle = math.acos(cos_angle) * 180.0 / math.pi angle *= 2.0 self.rotate(axis, angle) @@ -334,16 +389,17 @@ def mouseMoveEvent(self, _event): self.updateGL() def mouseReleaseEvent(self, _event): - if (self.isInRotation_): + if self.isInRotation_: self.isInRotation_ = False self.rotationEndEvent.emit() last_point_ok_ = False -#=============================================================================== + +# =============================================================================== # # Local Variables: # mode: Python # indent-tabs-mode: nil # End: # -#=============================================================================== +# =============================================================================== diff --git a/cellmodeller/gui/renderers.py b/cellmodeller/gui/renderers.py index 7935e57e..fbdb496f 100644 --- a/cellmodeller/gui/renderers.py +++ b/cellmodeller/gui/renderers.py @@ -4,203 +4,231 @@ import math import numpy import random -#import pygame # helper module for text rendering - turned off to see if it suppresses segfaults -#from pyopencl.array import vec + +# import pygame # helper module for text rendering - turned off to see if it suppresses segfaults +# from pyopencl.array import vec + class GLSphereRenderer: - def __init__(self, sim, properties=None, scales = None): - self.ncells_list = 0 - self.ncells_names_list = 0 - self.dlist = None - self.dlist_names = None - self.cellcol = [1, 1, 1] - self.sim = sim - self.quad = gluNewQuadric() - self.properties = properties - self.scales = scales - - def init_gl(self): - pass - - def build_list(self, cells): - if self.dlist: - glDeleteLists(self.dlist, 1) - index = glGenLists(1) - glNewList(index, GL_COMPILE) - self.render_cells() - glEndList() - self.dlist = index - - def build_list_names(self, cells): - if self.dlist_names: - glDeleteLists(self.dlist_names, 1) - index = glGenLists(1) - glNewList(index, GL_COMPILE) - self.render_cell_names() - glEndList() - self.dlist_names = index - - def render_gl(self, selection=None): - cells = self.sim.cellStates.values() - states = self.sim.cellStates.items() + def __init__(self, sim, properties=None, scales=None): + self.ncells_list = 0 + self.ncells_names_list = 0 + self.dlist = None + self.dlist_names = None + self.cellcol = [1, 1, 1] + self.sim = sim + self.quad = gluNewQuadric() + self.properties = properties + self.scales = scales + + def init_gl(self): + pass + + def build_list(self, cells): + if self.dlist: + glDeleteLists(self.dlist, 1) + index = glGenLists(1) + glNewList(index, GL_COMPILE) + self.render_cells() + glEndList() + self.dlist = index + + def build_list_names(self, cells): + if self.dlist_names: + glDeleteLists(self.dlist_names, 1) + index = glGenLists(1) + glNewList(index, GL_COMPILE) + self.render_cell_names() + glEndList() + self.dlist_names = index + + def render_gl(self, selection=None): + cells = self.sim.cellStates.values() + states = self.sim.cellStates.items() # FIXED ============================================================================= - # Before, the renderer would only draw cells when the number of cells changed. - # Now it draws them whenever render_gl is called (by paintGL in PyGLCMViewer.py) - #if len(cells)!=self.ncells_list or len(cells)<500: - # self.build_list(cells) - # self.ncells_list = len(cells) - - #if len(cells)!=self.ncells_list: - # self.build_list(cells) - # self.ncells_list = len(cells) - #==================================================================================== - #glCallList(self.dlist) - self.render_cells(selection=selection) - - - def renderNames_gl(self, selection=None): - #cells = self.sim.cellStates.values() - #if len(cells)!=self.ncells_names_list or len(cells)<500: - # self.build_list_names(cells) - # self.ncells_names_list = len(cells) - #glCallList(self.dlist_names) - #for cell in cells: self.render_cell_name(cell, selection) - self.render_cell_names() - - def render_cell_names(self): - # glDisable(GL_DEPTH_TEST) - glDisable(GL_LIGHTING) - for cell in self.sim.cellStates.values(): - l = cell.length - p = cell.pos - - cid = cell.id - glPushName(cid) - - glMatrixMode(GL_MODELVIEW) - glPushMatrix() - glTranslatef(p[0],p[1],p[2]) - gluSphere(self.quad, r, 8, 8) - glPopMatrix() + # Before, the renderer would only draw cells when the number of cells changed. + # Now it draws them whenever render_gl is called (by paintGL in PyGLCMViewer.py) + # if len(cells)!=self.ncells_list or len(cells)<500: + # self.build_list(cells) + # self.ncells_list = len(cells) + + # if len(cells)!=self.ncells_list: + # self.build_list(cells) + # self.ncells_list = len(cells) + # ==================================================================================== + # glCallList(self.dlist) + self.render_cells(selection=selection) - glPopName() + def renderNames_gl(self, selection=None): + # cells = self.sim.cellStates.values() + # if len(cells)!=self.ncells_names_list or len(cells)<500: + # self.build_list_names(cells) + # self.ncells_names_list = len(cells) + # glCallList(self.dlist_names) + # for cell in cells: self.render_cell_name(cell, selection) + self.render_cell_names() + + def render_cell_names(self): + # glDisable(GL_DEPTH_TEST) + glDisable(GL_LIGHTING) + for cell in self.sim.cellStates.values(): + l = cell.length + p = cell.pos - glEnable(GL_LIGHTING) + cid = cell.id + glPushName(cid) - def render_cell(self, cell, selection): - r = cell.radius - p = cell.pos - cid = cell.id - if selection==cid: - cellcol = [1,0,0] - else: - cellcol = cell.color + glMatrixMode(GL_MODELVIEW) + glPushMatrix() + glTranslatef(p[0], p[1], p[2]) + gluSphere(self.quad, r, 8, 8) + glPopMatrix() - glColor3fv(cellcol) + glPopName() - glMatrixMode(GL_MODELVIEW) - glPushMatrix() - glTranslatef(p[0],p[1],p[2]) - gluSphere(self.quad, r, 8, 8) - glPopMatrix() + glEnable(GL_LIGHTING) + + def render_cell(self, cell, selection): + r = cell.radius + p = cell.pos + cid = cell.id + if selection == cid: + cellcol = [1, 0, 0] + else: + cellcol = cell.color + + glColor3fv(cellcol) + + glMatrixMode(GL_MODELVIEW) + glPushMatrix() + glTranslatef(p[0], p[1], p[2]) + gluSphere(self.quad, r, 8, 8) + glPopMatrix() + + def render_cells(self, selection=None): + + # PLACEHOLDER + + # glDisable(GL_DEPTH_TEST) + glDisable(GL_LIGHTING) + cells = self.sim.cellStates.values() + for cell in cells: + self.render_cell(cell, selection) - def render_cells(self, selection=None): - - # PLACEHOLDER - - #glDisable(GL_DEPTH_TEST) - glDisable(GL_LIGHTING) - cells = self.sim.cellStates.values() - for cell in cells: - self.render_cell(cell, selection) class GLGridRenderer: - def __init__(self, sig, integ, rng=None, alpha=1.): + def __init__(self, sig, integ, rng=None, alpha=1.0): self.sig = sig self.integ = integ self.rng = rng self.alpha = alpha self.size = self.sig.gridSize self.dim = self.sig.gridDim[1:] - self.len = self.dim[0]*self.dim[1] - self.orig = [self.sig.gridOrig[i] - self.sig.gridSize[i]*0.5 for i in range(3)] + self.len = self.dim[0] * self.dim[1] + self.orig = [ + self.sig.gridOrig[i] - self.sig.gridSize[i] * 0.5 for i in range(3) + ] self.texture = glGenTextures(1) self.imageData = numpy.zeros(self.dim) - # Create byte array for texture data: OpenGL requires 2^n size and + # Create byte array for texture data: OpenGL requires 2^n size and # square? - self.texDim = max([2**math.ceil(math.log(d,2)) for d in self.dim[0:2]]) + self.texDim = max([2 ** math.ceil(math.log(d, 2)) for d in self.dim[0:2]]) # The texture coordinates to fit the actual data - self.tyMax = self.dim[0]/self.texDim - self.txMax = self.dim[1]/self.texDim + self.tyMax = self.dim[0] / self.texDim + self.txMax = self.dim[1] / self.texDim # The texture data, 3 bytes per (x,y,z) - self.byteImageData = numpy.zeros((self.texDim,self.texDim)+(3,)).astype(numpy.uint8) + self.byteImageData = numpy.zeros((self.texDim, self.texDim) + (3,)).astype( + numpy.uint8 + ) def init_gl(self): - pass - + pass + def renderNames_gl(self): - pass - + pass + def render_gl(self, selection=None): signalLevel = self.integ.signalLevel.reshape(self.sig.gridDim) - self.imageData = signalLevel[:,:,:,math.floor(self.dim[2]*0.5)] #numpy.log(self.sig.level[:,:,:,0]+1e-8) + self.imageData = signalLevel[ + :, :, :, math.floor(self.dim[2] * 0.5) + ] # numpy.log(self.sig.level[:,:,:,0]+1e-8) if self.rng: mx = self.rng[1] mn = self.rng[0] else: mx = numpy.max(self.imageData) mn = numpy.min(self.imageData) - if mx>mn: - scale = 255/(mx-mn) + if mx > mn: + scale = 255 / (mx - mn) else: scale = 1 - self.imageData = (self.imageData - mn)*scale - #print "Signal grid range = %f to %f"%(mn,mx) + self.imageData = (self.imageData - mn) * scale + # print "Signal grid range = %f to %f"%(mn,mx) for s in range(self.sig.nSignals): - self.byteImageData[0:self.dim[0],0:self.dim[1],s] = self.imageData[s,:,:].astype(numpy.uint8) + self.byteImageData[0 : self.dim[0], 0 : self.dim[1], s] = self.imageData[ + s, :, : + ].astype(numpy.uint8) - glEnable(GL_TEXTURE_2D) glDisable(GL_LIGHTING) - #glDisable(GL_DEPTH_TEST) + # glDisable(GL_DEPTH_TEST) glBindTexture(GL_TEXTURE_2D, self.texture) - #Load the Data into the Texture - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, self.texDim, self.texDim, 0, GL_RGB, GL_UNSIGNED_BYTE, self.byteImageData ) -# glTexSubImage2Dub( GL_TEXTURE_2D, 0, 0,0, GL_RED, GL_UNSIGNED_BYTE, self.imageData ) + # Load the Data into the Texture + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGB, + self.texDim, + self.texDim, + 0, + GL_RGB, + GL_UNSIGNED_BYTE, + self.byteImageData, + ) + # glTexSubImage2Dub( GL_TEXTURE_2D, 0, 0,0, GL_RED, GL_UNSIGNED_BYTE, self.imageData ) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) - #Define some Parameters for this Texture - + # Define some Parameters for this Texture + glEnable(GL_BLEND) - glBlendFunc(GL_SRC_ALPHA ,GL_ONE_MINUS_SRC_ALPHA) - glColor4f(1.0,1.0,1.0,self.alpha) + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) + glColor4f(1.0, 1.0, 1.0, self.alpha) glBegin(GL_QUADS) glTexCoord2f(0.0, 0.0) - glVertex3f(self.orig[0], self.orig[1], 0.0) # Bottom Left Of The Texture and Quad + glVertex3f( + self.orig[0], self.orig[1], 0.0 + ) # Bottom Left Of The Texture and Quad glTexCoord2f(0.0, self.tyMax) - glVertex3f(self.orig[0]+self.dim[0]*self.size[0], self.orig[1], 0.0)# Bottom Right Of The Texture and Quad + glVertex3f( + self.orig[0] + self.dim[0] * self.size[0], self.orig[1], 0.0 + ) # Bottom Right Of The Texture and Quad glTexCoord2f(self.txMax, self.tyMax) - glVertex3f( self.orig[0]+self.dim[0]*self.size[0], self.orig[1]+self.dim[1]*self.size[1], 0.0) # Top Right Of The Texture and Quad + glVertex3f( + self.orig[0] + self.dim[0] * self.size[0], + self.orig[1] + self.dim[1] * self.size[1], + 0.0, + ) # Top Right Of The Texture and Quad glTexCoord2f(self.txMax, 0.0) - glVertex3f(self.orig[0] , self.orig[1]+self.dim[1]*self.size[1], 0.0) + glVertex3f(self.orig[0], self.orig[1] + self.dim[1] * self.size[1], 0.0) glEnd() glEnable(GL_LIGHTING) - #glEnable(GL_DEPTH_TEST) + # glEnable(GL_DEPTH_TEST) glDisable(GL_BLEND) glDisable(GL_TEXTURE_2D) + class GLPlantSignalRenderer: # Render signals as channels rgb def __init__(self, sim, chanIdx): self.sim = sim self.wallcol = [0, 0, 0] self.nodecol = [0, 0, 0] - self.cellcol = [1, 1, 1] + self.cellcol = [1, 1, 1] self.chanIdx = chanIdx - + def init_gl(self): - pass + pass def renderNames_gl(self): pass @@ -208,39 +236,40 @@ def renderNames_gl(self): def render_gl(self, selection=None): # Render signals[chanIdx] as rgb # - maxSig = [0,0,0] + maxSig = [0, 0, 0] for i in range(len(self.chanIdx)): - for (cid,cellState) in self.sim.cellStates.items(): + for cid, cellState in self.sim.cellStates.items(): s = cellState.signals[self.chanIdx[i]] if s > maxSig[i]: maxSig[i] = s - if maxSig[i]==0: - maxSig[i]=1.0 + if maxSig[i] == 0: + maxSig[i] = 1.0 - for (cid,cellState) in self.sim.cellStates.items(): - col = [0,0,0] + for cid, cellState in self.sim.cellStates.items(): + col = [0, 0, 0] for i in range(len(self.chanIdx)): - col[i] = cellState.signals[self.chanIdx[i]]/maxSig[i] + col[i] = cellState.signals[self.chanIdx[i]] / maxSig[i] glColor3fv(col) glBegin(GL_POLYGON) for p in cellState.nodep: glVertex2d(p[0], p[1]) glEnd() - + + class GLPlantRenderer: def __init__(self, sim): self.sim = sim self.wallcol = [0, 0, 0] self.nodecol = [0, 0, 0] - self.cellcol = [1, 1, 1] - + self.cellcol = [1, 1, 1] + def init_gl(self): - pass + pass def renderNames_gl(self): # Render cell_ids for selection # - for (cid,cellState) in self.sim.cellStates.items(): + for cid, cellState in self.sim.cellStates.items(): glColor3fv(self.cellcol) glPushName(cid) glBegin(GL_POLYGON) @@ -252,32 +281,32 @@ def renderNames_gl(self): def render_gl(self, selection=None): # Render model using PyOpenGL # - # principle axes - #scale=10.0 - #c=cell.get_centre() - #glLineWidth(1) - #glColor3f(1.0,0.0,0.0) #red - #glBegin(GL_LINES) - #glVertex2d(c[0],c[1]) - #glVertex2d(c[0]+cell.pa1[0]*scale,c[1]+cell.pa1[1]*scale) - #glColor3f(0.0,0.0,1.0) #blue - #glVertex2d(c[0],c[1]) - #glVertex2d(c[0]+cell.pa2[0]*scale,c[1]+cell.pa2[1]*scale) - #glEnd() + # principle axes + # scale=10.0 + # c=cell.get_centre() + # glLineWidth(1) + # glColor3f(1.0,0.0,0.0) #red + # glBegin(GL_LINES) + # glVertex2d(c[0],c[1]) + # glVertex2d(c[0]+cell.pa1[0]*scale,c[1]+cell.pa1[1]*scale) + # glColor3f(0.0,0.0,1.0) #blue + # glVertex2d(c[0],c[1]) + # glVertex2d(c[0]+cell.pa2[0]*scale,c[1]+cell.pa2[1]*scale) + # glEnd() glDisable(GL_LIGHTING) glDisable(GL_DEPTH_TEST) cellStates = self.sim.cellStates - #for (cid,cellState) in cellStates.items(): - # cellcol = cellState.color + # for (cid,cellState) in cellStates.items(): + # cellcol = cellState.color # glColor3fv(cellcol) # glBegin(GL_POLYGON) # for p in cellState.nodep: # glVertex2d(p[0], p[1]) # glEnd() - for (cid,cellState) in cellStates.items(): + for cid, cellState in cellStates.items(): col = self.wallcol - for (wp1,wp2) in cellState.wallp: + for wp1, wp2 in cellState.wallp: glColor3fv(col) glLineWidth(2) glBegin(GL_LINES) @@ -285,10 +314,10 @@ def render_gl(self, selection=None): glVertex2d(wp2[0], wp2[1]) glEnd() - if selection>0 and cellStates.has_key(selection): + if selection > 0 and cellStates.has_key(selection): scell = cellStates[selection] - glColor3fv([1,0,0]) - for (wp1,wp2) in scell.wallp: + glColor3fv([1, 0, 0]) + for wp1, wp2 in scell.wallp: glLineWidth(2) glBegin(GL_LINES) glVertex2d(wp1[0], wp1[1]) @@ -296,10 +325,10 @@ def render_gl(self, selection=None): glEnd() # Draw nodes as points - #glColor3fv(self.nodecol) - #glPointSize(3) - - #for node in self.model.nodes: + # glColor3fv(self.nodecol) + # glPointSize(3) + + # for node in self.model.nodes: # p = node.get_pos() # glBegin(GL_POINTS) # glVertex2d(p[0], p[1]) @@ -309,102 +338,99 @@ def render_gl(self, selection=None): # glVertex2d(p[0], p[1]) # glVertex2d(p[0] + math.cos(r), p[1] + math.sin(r)) # glEnd() - + glEnable(GL_LIGHTING) - - - + class GLBacteriumRenderer: - def __init__(self, sim, properties=None, scales = None): - self.ncells_list = 0 - self.ncells_names_list = 0 - self.dlist = None - self.dlist_names = None - self.cellcol = [1, 1, 1] - self.sim = sim - self.quad = gluNewQuadric() - self.properties = properties - self.scales = scales - self.last_rendered_step = -1 - - def init_gl(self): - pass - - #def render_text(self, position, textString, fontSize): - # pygame.font.init() - # font = pygame.font.Font (None, fontSize) - # textSurface = font.render(textString, True, (0,0,0,225), (255,255,255,255)) - # textData = pygame.image.tostring(textSurface, "RGBA", True) - # glRasterPos3d(*position) - # glDrawPixels(textSurface.get_width(), textSurface.get_height(), GL_RGBA, GL_UNSIGNED_BYTE, textData) - - def build_list(self, cells): - if self.dlist: - glDeleteLists(self.dlist, 1) - index = glGenLists(1) - glNewList(index, GL_COMPILE) - self.render_cells() - glEndList() - self.dlist = index - - def build_list_names(self, cells): - if self.dlist_names: - glDeleteLists(self.dlist_names, 1) - index = glGenLists(1) - glNewList(index, GL_COMPILE) - self.render_cell_names() - glEndList() - self.dlist_names = index - - def render_gl(self, selection=None): - cells = self.sim.cellStates.values() - states = self.sim.cellStates.items() + def __init__(self, sim, properties=None, scales=None): + self.ncells_list = 0 + self.ncells_names_list = 0 + self.dlist = None + self.dlist_names = None + self.cellcol = [1, 1, 1] + self.sim = sim + self.quad = gluNewQuadric() + self.properties = properties + self.scales = scales + self.last_rendered_step = -1 + + def init_gl(self): + pass + + # def render_text(self, position, textString, fontSize): + # pygame.font.init() + # font = pygame.font.Font (None, fontSize) + # textSurface = font.render(textString, True, (0,0,0,225), (255,255,255,255)) + # textData = pygame.image.tostring(textSurface, "RGBA", True) + # glRasterPos3d(*position) + # glDrawPixels(textSurface.get_width(), textSurface.get_height(), GL_RGBA, GL_UNSIGNED_BYTE, textData) + + def build_list(self, cells): + if self.dlist: + glDeleteLists(self.dlist, 1) + index = glGenLists(1) + glNewList(index, GL_COMPILE) + self.render_cells() + glEndList() + self.dlist = index + + def build_list_names(self, cells): + if self.dlist_names: + glDeleteLists(self.dlist_names, 1) + index = glGenLists(1) + glNewList(index, GL_COMPILE) + self.render_cell_names() + glEndList() + self.dlist_names = index + + def render_gl(self, selection=None): + cells = self.sim.cellStates.values() + states = self.sim.cellStates.items() # FIXED ============================================================================= - # Before, the renderer would only draw cells when the number of cells changed. - # Now it draws them whenever render_gl is called (by paintGL in PyGLCMViewer.py) - #if len(cells)!=self.ncells_list or len(cells)<500: - # self.build_list(cells) - # self.ncells_list = len(cells) - - #if len(cells)!=self.ncells_list: - if self.last_rendered_step0: - glColor4f(s.signals[0],0,0,1) + if selection != cid: + s = states[cid] + if len(s.signals) > 0: + glColor4f(s.signals[0], 0, 0, 1) else: - glColor4fv(c.color) #c.color[0:3]) + glColor4fv(c.color) # c.color[0:3]) else: - glColor4f(1,0,0,1) - glDrawArrays(GL_TRIANGLES, self.vboOffsets[cid], len(c.tris)*3) - - glDisable(GL_POLYGON_OFFSET_FILL); + glColor4f(1, 0, 0, 1) + glDrawArrays(GL_TRIANGLES, self.vboOffsets[cid], len(c.tris) * 3) + + glDisable(GL_POLYGON_OFFSET_FILL) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) - glColor4f(0,0,0,0.5); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glColor4f(0, 0, 0, 0.5) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) glDrawArrays(GL_TRIANGLES, 0, self.nverts) - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) + self.vbo.unbind() - glDisableClientState(GL_VERTEX_ARRAY); - #glDisableClientState(GL_NORMAL_ARRAY); - + glDisableClientState(GL_VERTEX_ARRAY) + # glDisableClientState(GL_NORMAL_ARRAY); + # glEnable(GL_LIGHTING) - #glDisable(GL_BLEND) #DEPTH_TEST) + # glDisable(GL_BLEND) #DEPTH_TEST) # glDisable(GL_DEPTH_TEST) - + def renderNames_gl(self): if not self.vbo: self.init_gl() - + glDisable(GL_LIGHTING) glDisable(GL_DEPTH_TEST) - #glCullFace(GL_FRONT) + # glCullFace(GL_FRONT) glDisable(GL_CULL_FACE) - + self.vbo.bind() - glEnableClientState(GL_VERTEX_ARRAY); - - glVertexPointer(3, GL_FLOAT, 32, self.vbo ) + glEnableClientState(GL_VERTEX_ARRAY) + + glVertexPointer(3, GL_FLOAT, 32, self.vbo) for c in self.mesh.getCells(): cid = c.getId() glPushName(cid) - glDrawArrays(GL_TRIANGLES, self.vboOffsets[cid], len(c.tris)*3) + glDrawArrays(GL_TRIANGLES, self.vboOffsets[cid], len(c.tris) * 3) glPopName() - + self.vbo.unbind() - glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY) glEnable(GL_LIGHTING) - - class GLCelBacteriumRenderer: def __init__(self, sim, properties=None, scales=None): self.cellcolor = [0.4, 0.6, 0.5] @@ -1403,7 +1444,7 @@ def init_gl(self): glBindTexture(GL_TEXTURE_1D, self.texture) glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) - self.tex_img = [0.2]*(7*3) + [0.6]*(10*3) + [0.9]*(15*3) + self.tex_img = [0.2] * (7 * 3) + [0.6] * (10 * 3) + [0.9] * (15 * 3) glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGB, GL_FLOAT, self.tex_img) glEnable(GL_TEXTURE_1D) glBindTexture(GL_TEXTURE_1D, self.texture) @@ -1420,11 +1461,11 @@ def build_cylinder(self, n_phis): approximate the cylinder. """ index = glGenLists(1) - phis = [float(i)*2.0*numpy.pi/float(n_phis) for i in range(n_phis+1)] + phis = [float(i) * 2.0 * numpy.pi / float(n_phis) for i in range(n_phis + 1)] phi_pairs = zip(phis, phis[1:]) glNewList(index, GL_COMPILE) glBegin(GL_QUADS) - for phi1,phi2 in phi_pairs: + for phi1, phi2 in phi_pairs: dot1 = min(max(numpy.cos(phi1), 0.0), 1.0) dot2 = min(max(numpy.cos(phi2), 0.0), 1.0) glTexCoord1f(dot1) @@ -1448,24 +1489,43 @@ def build_hemisphere(self, n_phis, n_thetas): n_thetas -- Number of longitudes to use. """ index = glGenLists(1) - phis = [float(i)*numpy.pi/float(n_phis/2) for i in range(n_phis/2+1)] + phis = [float(i) * numpy.pi / float(n_phis / 2) for i in range(n_phis / 2 + 1)] phi_pairs = zip(phis, phis[1:]) - thetas = [float(i)*numpy.pi/float(n_thetas) for i in range(-n_thetas/2, n_thetas/2+1)] + thetas = [ + float(i) * numpy.pi / float(n_thetas) + for i in range(-n_thetas / 2, n_thetas / 2 + 1) + ] theta_pairs = zip(thetas, thetas[1:]) glNewList(index, GL_COMPILE) glBegin(GL_QUADS) - for phi1,phi2 in phi_pairs: + for phi1, phi2 in phi_pairs: dot1 = min(max(numpy.cos(phi1), 0.0), 1.0) dot2 = min(max(numpy.cos(phi2), 0.0), 1.0) - for th1,th2 in theta_pairs: + for th1, th2 in theta_pairs: glTexCoord1f(dot1) - glVertex3f(numpy.sin(phi1)*numpy.cos(th1), numpy.sin(phi1)*numpy.sin(th1), numpy.cos(phi1)) + glVertex3f( + numpy.sin(phi1) * numpy.cos(th1), + numpy.sin(phi1) * numpy.sin(th1), + numpy.cos(phi1), + ) glTexCoord1f(dot2) - glVertex3f(numpy.sin(phi2)*numpy.cos(th1), numpy.sin(phi2)*numpy.sin(th1), numpy.cos(phi2)) + glVertex3f( + numpy.sin(phi2) * numpy.cos(th1), + numpy.sin(phi2) * numpy.sin(th1), + numpy.cos(phi2), + ) glTexCoord1f(dot2) - glVertex3f(numpy.sin(phi2)*numpy.cos(th2), numpy.sin(phi2)*numpy.sin(th2), numpy.cos(phi2)) + glVertex3f( + numpy.sin(phi2) * numpy.cos(th2), + numpy.sin(phi2) * numpy.sin(th2), + numpy.cos(phi2), + ) glTexCoord1f(dot1) - glVertex3f(numpy.sin(phi1)*numpy.cos(th2), numpy.sin(phi1)*numpy.sin(th2), numpy.cos(phi1)) + glVertex3f( + numpy.sin(phi1) * numpy.cos(th2), + numpy.sin(phi1) * numpy.sin(th2), + numpy.cos(phi1), + ) glEnd() glEndList() return index @@ -1483,14 +1543,14 @@ def render_capsule(self, l, r): glPopMatrix() # draw +x hemisphere glPushMatrix() - glTranslatef(l/2.0, 0, 0) + glTranslatef(l / 2.0, 0, 0) glScalef(r, r, r) glCallList(self.hemisphere) glPopMatrix() # draw -x hemisphere glPushMatrix() glRotatef(180.0, 0, 0, 1) - glTranslatef(l/2.0, 0, 0) + glTranslatef(l / 2.0, 0, 0) glScalef(r, r, r) glCallList(self.hemisphere) glPopMatrix() @@ -1498,21 +1558,21 @@ def render_capsule(self, l, r): def render_cell(self, cell, selection=None): l = cell.length r = cell.radius - (e1,e2) = map(numpy.array, cell.ends) - ori = (e1+e2)/2.0 # origin in the cell's coordinates + e1, e2 = map(numpy.array, cell.ends) + ori = (e1 + e2) / 2.0 # origin in the cell's coordinates z = numpy.array([0, 0, 1]) - axis = (e2-e1)/l # x axis in the cell's coordinates - rotangle = numpy.arctan2(axis[1], axis[0]) # angle to rotate around the z axis + axis = (e2 - e1) / l # x axis in the cell's coordinates + rotangle = numpy.arctan2(axis[1], axis[0]) # angle to rotate around the z axis glMatrixMode(GL_MODELVIEW) glPushMatrix() # move to the cell's coordinates glTranslatef(ori[0], ori[1], ori[2]) - glRotatef(rotangle*180.0/numpy.pi, z[0], z[1], z[2]) + glRotatef(rotangle * 180.0 / numpy.pi, z[0], z[1], z[2]) # draw the cell in color - color = getattr(cell, 'color', self.cellcolor) + color = getattr(cell, "color", self.cellcolor) glColor3fv(color) self.render_capsule(l, r) @@ -1523,7 +1583,7 @@ def render_cell(self, cell, selection=None): glColor3f(1.0, 0.3, 0.3) glLineWidth(3.0) glEnable(GL_BLEND) - glBlendFunc(GL_SRC_ALPHA ,GL_ONE_MINUS_SRC_ALPHA) + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glEnable(GL_LINE_SMOOTH) # draw wireframe for back facing polygons and cull front-facing ones glPolygonMode(GL_BACK, GL_LINE) @@ -1542,18 +1602,18 @@ def render_cell(self, cell, selection=None): def render_cell_name(self, cell): l = cell.length r = cell.radius - (e1,e2) = map(numpy.array, cell.ends) - ori = (e1+e2)/2.0 # origin in the cell's coordinates + e1, e2 = map(numpy.array, cell.ends) + ori = (e1 + e2) / 2.0 # origin in the cell's coordinates z = numpy.array([0, 0, 1]) - axis = (e2-e1)/l # x axis in the cell's coordinates - rotangle = numpy.arctan2(axis[1], axis[0]) # angle to rotate around the z axis + axis = (e2 - e1) / l # x axis in the cell's coordinates + rotangle = numpy.arctan2(axis[1], axis[0]) # angle to rotate around the z axis glMatrixMode(GL_MODELVIEW) glPushMatrix() # move to the cell's coordinates glTranslatef(ori[0], ori[1], ori[2]) - glRotatef(rotangle*180.0/numpy.pi, z[0], z[1], z[2]) + glRotatef(rotangle * 180.0 / numpy.pi, z[0], z[1], z[2]) # draw the cell in color glPushName(cell.id) @@ -1562,19 +1622,15 @@ def render_cell_name(self, cell): glPopMatrix() - def render_gl(self, selection=None): cells = self.sim.cellStates.values() - for cell in cells: self.render_cell(cell, selection) + for cell in cells: + self.render_cell(cell, selection) def renderNames_gl(self, selection=None): cells = self.sim.cellStates.values() - for cell in cells: self.render_cell_name(cell) - - - - - + for cell in cells: + self.render_cell_name(cell) class GL2DBacteriumRenderer: @@ -1588,15 +1644,17 @@ def __init__(self, sim, properties=None, scales=None): self.properties = properties self.scales = scales self.cellcolor = [0.4, 0.6, 0.5] - self.circ_pts = [(math.cos(math.radians(th)), math.sin(math.radians(th))) for th in range(-80,90,20)] + self.circ_pts = [ + (math.cos(math.radians(th)), math.sin(math.radians(th))) + for th in range(-80, 90, 20) + ] self.semi = self.build_semicircle() - def build_semicircle(self): index = glGenLists(1) glNewList(index, GL_COMPILE) glVertex3f(0.5, -1, 0) - for x,y in self.circ_pts: + for x, y in self.circ_pts: glVertex3f(0.5 + x, y, 0.0) glVertex3f(0.5, 1, 0) glEndList() @@ -1605,18 +1663,18 @@ def build_semicircle(self): def draw_cell(self, p, d, l, r): glMatrixMode(GL_MODELVIEW) glPushMatrix() - ang = math.atan2(d[1], d[0]) * 360.0 / (2.0*3.141593) + ang = math.atan2(d[1], d[0]) * 360.0 / (2.0 * 3.141593) glTranslatef(p[0], p[1], 0.0) glRotatef(ang, 0.0, 0.0, 1.0) glBegin(GL_POLYGON) - glVertex3f(-l/2.0, -r, 0) - glVertex3f(l/2.0, -r, 0) - for x,y in self.circ_pts: - glVertex3f(l/2.0 + x*r, y*r, 0.0) - glVertex3f(l/2.0, r, 0) - glVertex3f(-l/2.0, r, 0) - for x,y in self.circ_pts: - glVertex3f(-l/2.0 -x*r, -y*r, 0.0) + glVertex3f(-l / 2.0, -r, 0) + glVertex3f(l / 2.0, -r, 0) + for x, y in self.circ_pts: + glVertex3f(l / 2.0 + x * r, y * r, 0.0) + glVertex3f(l / 2.0, r, 0) + glVertex3f(-l / 2.0, r, 0) + for x, y in self.circ_pts: + glVertex3f(-l / 2.0 - x * r, -y * r, 0.0) glEnd() glPopMatrix() @@ -1625,7 +1683,8 @@ def build_list(self, cells): glDeleteLists(self.dlist, 1) index = glGenLists(1) glNewList(index, GL_COMPILE) - for cell in cells: self.render_cell(cell) + for cell in cells: + self.render_cell(cell) glEndList() self.dlist = index @@ -1634,12 +1693,13 @@ def build_list_names(self, cells): glDeleteLists(self.dlist_names, 1) index = glGenLists(1) glNewList(index, GL_COMPILE) - for cell in cells: self.render_cell_name(cell) + for cell in cells: + self.render_cell_name(cell) glEndList() self.dlist_names = index def render_cell(self, cell, selection=None): - p,d,l,r = (cell.pos, cell.dir, cell.length, cell.radius) + p, d, l, r = (cell.pos, cell.dir, cell.length, cell.radius) glMatrixMode(GL_MODELVIEW) glEnable(GL_DEPTH_TEST) glPushMatrix() @@ -1649,23 +1709,21 @@ def render_cell(self, cell, selection=None): glColor3f(0.2, 0.1, 0.8) glTranslatef(0.0, 0.0, 0.025) self.draw_cell(p, d, l, r) - color = getattr(cell, 'color', [0.4, 0.4, 0.4]) + color = getattr(cell, "color", [0.4, 0.4, 0.4]) glColor3fv(color) glTranslatef(0.0, 0.0, 0.025) - self.draw_cell(p, d, l, r-0.15) + self.draw_cell(p, d, l, r - 0.15) glPopMatrix() glDisable(GL_DEPTH_TEST) - def render_cell_name(self, cell, selection=None): - p,d,l,r = (cell.pos, cell.dir, cell.length, cell.radius) + p, d, l, r = (cell.pos, cell.dir, cell.length, cell.radius) glPushName(cell.id) glEnable(GL_DEPTH_TEST) self.draw_cell(p, d, l, r) glPopName() glDisable(GL_DEPTH_TEST) - def render_gl(self, selection=None): glDisable(GL_LIGHTING) glEnable(GL_POLYGON_SMOOTH) @@ -1673,20 +1731,16 @@ def render_gl(self, selection=None): glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) cells = self.sim.cellStates.values() - #if len(cells)!=self.ncells_list: + # if len(cells)!=self.ncells_list: self.build_list(cells) - #self.ncells_list = len(cells) + # self.ncells_list = len(cells) glCallList(self.dlist) - #for cell in cells: self.render_cell(cell, selection) - + # for cell in cells: self.render_cell(cell, selection) def renderNames_gl(self, selection=None): cells = self.sim.cellStates.values() - if len(cells)!=self.ncells_names_list: + if len(cells) != self.ncells_names_list: self.build_list_names(cells) self.ncells_names_list = len(cells) glCallList(self.dlist_names) - #for cell in cells: self.render_cell_name(cell, selection) - - - + # for cell in cells: self.render_cell_name(cell, selection) diff --git a/cellmodeller/regulation/SBMLImport.py b/cellmodeller/regulation/SBMLImport.py index c0a10a3f..4f5ed85a 100644 --- a/cellmodeller/regulation/SBMLImport.py +++ b/cellmodeller/regulation/SBMLImport.py @@ -1,22 +1,21 @@ -from libsbml import * +from libsbml import * import math import new import urllib.request, urllib.error, urllib.parse - # indicates whether we should perform SBML document consistency check. -# suppressed by default because the MSR SBML library does not produce valid SBML. +# suppressed by default because the MSR SBML library does not produce valid SBML. suppressConsistencyCheck = True # get the array index of given species ID: def getSpecIndex(specIdToArrayIndexDict, specId): if specId not in specIdToArrayIndexDict: - specIdToArrayIndexDict[specId] = len(list(specIdToArrayIndexDict.keys())) - return specIdToArrayIndexDict[specId] + specIdToArrayIndexDict[specId] = len(list(specIdToArrayIndexDict.keys())) + return specIdToArrayIndexDict[specId] -# get python variable name for the ODE of given species ID: +# get python variable name for the ODE of given species ID: def specOdeNameFromId(specId): return "d_" + specId @@ -26,20 +25,26 @@ def specOdeNameFromId(specId): def checkSBMLConsistency(document): if suppressConsistencyCheck: return - + numFailures = document.checkInternalConsistency() if numFailures > 0: failureMsg = "" for failureNum in range(numFailures): - print("Failure " + str(failureNum) + ": " + document.getError(failureNum).getShortMessage() + "\n") + print( + "Failure " + + str(failureNum) + + ": " + + document.getError(failureNum).getShortMessage() + + "\n" + ) raise Exception(failureMsg) - - + + # load SBML model from given file. -def SBMLModelFromSBMLFile(sbmlFile): - reader = SBMLReader() +def SBMLModelFromSBMLFile(sbmlFile): + reader = SBMLReader() document = reader.readSBML(sbmlFile) - if document.getNumErrors()>0: + if document.getNumErrors() > 0: print("Errors in reading SBML file...") checkSBMLConsistency(document) model = document.getModel() @@ -50,20 +55,20 @@ def SBMLModelFromSBMLFile(sbmlFile): # load SBML model form given string. def SBMLModelFromSBMLStr(sbmlStr): - - # would be nice if SBMLReader.readSBMLFromStr worked - but it does not, + + # would be nice if SBMLReader.readSBMLFromStr worked - but it does not, # there seems to be some SWIG fuck-up. so we are forced to first write - # to temporary file: - file = open("tmp.sbml", 'w') - file.write(sbmlStr) - file.close() - + # to temporary file: + file = open("tmp.sbml", "w") + file.write(sbmlStr) + file.close() + # then read from file: - reader = SBMLReader() + reader = SBMLReader() document = reader.readSBML("tmp.sbml") - checkSBMLConsistency(document) + checkSBMLConsistency(document) model = document.getModel() - + return model @@ -76,82 +81,96 @@ def splitBinary(astNode, operand, kineticLaw, model): # constructs a python string representing the math expresson in an AST node. -# currently only covers basic cases, and not all the ASTNode types; an +# currently only covers basic cases, and not all the ASTNode types; an # exception is thrown if an unsupported type is encountered. # more types can easily be added. def pythonMathFromASTNode(astNode, kineticLaw, model): - if (astNode.getType() == AST_PLUS): + if astNode.getType() == AST_PLUS: return splitBinary(astNode, "+", kineticLaw, model) - - elif (astNode.getType() == AST_MINUS): + + elif astNode.getType() == AST_MINUS: return splitBinary(astNode, "-", kineticLaw, model) - elif (astNode.getType() == AST_DIVIDE): + elif astNode.getType() == AST_DIVIDE: return splitBinary(astNode, "/", kineticLaw, model) - - elif (astNode.getType() == AST_TIMES): - return splitBinary(astNode, "*", kineticLaw, model) - - elif (astNode.getType() == AST_FUNCTION_POWER): - return splitBinary(astNode, "**", kineticLaw, model) + + elif astNode.getType() == AST_TIMES: + return splitBinary(astNode, "*", kineticLaw, model) + + elif astNode.getType() == AST_FUNCTION_POWER: + return splitBinary(astNode, "**", kineticLaw, model) elif astNode.isNumber(): if astNode.isReal(): return str(astNode.getReal()) elif astNode.isInteger(): - return str(astNode.getInteger()) - + return str(astNode.getInteger()) + elif astNode.isName(): # check if this name is a defined parameter. can't see any way of distinguishing between # parameters and species identifiers, other than checking for definition this way? nodeName = astNode.getName() parameterLocal = kineticLaw.getParameter(nodeName) - parameterGlobal = model.getParameter(nodeName) + parameterGlobal = model.getParameter(nodeName) if parameterLocal != None: - val = str(parameterLocal.getValue()) + val = str(parameterLocal.getValue()) return val elif parameterGlobal != None: val = str(parameterGlobal.getValue()) return val - - # if not parameter, then check if this is a species id: - elif model.getSpecies(nodeName) != None: + + # if not parameter, then check if this is a species id: + elif model.getSpecies(nodeName) != None: return nodeName - + # something weird -- return 1 and issue warning: else: - print("WARNING: unknown identifier " + nodeName + ", defaulting to 1. Globals: " + str(model.getNumParameters()) + ". Locals: " + str(kineticLaw.getNumParameters())) + print( + "WARNING: unknown identifier " + + nodeName + + ", defaulting to 1. Globals: " + + str(model.getNumParameters()) + + ". Locals: " + + str(kineticLaw.getNumParameters()) + ) return "1" - - else: - raise Exception("Un-supported AST node type: " + str(astNode.isName()) + ", node: " + str(astNode.getType())) - + + else: + raise Exception( + "Un-supported AST node type: " + + str(astNode.isName()) + + ", node: " + + str(astNode.getType()) + ) + # constructs a python program string from given SBML model. def pythonStrFromSBMLModel(model): - # initialise dictionaries and python code string: - specIdToArrayIndexDict = {} + # initialise dictionaries and python code string: + specIdToArrayIndexDict = {} specIdToExpDict = {} - + # define indentation for python code: indent = " " - indent2 = indent + indent - + indent2 = indent + indent + # iterate over reactions: for reactionNum in range(model.getNumReactions()): - + reaction = model.getReaction(reactionNum) - - # compute rate expression. + + # compute rate expression. # UPDATE: first tried to use the formulaToString libSBML function, # which should have worked in most cases. but it doesn't substitute - # in defined parameters. hence we use our own ASTNode parsing function. - #mathAstNode = reaction.getKineticLaw().getMath() - #pythonRateExp = "(" + formulaToString(mathAstNode) + ")" - #pythonRateExp = reaction.getKineticLaw().getFormula() - pythonRateExp = pythonMathFromASTNode(reaction.getKineticLaw().getMath(), reaction.getKineticLaw(), model) - + # in defined parameters. hence we use our own ASTNode parsing function. + # mathAstNode = reaction.getKineticLaw().getMath() + # pythonRateExp = "(" + formulaToString(mathAstNode) + ")" + # pythonRateExp = reaction.getKineticLaw().getFormula() + pythonRateExp = pythonMathFromASTNode( + reaction.getKineticLaw().getMath(), reaction.getKineticLaw(), model + ) + """ # iterate over reactants to create mass-action rate expression: # UPDATE: don't assume mass-action, just read the rate expression literally. @@ -171,95 +190,101 @@ def pythonStrFromSBMLModel(model): else: pythonRateExp += "*" + reactantSpecId + "^" + str(stoich) """ - - # iterate over reactants and update ODE for each: + + # iterate over reactants and update ODE for each: for reactantNum in range(reaction.getNumReactants()): reactantSpecRef = reaction.getReactant(reactantNum) stoich = reactantSpecRef.getStoichiometry() - + # for some reason stoichiometry is sometimes NaN: if math.isnan(stoich): stoich = 1 - - reactantSpecId = reactantSpecRef.getSpecies() - - # add key to hash table if it doesn't exist: - if reactantSpecId not in specIdToExpDict: + + reactantSpecId = reactantSpecRef.getSpecies() + + # add key to hash table if it doesn't exist: + if reactantSpecId not in specIdToExpDict: specIdToExpDict[reactantSpecId] = "" - + if stoich == 1: specIdToExpDict[reactantSpecId] += " - " + pythonRateExp else: - specIdToExpDict[reactantSpecId] += " - " + str(stoich) + "*" + pythonRateExp - - # do the same for products: + specIdToExpDict[reactantSpecId] += ( + " - " + str(stoich) + "*" + pythonRateExp + ) + + # do the same for products: for productNum in range(reaction.getNumProducts()): productSpecRef = reaction.getProduct(productNum) stoich = productSpecRef.getStoichiometry() - + # for some reason stoichiometry is sometimes NaN: if math.isnan(stoich): stoich = 1 - - productSpecId = productSpecRef.getSpecies() - - # add key to hash table if it doesn't exist: - if productSpecId not in specIdToExpDict: - specIdToExpDict[productSpecId] = "" - + + productSpecId = productSpecRef.getSpecies() + + # add key to hash table if it doesn't exist: + if productSpecId not in specIdToExpDict: + specIdToExpDict[productSpecId] = "" + if stoich == 1: - specIdToExpDict[productSpecId] += " + " + pythonRateExp + specIdToExpDict[productSpecId] += " + " + pythonRateExp else: - specIdToExpDict[productSpecId] += " + " + str(stoich) + "*" + pythonRateExp - + specIdToExpDict[productSpecId] += ( + " + " + str(stoich) + "*" + pythonRateExp + ) + # create python variable definitions, python updated rate definitions, # and a list of species IDs in the relevant order. pythonVarDefs = "" - pythonRateUpdateExps = "" - specIdLst = [0]*len(specIdToExpDict) + pythonRateUpdateExps = "" + specIdLst = [0] * len(specIdToExpDict) for specId in list(specIdToExpDict.keys()): # get index into species array: index = getSpecIndex(specIdToArrayIndexDict, specId) - + # create python variable definition: - pythonVarDefs += indent + indent + specId + " = cell.species[" + str(index) + "]\n" + pythonVarDefs += ( + indent + indent + specId + " = cell.species[" + str(index) + "]\n" + ) # create python rate update expression: exp = specIdToExpDict[specId] varname = specOdeNameFromId(specId) pythonRateUpdateExps += indent2 + varname + " = " + exp + "\n" - + # insert spec id into correct position in list: - specIdLst[index] = specId #.insert(index, specId) - + specIdLst[index] = specId # .insert(index, specId) + # create a python list with updated rate expressions, - # and python lists with with species IDs and names in the relevant order. - pythonRateUpdateLst = "" + # and python lists with with species IDs and names in the relevant order. + pythonRateUpdateLst = "" pythonSpecIDLst = "" pythonSpecNameLst = "" for specId in specIdLst: - - # get species name from model: + + # get species name from model: specName = model.getSpecies(specId).getName() if specName == None: - specName = "Undefined" - + specName = "Undefined" + if pythonRateUpdateLst == "": pythonRateUpdateLst += "[" + specOdeNameFromId(specId) - pythonSpecIDLst += "[\"" + specId + "\"" - pythonSpecNameLst += "[\"" + specName + "\"" + pythonSpecIDLst += '["' + specId + '"' + pythonSpecNameLst += '["' + specName + '"' else: pythonRateUpdateLst += ", " + specOdeNameFromId(specId) - pythonSpecIDLst += ", \"" + specId + "\"" - pythonSpecNameLst += ", \"" + specName + "\"" - + pythonSpecIDLst += ', "' + specId + '"' + pythonSpecNameLst += ', "' + specName + '"' + pythonRateUpdateLst += "]" pythonSpecIDLst += "]" - pythonSpecNameLst += "]" - + pythonSpecNameLst += "]" + # build initial population list: - initPopLst = [0]*model.getNumSpecies() - for specId in specIdLst: + initPopLst = [0] * model.getNumSpecies() + for specId in specIdLst: sbmlSpec = model.getSpecies(specId) initAmount = sbmlSpec.getInitialAmount() initConc = sbmlSpec.getInitialConcentration() @@ -268,10 +293,10 @@ def pythonStrFromSBMLModel(model): init = initAmount elif not math.isnan(initConc) and initConc > 0: init = initConc - - index = getSpecIndex(specIdToArrayIndexDict, specId) + + index = getSpecIndex(specIdToArrayIndexDict, specId) initPopLst[index] = init - + # build initial population python string: pythonInitPopLst = "" for init in initPopLst: @@ -279,44 +304,47 @@ def pythonStrFromSBMLModel(model): pythonInitPopLst += "[" + str(init) else: pythonInitPopLst += "," + str(init) - - pythonInitPopLst += "]" - - # compose the complete python program string. + + pythonInitPopLst += "]" + + # compose the complete python program string. pythonStr = "" pythonStr += "def getRates(cells):\n" pythonStr += indent + "df = []\n" - pythonStr += indent + "for cell in cells:\n" + pythonStr += indent + "for cell in cells:\n" pythonStr += pythonVarDefs + "\n" pythonStr += pythonRateUpdateExps + "\n" - pythonStr += indent2 + "df.append(" + pythonRateUpdateLst + ")\n" - pythonStr += indent + "return df" + pythonStr += indent2 + "df.append(" + pythonRateUpdateLst + ")\n" + pythonStr += indent + "return df" pythonStr += "\n\n" pythonStr += "specIdLst = " + pythonSpecIDLst + "\n\n" pythonStr += "specNameLst = " + pythonSpecNameLst + "\n\n" pythonStr += "specInitPopLst = " + pythonInitPopLst + "\n\n" - + return pythonStr - -# create python module from code dynamically. + +# create python module from code dynamically. def pythonModuleFromPythonStr(pythonStr): module = new.module("sbmlPythonEncoding") exec(pythonStr, module.__dict__) - return module + return module -# get text from given channel. +# get text from given channel. def TextFromChannel(channelName): - f = urllib.request.urlopen('http://async-message-passer.appspot.com/?content_only=1&channel_name=' + channelName) - return f.read() + f = urllib.request.urlopen( + "http://async-message-passer.appspot.com/?content_only=1&channel_name=" + + channelName + ) + return f.read() def pythonModuleFromFile(fileName): - reader = SBMLReader() + reader = SBMLReader() document = reader.readSBML(fileName) - checkSBMLConsistency(document) - model = document.getModel() + checkSBMLConsistency(document) + model = document.getModel() pstr = pythonStrFromSBMLModel(model) print("Got python str: " + pstr) pythonModule = pythonModuleFromPythonStr(pstr) @@ -327,29 +355,28 @@ def pythonModuleFromFile(fileName): def pythonModuleFromChannel(channelName): sbmlStr = TextFromChannel(channelName) - #print "Got channel text:\n" + sbmlStr - + # print "Got channel text:\n" + sbmlStr + # 1) an apparent segmentation issue in libsbml means that we cannot # invoke SBMLModelFromSBMLStr() defined above. great. so we inline it below: - # 2) would be nice if SBMLReader.readSBMLFromStr worked - but it does not, + # 2) would be nice if SBMLReader.readSBMLFromStr worked - but it does not, # there seems to be some SWIG fuck-up. so we are forced to first write # to temporary file: - file = open("tmp.sbml", 'w') - file.write(sbmlStr) - file.close() - reader = SBMLReader() + file = open("tmp.sbml", "w") + file.write(sbmlStr) + file.close() + reader = SBMLReader() document = reader.readSBML("tmp.sbml") - checkSBMLConsistency(document) - model = document.getModel() - - + checkSBMLConsistency(document) + model = document.getModel() + pythonStr = pythonStrFromSBMLModel(model) print("Got python str: " + pythonStr) pythonModule = pythonModuleFromPythonStr(pythonStr) return pythonModule -# example usage: -#sbmlFile = "/Users/michaeldavidpedersen/tmp/testsbml.sbml" -#print sbmlToPython(sbmlFile) -#module = pythonModuleFromChannel("DEFAULT_CHANNEL") +# example usage: +# sbmlFile = "/Users/michaeldavidpedersen/tmp/testsbml.sbml" +# print sbmlToPython(sbmlFile) +# module = pythonModuleFromChannel("DEFAULT_CHANNEL") diff --git a/cellmodeller/regulation/module_regulator.py b/cellmodeller/regulation/module_regulator.py index fe483924..bb976454 100644 --- a/cellmodeller/regulation/module_regulator.py +++ b/cellmodeller/regulation/module_regulator.py @@ -2,6 +2,7 @@ import os.path import sys + class ModuleRegulator: def __init__(self, sim, biophys=None, signalling=None): self.modName = sim.moduleName @@ -12,7 +13,7 @@ def __init__(self, sim, biophys=None, signalling=None): self.signal = signalling # Simulator is responsible for loading the model as a python module # This class uses the module imported by Simulator - self.module = sim.module + self.module = sim.module def addCell(self, cellState, **kwargs): self.module.init(cellState, **kwargs) @@ -31,7 +32,7 @@ def sigRateCL(self): def specRateCL(self): return self.module.specRateCL() - + def signalRates(self, cstate, speciesLevels, signalLevels): return self.module.signalRates(cstate, speciesLevels, signalLevels) @@ -42,7 +43,7 @@ def initSpeciesLevels(self, levels): csv = list(self.cellStates.values()) nCells = len(csv) for i in range(nCells): - levels[i,:] = csv[i].species + levels[i, :] = csv[i].species def step(self, dt=0): try: @@ -56,5 +57,3 @@ def divide(self, pState, d1State, d2State): divfunc = getattr(self.module, "divide", None) if callable(divfunc): divfunc(pState, d1State, d2State) - - diff --git a/cellmodeller/simulator.py b/cellmodeller/simulator.py index 4f777b18..41b13ad7 100644 --- a/cellmodeller/simulator.py +++ b/cellmodeller/simulator.py @@ -10,36 +10,39 @@ import configparser import importlib + class Simulator: """ -This class is in charge of running the simulation, creating the various models -and stepping them forward in time. It is the control interface for the gui -or script that is running the simulation. - -Stores a map from cell_id to CellState, which stores the current simulation -state of each cell. - -Constructed on a user-defined python file. This file implements a -function setup(Simulator, Gui) that constructs the requiredx modules -(Regulator, Signalling, Integrator), and calls Simulator.init(). It -can also create Renderers and add them by calling -Simulator.addRenderer(renderer) so that the simulation can be -visualised. -""" + This class is in charge of running the simulation, creating the various models + and stepping them forward in time. It is the control interface for the gui + or script that is running the simulation. + + Stores a map from cell_id to CellState, which stores the current simulation + state of each cell. + + Constructed on a user-defined python file. This file implements a + function setup(Simulator, Gui) that constructs the requiredx modules + (Regulator, Signalling, Integrator), and calls Simulator.init(). It + can also create Renderers and add them by calling + Simulator.addRenderer(renderer) so that the simulation can be + visualised. + """ ## Construct an empty simulator object. This object will not be able to # do anything yet unti we use 'init' method to specify the models for # physical interaction, genetic circuit, diffusion and integrator. - def __init__(self, \ - moduleName, \ - dt, \ - pickleSteps=50, \ - outputDirName=None, \ - moduleStr=None, \ - saveOutput=False, \ - clPlatformNum=0, \ - clDeviceNum=0, \ - is_gui=False): + def __init__( + self, + moduleName, + dt, + pickleSteps=50, + outputDirName=None, + moduleStr=None, + saveOutput=False, + clPlatformNum=0, + clDeviceNum=0, + is_gui=False, + ): # Is this simulator running in a gui? self.is_gui = is_gui @@ -64,50 +67,51 @@ def __init__(self, \ self.dt = dt if "CMPATH" in os.environ: - self.cfg_file = os.path.join(os.environ["CMPATH"], 'CMconfig.cfg') + self.cfg_file = os.path.join(os.environ["CMPATH"], "CMconfig.cfg") else: - self.cfg_file = 'cellmodeller/CMconfig.cfg' + self.cfg_file = "cellmodeller/CMconfig.cfg" if not self.init_cl(platnum=clPlatformNum, devnum=clDeviceNum): print("Couldn't initialise OpenCL context") return # Two ways to specify a module (model): - self.moduleName = moduleName # Import via standard python - self.moduleStr = moduleStr # Import stored python code string (from a pickle usually) + self.moduleName = moduleName # Import via standard python + self.moduleStr = ( + moduleStr # Import stored python code string (from a pickle usually) + ) if self.moduleStr: - print("Importing model %s from string"%(self.moduleName)) + print("Importing model %s from string" % (self.moduleName)) module_spec = importlib.util.spec_from_loader(moduleName, loader=None) self.module = importlib.util.module_from_spec(module_spec) exec(moduleStr, self.module.__dict__) else: # In case the moduleName is a path to a python file: # Get path and file name - (path,name) = os.path.split(self.moduleName) + path, name = os.path.split(self.moduleName) # Append path to PYTHONPATH, if no path do nothing if path: if path not in sys.path: sys.path.append(path) # Remove .py extension if present - self.moduleName = str(name).split('.')[0] - print("Importing model %s"%(self.moduleName)) + self.moduleName = str(name).split(".")[0] + print("Importing model %s" % (self.moduleName)) if self.moduleName in sys.modules: self.module = sys.modules[self.moduleName] importlib.reload(self.module) else: self.module = __import__(self.moduleName, globals(), locals(), [], 0) - # TJR: What is this invar thing? I have never seen this used... - #setup the simulation here: - #if invar: + # setup the simulation here: + # if invar: # self.module.setup(self, invar) - #else: + # else: # Set up the data output directory - self.dataOutputInitialised=False + self.dataOutputInitialised = False self.outputDirName = outputDirName self.setSaveOutput(saveOutput) - + # Call the user-defined setup function on ourself self.module.setup(self) @@ -118,32 +122,38 @@ def setSaveOutput(self, save): def init_data_output(self): import time + startTime = time.localtime() - outputFileRoot = self.outputDirName if self.outputDirName else self.moduleName + '-' + time.strftime('%y-%m-%d-%H-%M', startTime) - self.outputDirPath = os.path.join('data', outputFileRoot) - if 'CMPATH' in os.environ: + outputFileRoot = ( + self.outputDirName + if self.outputDirName + else self.moduleName + "-" + time.strftime("%y-%m-%d-%H-%M", startTime) + ) + self.outputDirPath = os.path.join("data", outputFileRoot) + if "CMPATH" in os.environ: self.outputDirPath = os.path.join(os.environ["CMPATH"], self.outputDirPath) - # Add a number to end of dir name if it already exists + # Add a number to end of dir name if it already exists label = 2 while os.path.exists(self.outputDirPath): - if label>2: - self.outputDirPath = self.outputDirPath[:-2]+"_"+str(label) + if label > 2: + self.outputDirPath = self.outputDirPath[:-2] + "_" + str(label) else: - self.outputDirPath = self.outputDirPath+"_"+str(label) - label+=1 + self.outputDirPath = self.outputDirPath + "_" + str(label) + label += 1 os.mkdir(self.outputDirPath) - # write a copy of the model into the dir (for reference), + # write a copy of the model into the dir (for reference), # this goes in the pickle too (and gets loaded when a pickle is loaded) if self.moduleStr: self.moduleOutput = self.moduleStr else: self.moduleOutput = inspect.getsource(self.module) - open(os.path.join(self.outputDirPath, self.moduleName), 'w').write(self.moduleOutput) - - self.dataOutputInitialised=True + open(os.path.join(self.outputDirPath, self.moduleName), "w").write( + self.moduleOutput + ) + self.dataOutputInitialised = True ## Get an id for the next cell to be created def next_id(self): @@ -157,7 +167,6 @@ def next_idx(self): self._next_idx += 1 return idx - # Currently, the user-defined regulation module creates the # biophysics, regulation, and signalling objects in a function # setup(). @@ -190,69 +199,72 @@ def init(self, phys, reg, sig, integ): self.integ.setSignalling(sig) self.reg.setSignalling(sig) - ## Set up the OpenCL context, the configuration is set up the first time, and is saved in the config file def init_cl(self, platnum, devnum): # Check that specified platform exists platforms = cl.get_platforms() - if len(platforms)<=platnum: + if len(platforms) <= platnum: print("Specified OpenCL platform number (%d) does not exist.") print("Options are:") for p in range(len(platforms)): - print("%d: %s"%(p, str(platforms[p]))) + print("%d: %s" % (p, str(platforms[p]))) return False else: platform = platforms[platnum] # Check that specified device exists on that platform devices = platforms[platnum].get_devices() - if len(devices)<=devnum: - print("Specified OpenCL device number (%d) does not exist on platform %s."%(devnum,platform)) + if len(devices) <= devnum: + print( + "Specified OpenCL device number (%d) does not exist on platform %s." + % (devnum, platform) + ) print("Options are:") for d in range(len(devices)): - print("%d: %s"%(d, str(devices[d]))) + print("%d: %s" % (d, str(devices[d]))) return False else: device = devices[devnum] # Create a context and queue - self.CLContext = cl.Context(properties=[(cl.context_properties.PLATFORM, platform)], - devices=[device]) + self.CLContext = cl.Context( + properties=[(cl.context_properties.PLATFORM, platform)], devices=[device] + ) self.CLQueue = cl.CommandQueue(self.CLContext) print("Set up OpenCL context:") - print(" Platform: %s"%(str(platform.name))) - print(" Device: %s"%(str(device.name))) + print(" Platform: %s" % (str(platform.name))) + print(" Device: %s" % (str(device.name))) return True - - ## Get the OpenCL context and queue for running kernels + + ## Get the OpenCL context and queue for running kernels def getOpenCL(self): return (self.CLContext, self.CLQueue) ## set cell states from a given dict def setCellStates(self, cellStates): - #Set cell states, e.g. from pickle file - #this sets them on the card too + # Set cell states, e.g. from pickle file + # this sets them on the card too self.cellStates = {} self.cellStates = cellStates idx_map = {} id_map = {} idmax = 0 - for id,state in cellStates.items(): + for id, state in cellStates.items(): idx_map[state.id] = state.idx id_map[state.idx] = state.id - if id>idmax: - idmax=id + if id > idmax: + idmax = id self.idToIdx = idx_map self.idxToId = id_map - self._next_id = idmax+1 + self._next_id = idmax + 1 self._next_idx = len(cellStates) self.reg.cellStates = cellStates self.phys.load_from_cellstates(cellStates) - + ## Add a graphics renderer - this should not be here --> GUI def addRenderer(self, renderer): self.renderers.append(renderer) - + ## Reset the simulation back to initial conditions def reset(self): # Delete existing models @@ -265,8 +277,8 @@ def reset(self): if self.reg: del self.reg - if not self.moduleStr: - #This will take up any changes made in the model file + if not self.moduleStr: + # This will take up any changes made in the model file importlib.reload(self.module) else: # TJR: Module loaded from pickle, cannot reset? @@ -277,7 +289,6 @@ def reset(self): # Recreate models via module setup self.module.setup(self) - # Divide a cell to two daughter cells def divide(self, pState): pState.divideFlag = False @@ -289,13 +300,13 @@ def divide(self, pState): d1State.id = d1id d2State.id = d2id - #reset cell ages + # reset cell ages d1State.cellAge = 0 d2State.cellAge = 0 - #inherit effGrowth + # inherit effGrowth d1State.effGrowth = pState.effGrowth d2State.effGrowth = pState.effGrowth - + self.lineage[d1id] = pid self.lineage[d2id] = pid @@ -314,7 +325,7 @@ def divide(self, pState): del self.idToIdx[pid] # Divide the cell in each model - asymm = getattr(pState, 'asymm', [1, 1]) + asymm = getattr(pState, "asymm", [1, 1]) self.phys.divide(pState, d1State, d2State, f1=asymm[0], f2=asymm[1]) if self.integ: self.integ.divide(pState, d1State, d2State) @@ -338,7 +349,7 @@ def addCell(self, cellType=0, cellAdh=0, length=3.5, **kwargs): self.sig.addCell(cs) self.phys.addCell(cs, **kwargs) - #--- + # --- # Some functions to modify existing cells (e.g. from GUI) # Eventually prob better to have a generic editCell() that deals with this stuff # @@ -351,78 +362,79 @@ def moveCell(self, cid, delta_pos): def step(self): self.reg.step(self.dt) states = dict(self.cellStates) - for (cid,state) in list(states.items()): + for cid, state in list(states.items()): state.time = self.stepNum * self.dt if state.divideFlag: - self.divide(state) #neighbours no longer current + self.divide(state) # neighbours no longer current self.phys.set_cells() - while not self.phys.step(self.dt): #neighbours are current here + while not self.phys.step(self.dt): # neighbours are current here pass if self.sig: self.sig.step(self.dt) if self.integ: self.integ.step(self.dt) - if self.saveOutput and self.stepNum%self.pickleSteps==0: + if self.saveOutput and self.stepNum % self.pickleSteps == 0: self.writePickle() self.stepNum += 1 return True - ## Import cells to the simulator from csv file. The file contains a list of 7-coordinates {pos,dir,len} (comma delimited) of each cell - also, there should be no cells around - ie run this from an empty model instead of addcell def importCells_file(self, filename): - f=open(filename, 'rU') - list=csv.reader(f,delimiter=',') + f = open(filename, "rU") + list = csv.reader(f, delimiter=",") for row in list: - cpos = [float(row[0]),float(row[1]),float(row[2])] - cdir = [float(row[3]),float(row[4]),float(row[5])] - cell_len = float(row[6]) #radius should be removed from this in the analysis - ndir = cdir/numpy.linalg.norm(cdir) #normalize cell dir just in case - #this should probably also check for overlaps + cpos = [float(row[0]), float(row[1]), float(row[2])] + cdir = [float(row[3]), float(row[4]), float(row[5])] + cell_len = float( + row[6] + ) # radius should be removed from this in the analysis + ndir = cdir / numpy.linalg.norm(cdir) # normalize cell dir just in case + # this should probably also check for overlaps self.addCell(pos=tuple(cpos), dir=tuple(ndir), length=cell_len) ## Write current simulation state to an output file def writePickle(self, csv=False): - filename = os.path.join(self.outputDirPath, 'step-%05i.pickle' % self.stepNum) - outfile = open(filename, 'wb') + filename = os.path.join(self.outputDirPath, "step-%05i.pickle" % self.stepNum) + outfile = open(filename, "wb") data = {} - data['cellStates'] = self.cellStates - data['stepNum'] = self.stepNum - data['lineage'] = self.lineage - data['moduleStr'] = self.moduleOutput - data['moduleName'] = self.moduleName + data["cellStates"] = self.cellStates + data["stepNum"] = self.stepNum + data["lineage"] = self.lineage + data["moduleStr"] = self.moduleOutput + data["moduleName"] = self.moduleName if self.integ: - # print("Writing new pickle format") - data['specData'] = self.integ.levels + # print("Writing new pickle format") + data["specData"] = self.integ.levels if self.sig: - data['sigGridOrig'] = self.sig.gridOrig - data['sigGridDim'] = self.sig.gridDim - data['sigGridSize'] = self.sig.gridSize + data["sigGridOrig"] = self.sig.gridOrig + data["sigGridDim"] = self.sig.gridDim + data["sigGridSize"] = self.sig.gridSize if self.sig and self.integ: - data['sigGrid'] = self.integ.signalLevel - data['sigData'] = self.integ.cellSigLevels - data['sigGrid'] = self.integ.signalLevel + data["sigGrid"] = self.integ.signalLevel + data["sigData"] = self.integ.cellSigLevels + data["sigGrid"] = self.integ.signalLevel pickle.dump(data, outfile, protocol=-1) - #output csv file with cell pos,dir,len - sig? + # output csv file with cell pos,dir,len - sig? # Populate simulation from saved data pickle def loadGeometryFromPickle(self, data): - self.setCellStates(data['cellStates']) - self.lineage = data['lineage'] + self.setCellStates(data["cellStates"]) + self.lineage = data["lineage"] idx_map = {} id_map = {} idmax = 0 - for id,state in data['cellStates'].items(): + for id, state in data["cellStates"].items(): idx_map[state.id] = state.idx id_map[state.idx] = state.id - if id>idmax: - idmax=id + if id > idmax: + idmax = id self.idToIdx = idx_map self.idxToId = id_map - self._next_id = idmax+1 - self._next_idx = len(data['cellStates']) + self._next_id = idmax + 1 + self._next_idx = len(data["cellStates"]) if self.integ: self.integ.setCellStates(self.cellStates) if self.sig: @@ -430,25 +442,23 @@ def loadGeometryFromPickle(self, data): # Populate simulation from saved data pickle def loadFromPickle(self, data): - self.setCellStates(data['cellStates']) - self.lineage = data['lineage'] - self.stepNum = data['stepNum'] + self.setCellStates(data["cellStates"]) + self.lineage = data["lineage"] + self.stepNum = data["stepNum"] idx_map = {} id_map = {} idmax = 0 - for id,state in data['cellStates'].items(): + for id, state in data["cellStates"].items(): idx_map[state.id] = state.idx id_map[state.idx] = state.id - if id>idmax: - idmax=id + if id > idmax: + idmax = id self.idToIdx = idx_map self.idxToId = id_map - self._next_id = idmax+1 - self._next_idx = len(data['cellStates']) + self._next_id = idmax + 1 + self._next_idx = len(data["cellStates"]) if self.integ: - if 'sigData' in data: - self.integ.setLevels(data['specData'],data['sigData']) - elif 'specData' in data: - self.integ.setLevels(data['specData']) - - + if "sigData" in data: + self.integ.setLevels(data["specData"], data["sigData"]) + elif "specData" in data: + self.integ.setLevels(data["specData"]) diff --git a/scripts/batch.py b/scripts/batch.py index b80992e6..a9ceca55 100644 --- a/scripts/batch.py +++ b/scripts/batch.py @@ -9,39 +9,44 @@ max_cells = 50000 cell_buffer = 256 + def simulate(modfilename, platform, device, steps=50): - (path,name) = os.path.split(modfilename) - modname = str(name).split('.')[0] + path, name = os.path.split(modfilename) + modname = str(name).split(".")[0] sys.path.append(path) - sim = Simulator(modname, 0.025, clPlatformNum=platform, clDeviceNum=device, saveOutput=True) - while len(sim.cellStates) < max_cells-cell_buffer: + sim = Simulator( + modname, 0.025, clPlatformNum=platform, clDeviceNum=device, saveOutput=True + ) + while len(sim.cellStates) < max_cells - cell_buffer: sim.step() + def main(): # Get module name to load - if len(sys.argv)<2: + if len(sys.argv) < 2: print("Please specify a model (.py) file") exit(0) else: moduleName = sys.argv[1] # Get OpenCL platform/device numbers - if len(sys.argv)<3: + if len(sys.argv) < 3: # User input of OpenCL setup import pyopencl as cl + # Platform platforms = cl.get_platforms() print("Select OpenCL platform:") for i in range(len(platforms)): - print(('press '+str(i)+' for '+str(platforms[i]))) - platnum = int(eval(input('Platform Number: '))) + print(("press " + str(i) + " for " + str(platforms[i]))) + platnum = int(eval(input("Platform Number: "))) # Device devices = platforms[platnum].get_devices() print("Select OpenCL device:") for i in range(len(devices)): - print(('press '+str(i)+' for '+str(devices[i]))) - devnum = int(eval(input('Device Number: '))) + print(("press " + str(i) + " for " + str(devices[i]))) + devnum = int(eval(input("Device Number: "))) else: platnum = int(sys.argv[2]) devnum = int(sys.argv[3]) @@ -49,6 +54,7 @@ def main(): # Set up complete, now run the simulation simulate(moduleName, platnum, devnum) + # Make sure we are running as a script -if __name__ == "__main__": +if __name__ == "__main__": main() diff --git a/scripts/batch_file.py b/scripts/batch_file.py index e66c7c58..6017c25e 100644 --- a/scripts/batch_file.py +++ b/scripts/batch_file.py @@ -8,14 +8,13 @@ from cellmodeller.simulator import Simulator -sys.path.append('./') +sys.path.append("./") print((os.getcwd())) import cellmodeller.AdaptiveSimulator - -sys.path.append('Models') +sys.path.append("Models") cells = 300000 cell_buffer = 256 @@ -24,7 +23,7 @@ try: mod_name = sys.argv[1] except: - mod_name = 'DaninoOscillator' + mod_name = "DaninoOscillator" try: pickleDir = sys.argv[2] @@ -34,21 +33,21 @@ try: pickleSteps = int(sys.argv[3]) except: - 'setting pickleSteps to %i' % pickleSteps + "setting pickleSteps to %i" % pickleSteps try: os.mkdir(pickleDir) except OSError: - print((pickleDir, 'exists')) + print((pickleDir, "exists")) pickleSetDir = os.path.join(pickleDir, mod_name) try: os.mkdir(pickleSetDir) except: - print((pickleSetDir, 'exists')) + print((pickleSetDir, "exists")) -folderName = time.strftime('%Y%m%d-%H%M%S', time.localtime()) +folderName = time.strftime("%Y%m%d-%H%M%S", time.localtime()) pickleFileRoot = os.path.join(pickleSetDir, folderName) max_cells = 300000 @@ -56,14 +55,15 @@ def simulate(mod_name, steps=50): - print('simulate') + print("simulate") sim = Simulator(mod_name, 0.25, None, pickleSteps=50, pickleFileRoot=pickleFileRoot) - print('start') + print("start") sim.phys.set_cells() sim.phys.calc_cell_geom() - while len(sim.cellStates) < max_cells-cell_buffer: + while len(sim.cellStates) < max_cells - cell_buffer: sim.step() + simulate(mod_name) diff --git a/scripts/batch_iter.py b/scripts/batch_iter.py index 5d87dc4e..cbcae202 100644 --- a/scripts/batch_iter.py +++ b/scripts/batch_iter.py @@ -6,18 +6,20 @@ from cellmodeller.simulator import Simulator -sys.path.append('../../Models') +sys.path.append("../../Models") max_cells = 100000 cell_buffer = 256 -gammas = [2,5,10,15,30,50,100,500] +gammas = [2, 5, 10, 15, 30, 50, 100, 500] + def simulate(mod_name, ingam, fname): sim = Simulator(mod_name, 0.25, ingam, 25, fname) - while len(sim.cellStates) < max_cells-cell_buffer: + while len(sim.cellStates) < max_cells - cell_buffer: sim.step() -#here we are varying gamma from 1 to 50, every 2 + +# here we are varying gamma from 1 to 50, every 2 for i in range(len(gammas)): - simulate(sys.argv[1],gammas[i],(str(sys.argv[1])+'_gamma='+str(gammas[i]))) + simulate(sys.argv[1], gammas[i], (str(sys.argv[1]) + "_gamma=" + str(gammas[i]))) diff --git a/scripts/cell_modeller_gui.py b/scripts/cell_modeller_gui.py index 3763764f..77191c40 100644 --- a/scripts/cell_modeller_gui.py +++ b/scripts/cell_modeller_gui.py @@ -22,7 +22,7 @@ qapp = QApplication([]) # The UI -uifile = resource_stream('cellmodeller.gui', 'py_gl_gui.ui') +uifile = resource_stream("cellmodeller.gui", "py_gl_gui.ui") ui = uic.loadUi(uifile) ui.show() ui.raise_() @@ -34,7 +34,8 @@ label.setAlignment(Qt.AlignJustify) # Load a model if specified -if len(sys.argv) > 1: cmv.loadModelFile(sys.argv[1]) +if len(sys.argv) > 1: + cmv.loadModelFile(sys.argv[1]) # Launch app main loop sys.exit(qapp.exec_()) diff --git a/scripts/contact_graph.py b/scripts/contact_graph.py index 18360004..0e8e5ef4 100644 --- a/scripts/contact_graph.py +++ b/scripts/contact_graph.py @@ -14,6 +14,7 @@ from reportlab.lib.colors import Color from reportlab.graphics.shapes import Circle + class CellModellerPDFGenerator(Canvas): # --- # Class that extends reportlab pdf canvas to draw CellModeller simulations @@ -24,26 +25,26 @@ def __init__(self, name, network, bg_color): self.bg_color = bg_color Canvas.__init__(self, name) self.network = network - + def setup_canvas(self, name, world, page, page_center): - worldx,worldy = world - pagex,pagey = page - page_centx,page_centy = page_center - self.setPageSize((pagex*units.cm, pagey*units.cm)) + worldx, worldy = world + pagex, pagey = page + page_centx, page_centy = page_center + self.setPageSize((pagex * units.cm, pagey * units.cm)) self.setFillColor(self.bg_color) - self.rect(0, 0, pagex*units.cm, pagey*units.cm, fill=1) - self.translate(pagex*units.cm/2.0, pagey*units.cm/2.0) - self.translate(page_centx*units.cm, page_centy*units.cm) - self.scale(float(pagex*units.cm)/worldx, float(pagey*units.cm)/worldy) + self.rect(0, 0, pagex * units.cm, pagey * units.cm, fill=1) + self.translate(pagex * units.cm / 2.0, pagey * units.cm / 2.0) + self.translate(page_centx * units.cm, page_centy * units.cm) + self.scale(float(pagex * units.cm) / worldx, float(pagey * units.cm) / worldy) - def drawNode(self,pos,col): - Canvas.setFillColor(self,col) - Canvas.circle(self,pos[0],pos[1],0.3, fill = 1) + def drawNode(self, pos, col): + Canvas.setFillColor(self, col) + Canvas.circle(self, pos[0], pos[1], 0.3, fill=1) - def drawEdge(self,pos1,pos2): + def drawEdge(self, pos1, pos2): path = self.beginPath() - path.moveTo(pos1[0],pos1[1]) - path.lineTo(pos2[0],pos2[1]) + path.moveTo(pos1[0], pos1[1]) + path.lineTo(pos2[0], pos2[1]) self.drawPath(path, fill=1) def draw_frame(self, name, world, page, center): @@ -54,66 +55,79 @@ def draw_frame(self, name, world, page, center): def draw_graph(self): self.saveState() - self.setLineWidth(0.003*units.cm) - self.setStrokeColor((0.0,0.0,0.0)) - positions = list(networkx.get_node_attributes(G,'pos').values()) - colors = list(networkx.get_node_attributes(G,'color').values()) - for u,v,di in self.network.edges_iter(data=True): - self.drawEdge(positions[u],positions[v]) + self.setLineWidth(0.003 * units.cm) + self.setStrokeColor((0.0, 0.0, 0.0)) + positions = list(networkx.get_node_attributes(G, "pos").values()) + colors = list(networkx.get_node_attributes(G, "color").values()) + for u, v, di in self.network.edges_iter(data=True): + self.drawEdge(positions[u], positions[v]) for n in self.network.nodes_iter(): - self.drawNode(positions[n],colors[n]) + self.drawNode(positions[n], colors[n]) self.restoreState() -def generate_network(G,num_cells,ct_tos,n_cts,pos,celldata): - for i in range(0, num_cells): #make all nodes - G.add_node(i, pos = pos[i], type=celldata[i], color = (1,0,0) if celldata[i]==0 else (0,1,0)) - for i in range(0, num_cells): #make all edges (when all nodes are present) - for j in range(0, n_cts[i]): #make all edges from contact_tos - G.add_edge(i,ct_tos[i,j], width=8 , color = 'black') + +def generate_network(G, num_cells, ct_tos, n_cts, pos, celldata): + for i in range(0, num_cells): # make all nodes + G.add_node( + i, + pos=pos[i], + type=celldata[i], + color=(1, 0, 0) if celldata[i] == 0 else (0, 1, 0), + ) + for i in range(0, num_cells): # make all edges (when all nodes are present) + for j in range(0, n_cts[i]): # make all edges from contact_tos + G.add_edge(i, ct_tos[i, j], width=8, color="black") + def get_current_contacts(G, data): - cs = data['cellStates'] + cs = data["cellStates"] it = iter(cs) n = len(cs) - cell_type={} - pos_dict={} + cell_type = {} + pos_dict = {} for it in cs: cell_type[cs[it].idx] = cs[it].cellType pos_dict[cs[it].idx] = cs[it].pos[0:2] - modname = data['moduleName'] - moduleStr = data['moduleStr'] + modname = data["moduleName"] + moduleStr = data["moduleStr"] sim = Simulator(modname, 0.0, moduleStr=moduleStr, saveOutput=False) sim.loadFromPickle(data) - sim.phys.update_grid() # we assume local cell_centers is current + sim.phys.update_grid() # we assume local cell_centers is current sim.phys.bin_cells() - sim.phys.cell_sqs = sim.phys.cell_sqs_dev.get() # get updated cell sqs + sim.phys.cell_sqs = sim.phys.cell_sqs_dev.get() # get updated cell sqs sim.phys.sort_cells() - sim.phys.sorted_ids_dev.set(sim.phys.sorted_ids) # push changes to the device + sim.phys.sorted_ids_dev.set(sim.phys.sorted_ids) # push changes to the device sim.phys.sq_inds_dev.set(sim.phys.sq_inds) sim.phys.find_contacts(predict=False) sim.phys.get_cts() - ct_pts=sim.phys.ct_pts #these are the points on the cell surface - they can be transformed into the global coordinate system - ct_tos=sim.phys.ct_tos #this is the list of *some* contacts from each cell (only for lower cell_ids) - ct_dists=sim.phys.ct_dists - cell_cts=sim.phys.cell_n_cts #not really all the contacts of the cell, because the tos are only defined between a cell and ones with lower ids - generate_network(G,n,ct_tos,cell_cts,pos_dict,cell_type) + ct_pts = ( + sim.phys.ct_pts + ) # these are the points on the cell surface - they can be transformed into the global coordinate system + ct_tos = ( + sim.phys.ct_tos + ) # this is the list of *some* contacts from each cell (only for lower cell_ids) + ct_dists = sim.phys.ct_dists + cell_cts = ( + sim.phys.cell_n_cts + ) # not really all the contacts of the cell, because the tos are only defined between a cell and ones with lower ids + generate_network(G, n, ct_tos, cell_cts, pos_dict, cell_type) -bg_color = Color(1.0,1.0,1.0,alpha=1.0) +bg_color = Color(1.0, 1.0, 1.0, alpha=1.0) G = networkx.Graph() fname = sys.argv[1] -data = pickle.load(open(fname,'rb')) -cs = data['cellStates'] +data = pickle.load(open(fname, "rb")) +cs = data["cellStates"] it = iter(cs) n = len(cs) -oname = fname.replace('.pickle','_graph.pdf') +oname = fname.replace(".pickle", "_graph.pdf") -print(("num_cells = "+str(n))) +print(("num_cells = " + str(n))) -cell_type={} -pos_dict={} +cell_type = {} +pos_dict = {} for it in cs: cell_type[cs[it].idx] = cs[it].cellType pos_dict[cs[it].idx] = cs[it].pos[0:2] @@ -124,18 +138,17 @@ def get_current_contacts(G, data): degrees = list(G.degree().values()) print(("mean degree = " + str(np.mean(degrees)))) -if list(networkx.get_edge_attributes(G,'color').items()): - edges,ecolor = list(zip(*list(networkx.get_edge_attributes(G,'color').items()))) -ncolor = list(networkx.get_node_attributes(G,'color').values()) +if list(networkx.get_edge_attributes(G, "color").items()): + edges, ecolor = list(zip(*list(networkx.get_edge_attributes(G, "color").items()))) +ncolor = list(networkx.get_node_attributes(G, "color").values()) pdf = CellModellerPDFGenerator(oname, G, bg_color) -world = (120,120) -page = (50,50) -center = (0,0) +world = (120, 120) +page = (50, 50) +center = (0, 0) pdf.draw_frame(oname, world, page, center) -#from this, I want the spatial position of every contact, and the graph of the cells that each cell is touching -#This can be all in one data structure - a graph where each vertex has a position, and each node has a cellState - +# from this, I want the spatial position of every contact, and the graph of the cells that each cell is touching +# This can be all in one data structure - a graph where each vertex has a position, and each node has a cellState diff --git a/scripts/draw_2d_pdf.py b/scripts/draw_2d_pdf.py index af920463..0150d7d6 100644 --- a/scripts/draw_2d_pdf.py +++ b/scripts/draw_2d_pdf.py @@ -12,21 +12,22 @@ mxsig0 = 0 + class CellModellerPDFGenerator(Canvas): # --- # Class that extends reportlab pdf canvas to draw CellModeller simulations # --- def __init__(self, name, data, bg_color): self.name = name - self.states = data.get('cellStates') + self.states = data.get("cellStates") - self.signal_levels = data.get('sigGrid', None) - self.signal_grid_orig = data.get('sigGridOrig', None) - self.signal_grid_dim = data.get('sigGridDim', None) - self.signal_grid_size = data.get('sigGridSize', None) + self.signal_levels = data.get("sigGrid", None) + self.signal_grid_orig = data.get("sigGridOrig", None) + self.signal_grid_dim = data.get("sigGridDim", None) + self.signal_grid_size = data.get("sigGridSize", None) self.signals = self.signal_levels is not None - - self.parents = data.get('lineage') + + self.parents = data.get("lineage") self.data = data self.bg_color = bg_color Canvas.__init__(self, name) @@ -38,40 +39,41 @@ def __init__(self, name, data, bg_color): # ---- def calc_cell_colors(self, state): # Generate Color objects from cellState, with black outline - (r,g,b) = state.color + r, g, b = state.color # Return value is tuple of colors, (fill, stroke) - return [Color(r,g,b,alpha=1.0) , Color(0,0,0,alpha=1.0)] + return [Color(r, g, b, alpha=1.0), Color(0, 0, 0, alpha=1.0)] + # ---- def setup_canvas(self, name, world, page, page_center): - worldx,worldy = world - pagex,pagey = page - page_centx,page_centy = page_center - self.setPageSize((pagex*units.cm, pagey*units.cm)) + worldx, worldy = world + pagex, pagey = page + page_centx, page_centy = page_center + self.setPageSize((pagex * units.cm, pagey * units.cm)) self.setFillColor(self.bg_color) - self.rect(0, 0, pagex*units.cm, pagey*units.cm, fill=1) - self.translate(pagex*units.cm/2.0, pagey*units.cm/2.0) - self.translate(page_centx*units.cm, page_centy*units.cm) - self.scale(float(pagex*units.cm)/worldx, float(pagey*units.cm)/worldy) + self.rect(0, 0, pagex * units.cm, pagey * units.cm, fill=1) + self.translate(pagex * units.cm / 2.0, pagey * units.cm / 2.0) + self.translate(page_centx * units.cm, page_centy * units.cm) + self.scale(float(pagex * units.cm) / worldx, float(pagey * units.cm) / worldy) def capsule_path(self, l, r): path = self.beginPath() - path.moveTo(-l/2.0, -r) - path.lineTo(l/2.0, -r) + path.moveTo(-l / 2.0, -r) + path.lineTo(l / 2.0, -r) - path.arcTo(l/2.0-r, -r, l/2.0+r, r, -90, 180) + path.arcTo(l / 2.0 - r, -r, l / 2.0 + r, r, -90, 180) - path.lineTo(-l/2.0, r) - path.arc(-l/2.0-r, -r, -l/2.0+r, r, 90, 180) - #path.close() + path.lineTo(-l / 2.0, r) + path.arc(-l / 2.0 - r, -r, -l / 2.0 + r, r, 90, 180) + # path.close() return path def draw_capsule(self, p, d, l, r, fill_color, stroke_color): self.saveState() self.setStrokeColor(stroke_color) self.setFillColor(fill_color) - self.setLineWidth(0.001*units.cm) - self.setLineWidth(0.001*units.cm) + self.setLineWidth(0.001 * units.cm) + self.setLineWidth(0.001 * units.cm) self.translate(p[0], p[1]) self.rotate(math.degrees(math.atan2(d[1], d[0]))) path = self.capsule_path(l, r) @@ -89,41 +91,43 @@ def draw_cells(self): def draw_chamber(self): # for EdgeDetectorChamber-22-57-02-06-12 - self.setLineWidth(0.015*units.cm) + self.setLineWidth(0.015 * units.cm) self.line(-100, -16, 100, -16) self.line(-100, 16, 100, 16) def draw_signals(self, index=0, scale=0.0192, z=0): - ''' + """ Function for drawing signal grids, currently limited to 1 signal a plane at a fixed z-axis level through the grid index = index of signal to render scale = scale factor for signal level - z = height of slice through grid - ''' + z = height of slice through grid + """ global mxsig0 # for EdgeDetectorChamber-22-57-02-06-12 - l, orig, dim, levels = self.signal_grid_size, \ - self.signal_grid_orig, \ - self.signal_grid_dim, \ - self.signal_levels + l, orig, dim, levels = ( + self.signal_grid_size, + self.signal_grid_orig, + self.signal_grid_dim, + self.signal_levels, + ) levels = levels.reshape(dim) - mx = levels[index,:,:,z].max() - l = list(map(float,l)) + mx = levels[index, :, :, z].max() + l = list(map(float, l)) for i in range(dim[1]): - x = l[0]*i + orig[0] + x = l[0] * i + orig[0] for j in range(dim[2]): - y = l[1]*j + orig[1] - lvls = levels[index,i,j,z]/mx + y = l[1] * j + orig[1] + lvls = levels[index, i, j, z] / mx mxsig0 = max(lvls, mxsig0) self.setFillColorRGB(lvls, 0, 0) - self.rect(x-l[0]/2.0, y-l[1]/2.0, l[0], l[1], stroke=0, fill=1) + self.rect(x - l[0] / 2.0, y - l[1] / 2.0, l[0], l[1], stroke=0, fill=1) def draw_frame(self, name, world, page, center): self.setup_canvas(name, world, page, center) - #draw_chamber(c) - if self.signals: + # draw_chamber(c) + if self.signals: print("Drawing signals") self.draw_signals() self.draw_cells() @@ -141,62 +145,67 @@ def computeBox(self): mnx = -20 mxy = 20 mny = -20 - for (id,s) in list(self.states.items()): - pos = s.pos - l = s.length # add/sub length to keep cell in frame - mxx = max(mxx,pos[0]+l) - mnx = min(mnx,pos[0]-l) - mxy = max(mxy,pos[1]+l) - mny = min(mny,pos[1]-l) - w = (mxx-mnx) - h = (mxy-mny) - return (w,h) + for id, s in list(self.states.items()): + pos = s.pos + l = s.length # add/sub length to keep cell in frame + mxx = max(mxx, pos[0] + l) + mnx = min(mnx, pos[0] - l) + mxy = max(mxy, pos[1] + l) + mny = min(mny, pos[1] - l) + w = mxx - mnx + h = mxy - mny + return (w, h) + + # -#End class CellModellerPDFGenerator +# End class CellModellerPDFGenerator + def importPickle(fname): - if fname[-7:]=='.pickle': - print(('Importing CellModeller pickle file: %s'%fname)) - data = pickle.load(open(fname, 'rb')) + if fname[-7:] == ".pickle": + print(("Importing CellModeller pickle file: %s" % fname)) + data = pickle.load(open(fname, "rb")) - # Check for old-style pickle that is tuple, + # Check for old-style pickle that is tuple, # just extract cellStates from 1st element if isinstance(data, tuple): - data = {'cellStates':data[0]} + data = {"cellStates": data[0]} # Return dictionary of simulation data return data else: return None + # Define a pdf generator class with cell outline color same as fill color class MyPDFGenerator(CellModellerPDFGenerator): def calc_cell_colors(self, state): # Generate Color objects from cellState, fill=stroke - (r,g,b) = state.color + r, g, b = state.color # Return value is tuple of colors, (fill, stroke) - fcol = Color(r,g,b,alpha=1.0) - scol = Color(r*0.5,g*0.5,b*0.5,alpha=1.0) - return [fcol,scol] + fcol = Color(r, g, b, alpha=1.0) + scol = Color(r * 0.5, g * 0.5, b * 0.5, alpha=1.0) + return [fcol, scol] + def main(): # To do: parse some useful arguments as rendering options here # e.g. outline color, page size, etc. # # For now, put these options into variables here: - bg_color = Color(0,0,0,alpha=1.0) + bg_color = Color(0, 0, 0, alpha=1.0) # For now just assume a list of files infns = sys.argv[1:] for infn in infns: # File names - if infn[-7:]!='.pickle': - print(('Ignoring file %s, because its not a pickle...'%(infn))) + if infn[-7:] != ".pickle": + print(("Ignoring file %s, because its not a pickle..." % (infn))) continue - outfn = infn.replace('.pickle', '.pdf') - outfn = os.path.basename(outfn) # Put output in this dir - print(('Processing %s to generate %s'%(infn,outfn))) - + outfn = infn.replace(".pickle", ".pdf") + outfn = os.path.basename(outfn) # Put output in this dir + print(("Processing %s to generate %s" % (infn, outfn))) + # Import data data = importPickle(infn) if not data: @@ -209,19 +218,19 @@ def main(): # Get the bounding square of the colony to size the image # This will resize the image to fit the page... # ** alternatively you can specify a fixed world size here - '''(w,h) = pdf.computeBox() + """(w,h) = pdf.computeBox() sqrt2 = math.sqrt(2) - world = (w/sqrt2,h/sqrt2)''' - world = (150,150) + world = (w/sqrt2,h/sqrt2)""" + world = (150, 150) # Page setup - page = (20,20) - center = (0,0) + page = (20, 20) + center = (0, 0) # Render pdf - print(('Rendering PDF output to %s'%outfn)) + print(("Rendering PDF output to %s" % outfn)) pdf.draw_frame(outfn, world, page, center) -if __name__ == "__main__": - main() +if __name__ == "__main__": + main() diff --git a/scripts/length_histogram.py b/scripts/length_histogram.py index c0c591bc..504eafd0 100644 --- a/scripts/length_histogram.py +++ b/scripts/length_histogram.py @@ -2,54 +2,60 @@ import os import math import numpy as np -sys.path.append('.') + +sys.path.append(".") import pickle import cellmodeller -#import matplotlib.pyplot as plt -file = sys.argv[1] #select pickle file in command line -output_file = open('LengthData.csv','w') +# import matplotlib.pyplot as plt + +file = sys.argv[1] # select pickle file in command line +output_file = open("LengthData.csv", "w") def rad_pos(cellstate): - return np.sqrt(cellstate.pos[0]*cellstate.pos[0]+cellstate.pos[1]*cellstate.pos[1]) + return np.sqrt( + cellstate.pos[0] * cellstate.pos[0] + cellstate.pos[1] * cellstate.pos[1] + ) + def lengthHist(pickle, bins, file=False): - print(('opening '+ pickle)) - data = pickle.load(open(pickle,'r')) - cs = data['cellStates'] + print(("opening " + pickle)) + data = pickle.load(open(pickle, "r")) + cs = data["cellStates"] it = iter(cs) n = len(cs) - print(('Number of cells = '+str(n))) + print(("Number of cells = " + str(n))) lens = [] r = [] for it in cs: radialPosition = rad_pos(cs[it]) - cellLength = cs[it].length+2*cs[it].radius + cellLength = cs[it].length + 2 * cs[it].radius r.append(radialPosition) lens.append(cellLength) if file: - file.write(str(radialPosition)+', '+ str(cellLength)+'\n') - #plt.hist(lens,bins) - #heatmap, xedges, yedges = np.histogram2d(r, lens, bins=100) - #extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]] - #plt.imshow(heatmap,extent=extent,aspect='auto') - #plt.show() - #print r, lens + file.write(str(radialPosition) + ", " + str(cellLength) + "\n") + # plt.hist(lens,bins) + # heatmap, xedges, yedges = np.histogram2d(r, lens, bins=100) + # extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]] + # plt.imshow(heatmap,extent=extent,aspect='auto') + # plt.show() + # print r, lens return r, lens -def dirLengthHist(dir,bins,file=False): + +def dirLengthHist(dir, bins, file=False): for f in os.listdir(dir): - if '.pickle' in f: + if ".pickle" in f: number = f[5:-7] if file: - fout = open('LengthData'+number+'.csv') - print(('step number = ', number)) - n, lens = lengthHist(dir + f,bins,file) + fout = open("LengthData" + number + ".csv") + print(("step number = ", number)) + n, lens = lengthHist(dir + f, bins, file) if file: fout.close() -bin = np.arange(0.0,6.0,0.1) -lengthHist(file,bin,output_file) -output_file.close() +bin = np.arange(0.0, 6.0, 0.1) +lengthHist(file, bin, output_file) +output_file.close() diff --git a/scripts/multi_batch.py b/scripts/multi_batch.py index 9ec3cfdb..dfb34d7c 100644 --- a/scripts/multi_batch.py +++ b/scripts/multi_batch.py @@ -9,39 +9,42 @@ max_cells = 100000 cell_buffer = 256 + def simulate(modfilename, platform, device, steps=50): - (path,name) = os.path.split(modfilename) - modname = str(name).split('.')[0] + path, name = os.path.split(modfilename) + modname = str(name).split(".")[0] sys.path.append(path) sim = Simulator(modname, 0.25, clPlatformNum=platform, clDeviceNum=device) - while len(sim.cellStates) < max_cells-cell_buffer: + while len(sim.cellStates) < max_cells - cell_buffer: sim.step() + def main(): # Get module name to load - if len(sys.argv)<2: + if len(sys.argv) < 2: print("Please specify a model (.py) file") exit(0) else: moduleName = sys.argv[1] # Get OpenCL platform/device numbers - if len(sys.argv)<3: + if len(sys.argv) < 3: # User input of OpenCL setup import pyopencl as cl + # Platform platforms = cl.get_platforms() print("Select OpenCL platform:") for i in range(len(platforms)): - print(('press '+str(i)+' for '+str(platforms[i]))) - platnum = int(eval(input('Platform Number: '))) + print(("press " + str(i) + " for " + str(platforms[i]))) + platnum = int(eval(input("Platform Number: "))) # Device devices = platforms[platnum].get_devices() print("Select OpenCL device:") for i in range(len(devices)): - print(('press '+str(i)+' for '+str(devices[i]))) - devnum = int(eval(input('Device Number: '))) + print(("press " + str(i) + " for " + str(devices[i]))) + devnum = int(eval(input("Device Number: "))) else: platnum = int(sys.argv[2]) devnum = int(sys.argv[3]) @@ -50,7 +53,7 @@ def main(): for i in range(3): simulate(moduleName, platnum, devnum) + # Make sure we are running as a script -if __name__ == "__main__": +if __name__ == "__main__": main() - diff --git a/scripts/print_timing.py b/scripts/print_timing.py index 055e9957..8967bf6b 100644 --- a/scripts/print_timing.py +++ b/scripts/print_timing.py @@ -1,18 +1,18 @@ import sys import os -sys.path.append('.') + +sys.path.append(".") import pickle import cellmodeller -dir = os.path.join('data', sys.argv[1]) +dir = os.path.join("data", sys.argv[1]) print("No. cells\ttime (s)") print("-------------------") for f in os.listdir(dir): - if 'pickle' in f: - ff = os.path.join(dir,f) - (cs,lin) = pickle.load(open(ff,'r')) + if "pickle" in f: + ff = os.path.join(dir, f) + cs, lin = pickle.load(open(ff, "r")) n = len(cs) t = os.path.getmtime(ff) - print(("%i\t%f"%(n,t))) - + print(("%i\t%f" % (n, t))) diff --git a/scripts/spatial_analyze.py b/scripts/spatial_analyze.py index affcc4b7..9a8c386e 100644 --- a/scripts/spatial_analyze.py +++ b/scripts/spatial_analyze.py @@ -2,43 +2,46 @@ import os import math import numpy as np -sys.path.append('.') + +sys.path.append(".") import pickle import cellmodeller import matplotlib.pyplot as plt -pname= sys.argv[1] -print(('opening '+ pname)) -fout=open('spatial.txt', "w") +pname = sys.argv[1] +print(("opening " + pname)) +fout = open("spatial.txt", "w") fout.write("r spec_level \n") -bin_num=20 -rad_max=95 +bin_num = 20 +rad_max = 95 -narray=np.zeros(bin_num) -specArray=np.zeros(bin_num) +narray = np.zeros(bin_num) +specArray = np.zeros(bin_num) -data = pickle.load(open(pname,'r')) -cs = data['cellStates'] +data = pickle.load(open(pname, "r")) +cs = data["cellStates"] it = iter(cs) n = len(cs) -rArray = np.multiply(list(range(0,bin_num)),rad_max/bin_num) +rArray = np.multiply(list(range(0, bin_num)), rad_max / bin_num) for it in cs: - r = np.sqrt(cs[it].pos[0]*cs[it].pos[0]+cs[it].pos[1]*cs[it].pos[1]) - for x in range(0,bin_num): - if((r>=x*rad_max/bin_num)and(r<(x+1)*rad_max/bin_num)): - specArray[x]=specArray[x]*narray[x]+cs[it].species[0] - narray[x]+=1 - specArray[x]=specArray[x]/narray[x] - -for x in range(0,bin_num): - fout.write(str((x+1)*rad_max/bin_num/2)+" "+str(narray[x])) - if(narray[x]==0): fout.write(" 0.0\n") - else: fout.write(" "+str(specArray[x])+"\n") + r = np.sqrt(cs[it].pos[0] * cs[it].pos[0] + cs[it].pos[1] * cs[it].pos[1]) + for x in range(0, bin_num): + if (r >= x * rad_max / bin_num) and (r < (x + 1) * rad_max / bin_num): + specArray[x] = specArray[x] * narray[x] + cs[it].species[0] + narray[x] += 1 + specArray[x] = specArray[x] / narray[x] + +for x in range(0, bin_num): + fout.write(str((x + 1) * rad_max / bin_num / 2) + " " + str(narray[x])) + if narray[x] == 0: + fout.write(" 0.0\n") + else: + fout.write(" " + str(specArray[x]) + "\n") fout.close() -plt.plot(rArray,specArray) -plt.show() \ No newline at end of file +plt.plot(rArray, specArray) +plt.show()