This tutorial shows, step by step, how to create a simple simulation in python using MorphoNet as a viewer.
For this tutorial, you need python 3.x and the API of morphonet.
You can easly install it using pip install morphonet
The API has some dependecies scipy , numpy, scikit-image, vtk
For our simulation we use this librairy Traer Physics but we redevelop it in python. You can download it here
The objective here is just to show you how to use MorphoNet as a 4D Interactive viewer. For that we use a simple simulation example where sphere divide !
We first import classical librarie, define some basic functions and read a sphere as an obj file
import sys,os
import numpy as np
import math
sys.path.append('traer') #The traer.zip path
from ParticleSystem import ParticleSystem
def volume(radius):
return 4.0/3.0*math.pi*math.pow(radius,3)
def radius(vol):
return math.pow(vol/(math.pi*(4.0/3.0)),1.0/3.0)
with open("sphere.obj",'r') as f:
obj = f.read()
We create a class for a cell and for the simulated embyro
id_cell=0 #Global Id Cell
class Cell():
def __init__(self,radius,life,coord): # CONSTRUCTATORRRR
global id_cell
self.id=id_cell
id_cell+=1
self.radius=radius
self.p=physics.makeParticle(1.0,coord[0], coord[1], coord[2])
self.cell_life=life
self.life=life
def center(self):
return [self.p.position.x,self.p.position.y,self.p.position.z]
class Embryo():
def __init__(self,cell_radius=100,cell_life=50,step_physics=1,maxTime=500,plotTime=10): # CONSTRUCTATORRRR
self.cells=[]
self.cell_life=cell_life
c=Cell(cell_radius,cell_life,[0,0,0])
self.cells.append(c)
self.step_physics=step_physics
self.maxTime=maxTime
self.t=0
self.plotTime=plotTime
self.lineage="#Lineage Simulated\n"
self.lineage+="type:time\n"
def live(self):
while self.t<self.maxTime:
if self.t%self.plotTime==0:
self.plot()
physics.tick(self.step_physics)
if len(self.cells)<1000:
self.isDivide()
if len(self.cells)>1:
print('-> at '+str(self.t)+ ", " +str(len(self.cells))+ " cells -> Average forces "+str(physics.tension()))
else:
print('-> at '+str(self.t)+ "-> no springs")
self.t+=1
print("Done !")
def getTime(self):
return int(self.t/self.plotTime) #Time of plot
def plot(self):
tp=self.getTime()
obj="#Test Primitives\n"
for c in self.cells:
obj+="p "+str(tp)+","+str(c.id)+" sphere ("+str(c.p.position.x)+","+str(c.p.position.y)+","+str(c.p.position.z)+") "+str(c.radius)+" (1,1,1,1) \n"
mp.plotAt(tp,obj)
def plot_lineage(self):
f=open('lineage.txt',"w");f.write(self.lineage);f.close()
mp.plot_infos("Lineage",self.lineage)
def divide(self,c,aug_life=5):#Create a new Cell after Division
c.radius=radius(volume(c.radius)/2)
sister=Cell(c.radius,c.cell_life+np.random.randint(aug_life),c.center()+np.random.rand(3))
s=physics.makeSpring(c.p,sister.p, 0.04, 0.1,c.radius+sister.radius) #0.05,0.1
c.life=c.cell_life+np.random.randint(aug_life)
self.cells.append(sister)
return sister
def isDivide(self):
tp=self.getTime()
for c in self.cells:
self.lineage+=str(tp)+","+str(c.id)+":"+str(tp+1)+","+str(c.id)+"\n"
if c.life<=0:
newcell=self.divide(c)
self.lineage+=str(tp)+","+str(c.id)+":"+str(tp+1)+","+str(newcell.id)+"\n"
c.life-=1
We import morphonet API and run the simulation
import morphonet
mp=morphonet.Plot()
mp.addPrimitive("sphere",obj) #We define our sphere as a primitive
physics = ParticleSystem()
e=Embryo(maxTime=500,plotTime=10)
e.live()
e.plot_lineage()
And now we can directly visualize the simulation in the browser and play with it