海津一成
In [1]:
%matplotlib inline
from ecell4 import *
from ecell4_base.core import *
from ecell4_base import *
In [2]:
import matplotlib as mpl
inline_rc = dict(mpl.rcParams)
import seaborn
seaborn.set(font_scale=1.5)
# mpl.rc("figure", figsize=(8.0, 5.5))
mpl.rc("figure", figsize=(6, 4))
PlanarSurface
: 平面Sphere
: 球体Cylinder
: 円柱Rod
: ロッドAABB
: 直方体
In [3]:
help(Rod.__init__)
In [4]:
w = spatiocyte.World(Real3(2, 1, 1), 0.01)
w.add_structure(Species('C'), Rod(1, 0.5, Real3(1, 0.5, 0.5)))
viz.plot_world(w)
これらの基本要素に対してその表面だけを構造体とすることもできる。
In [5]:
w = spatiocyte.World(Real3(2, 1, 1), 0.01)
obj = Rod(1, 0.5, Real3(1, 0.5, 0.5))
w.add_structure(Species('C'), obj.surface())
show(w)
これらを組み合せてより複雑な形状をつくることもできる。
Union
: ふたつのShape
の和で新しいShape
をつくるComplement
: ふたつのShape
、X
とY
を受けとり、その差(X-Y
)で新しいShape
をつくるAffineTransformation
: 受けとったShape
に対して変形操作を行う。今は平行移動とリサイズ、軸周りの回転が可能
In [6]:
w = spatiocyte.World(Real3(1.75, 1, 1), 0.01)
obj1 = Sphere(Real3(0.5, 0.5, 0.5), 0.5)
obj2 = Sphere(Real3(1.25, 0.5, 0.5), 0.5)
obj = Union(obj1, obj2)
w.add_structure(Species('C'), obj.surface())
show(w)
こうした問題に対して、分子種に構造を与えるのがルールベース・モデリングの第一歩である。
In [7]:
with reaction_rules():
# corresponding to 'A > B | 1'
X(s=u) > X(s=p) | 1
In [8]:
m = get_model()
E-Cell4では括弧や等号を使って分子種の構造を決める。
X(s=u)
はX
という分子の修飾s
が状態u
である。X(s=p)
はX
という分子の修飾s
が状態'p'である。X
の修飾s
の状態をu
からp
にする。分子種の構造をWorld
で確かめる。
In [9]:
w = gillespie.World()
w.add_molecules(Species('X(s=u)'), 60)
w.add_molecules(Species('X(s=p)'), 120)
print(w.num_molecules(Species('X(s=u)')))
print(w.num_molecules(Species('X(s=p)')))
print(w.num_molecules(Species("X")))
X
という分子種は1つも追加していないにもかかわらずnum_molecules
で180個という数が得られた。
これはX
という分子を修飾状態に関わらず全て数え上げているためである。
加えた2つの分子種はどちらもX
という分子で修飾状態だけが異なる。従って、X
を数えた場合どちらも当てはまる。
きっちりX
という名前の分子種だけを数えたい場合はnum_molecules_exact
を使う。
In [10]:
print(w.num_molecules_exact(Species('X(s=u)')))
print(w.num_molecules_exact(Species('X(s=p)')))
print(w.num_molecules_exact(Species("X")))
次に、X
という分子とY
という分子が結合した複合体を表す分子種は以下のように書ける。
In [11]:
with reaction_rules():
X(b1) + Y(b2) > X(b1^1).Y(b2^1) | 1
In [12]:
m = get_model()
X
とY
がドット.
で結合されている。このように複合体は複数の分子種をドットでつないで表現する。
X(b1^1).Y(b2^1)
は全体として一つの分子種を表すが、中にX(b1^1)
とY(b2^1)
という二つの要素が含まれる。E-Cell4ではこれらを単位分子種UnitSpecies
と呼ぶ。
X(b1^1).Y(b2^1)
の単位分子種はb1
、b2
という修飾を持つ。
これが単位分子種間の結合箇所を決める。X
とY
は各々の修飾b1
、b2
を介して結合している。
記号^
の後の数字は結合箇所の対応を表す数字である。これは対応さえ取れていれば、0より大きなどんな数字でも良い。
左辺のX(b1)
で修飾b1
に等号による状態も^
による結合も記されていないのは、結合箇所b1
が誰とも結合していないことを明らかにするため。
X(b1)
は修飾b1
を介して誰とも結合していないX
を意味している。
複合体の表現を説明したところで先ほどと同じように試してみる。
In [13]:
w = gillespie.World()
In [14]:
w.add_molecules(Species('X(b1)'), 10)
w.add_molecules(Species('Y(b2)'), 20)
w.add_molecules(Species('X(b1^1).Y(b2^1)'), 30)
print(w.num_molecules(Species('X')))
print(w.num_molecules(Species('Y')))
print(w.num_molecules(Species('X.Y')))
X
とY
は単体と複合体の和になっているのに対して、X.Y
は複合体だけを数えているのがわかる。
注意点だが、結合部位と修飾部位を両方もつ分子種の場合、
X(a, b=c)
とは書けるがX(b=c, a)
とは書けない。
部位が複数ある場合もX(a, b, c, d=e, f=g)
のように書く必要がある。ただし、順番を入れ替えたX(c, a, b, f=g, d=e)
は先ほどと同じ意味になる。
単位分子種X
には3つのリン酸化部位s1
、s2
、s3
があり、各々u
かp
の二状態のいずれかを独立に取るものとする。
このとき単位分子種X
のとりえる状態数は$2^3=8$状態となる。
このような分子X
のリン酸化反応は次のように書ける。
In [15]:
with reaction_rules():
X(s1=u, s2=u, s3=u) > X(s1=p, s2=u, s3=u) | 1
X(s1=u, s2=p, s3=u) > X(s1=p, s2=p, s3=u) | 1
X(s1=u, s2=u, s3=p) > X(s1=p, s2=u, s3=p) | 1
X(s1=u, s2=p, s3=p) > X(s1=p, s2=p, s3=p) | 1
X(s1=u, s2=u, s3=u) > X(s1=u, s2=p, s3=u) | 2
X(s1=p, s2=u, s3=u) > X(s1=p, s2=p, s3=u) | 2
X(s1=u, s2=u, s3=p) > X(s1=u, s2=p, s3=p) | 2
X(s1=p, s2=u, s3=p) > X(s1=p, s2=p, s3=p) | 2
X(s1=u, s2=u, s3=u) > X(s1=u, s2=u, s3=p) | 3
X(s1=u, s2=p, s3=u) > X(s1=u, s2=p, s3=p) | 3
X(s1=p, s2=u, s3=u) > X(s1=p, s2=u, s3=p) | 3
X(s1=p, s2=p, s3=u) > X(s1=p, s2=p, s3=p) | 3
In [16]:
m = get_model()
このように面倒になるのは、各リン酸化反応が独立であることが活かされず、1つのリン酸化部位を考えるのに他の全ての状態を数え上げなければならないからである。
そこで分子種のパターンで考える。
リン酸化部位s1
に着目したとき、リン酸化反応は分子X
のs1
の状態がu
からp
から変わることである。
すなわち、s1
の状態がu
である分子X
のパターンに当てはまる分子種をとってきて、その状態をp
に変えると考える。
In [17]:
with reaction_rules():
X(s1=u) > X(s1=p) | 1
X(s2=u) > X(s2=p) | 2
X(s3=u) > X(s3=p) | 3
これらは個々の具体的な分子種を左右に持った反応ではなく、分子種のパターンを与えるものであるから反応則ReactionRule
と呼ぶ。
反応則はあくまでもパターンに基づいたルールでしかないため、これだけでは実際にどんな分子種があるのかはわからない。
上の例で言えば左辺にX(s1=u)
という分子種があるからといってそれが実在するとは限らない。
実際に最初に想定したのはX(s1=u, s2=u, s3=u)
といった3つの修飾をもった分子種であった。
ルールベース・モデルでは種seed
となる分子種を与え、そこから繰り返し反応則を適用して出来うる全ての分子種を芋づる的に生成する。ここで種となる分子種は後でWorld
に追加する分子種だと思えば良い。
In [18]:
m = get_model(seeds=[Species('X(s1=u, s2=u, s3=u)')])
print(len(m.reaction_rules()))
ここで与えたX(s1=u, s2=u, s3=u)
という種から12の反応が望み通りに得られることがわかる。
このモデルを使って計算してみると、
In [19]:
run_simulation(5, y0={'X(s1=u,s2=u,s3=u)': 120}, model=m,
species_list=('X', 'X(s1=p)', 'X(s2=p)', 'X(s3=p)'),
opt_kwargs={'ylim': (0, 130)})
In [20]:
with reaction_rules():
A(b) + B(b) > A(b^1).B(b^1) | 1
A(b^_, s=u) > A(b^_, s=p) | 2
In [21]:
m = get_model()
2つ目の反応則は修飾s
をu
からp
に変えるが、A
がb
を介して誰かと結合しているときにしか起こらない.
_
がワイルド・カード、すなわちどんなものとも合致する記号である。
誰かと結合しているA
はA(b^_)
と表現される。
修飾にワイルドカードを使うと、
A(s=_)
は修飾s
の状態が何であっても良いことを意味する。
何であっても良いならば書く必要ない気もするが、A
にs
という修飾があることを保証する。
単位分子種名にワイルドカードを使うと、
_(s=u)
と書けば状態u
の修飾s
を持つどんな分子種にも当てはまる。試すと、
In [22]:
with reaction_rules():
_(s=u) > _(s=p) | 1
m = get_model(seeds=(
Species('A(s=u)'), Species('B(s=u)'), Species('C(b^1,s=u).C(b^1,s=u)')))
run_simulation(
5, y0={'A(s=u)': 10, 'B(s=u)': 20, 'C(b^1,s=u).C(b^1,s=u)': 15}, model=m,
species_list=('A(s=u)', 'B(s=u)', 'C(s=u)', '_(s=u)'))
分子種の属性を決める場合にもワイルドカードが使える。
In [23]:
with species_attributes():
_ | {'D': 1, 'radius': 0.005}
In [24]:
m = get_model()
In [25]:
with species_attributes():
A | {'D': 1, 'location': 'C', 'dimension': 3}
B | {'D': 1, 'location': 'N', 'dimension': 3}
N | {'location': 'C', 'dimension': 3}
C | {'dimension': 3}
with reaction_rules():
A + N > B | 1e-4
B + C > A | 1e-4
m = get_model()
w = spatiocyte.World(ones(), 0.005)
w.bind_to(m)
w.add_structure(Species('C'), Sphere(0.5 * ones(), 0.441))
w.add_structure(Species('N'), Sphere(0.5 * ones(), 0.350))
w.add_molecules(Species('A'), 720)
In [26]:
viz.plot_world(w, species_list=('C', 'N'))
全ての状態を保存するにはFixedIntervalHDF5Observer
を使う。
In [27]:
sim = spatiocyte.Simulator(w)
obs1 = NumberObserver(('A', 'B'))
obs2 = FixedIntervalHDF5Observer(0.01, 'data/sample%03d.h5')
sim.run(0.5, (obs1, obs2))
viz.plot_number_observer(obs1)
あとはこのObserver
をviz.plot_movie
で可視化する。
In [28]:
mpl.rcParams.update(inline_rc)
In [29]:
viz.plot_movie(obs2, species_list=('A', 'B'))
In [30]:
import seaborn
seaborn.set(font_scale=1.5)
mpl.rc("figure", figsize=(6, 4))
ParaView(http://www.paraview.org/)というソフトウェアを使うと動画作成などより詳細な可視化が行える。
FixedIntervalCSVObserver
で状態をCSV形式で保存する。
In [31]:
with species_attributes():
A | {'D': 1, 'location': 'C', 'dimension': 3}
B | {'D': 1, 'location': 'N', 'dimension': 3}
N | {'location': 'C', 'dimension': 3}
C | {'dimension': 3}
with reaction_rules():
A + N > B | 1e-4
B + C > A | 1e-4
m = get_model()
w = spatiocyte.World(ones(), 0.005)
w.bind_to(m)
w.add_structure(Species('C'), Sphere(0.5 * ones(), 0.441))
w.add_structure(Species('N'), Sphere(0.5 * ones(), 0.350))
w.add_molecules(Species('A'), 720)
In [32]:
sim = spatiocyte.Simulator(w)
obs = FixedIntervalCSVObserver(0.01, 'data/sample%03d.csv', ('A', 'B'))
sim.run(0.5, obs)
File->Open
で保存したCSV形式のデータを選択する。保存した連番のファイルは下図のようにまとめて表示される。読み込んだら左下にあるProperties
でApply
ボタンを押す。Filters->Alphabetical->Table To Points
を選択し、左下からX
, Y
, Z Column
としてx
, y
, z
を選択しApply
ボタンを押す。Filters->Common->Glyph
を選択する。同様に左下のProperties
からGlyph Type
をSphere
に、Scale Mode
をscalar
にして下のScale Factor
横のReset using current data values
とヒントの出るボタンを押す。今回は4を入力してApplyボタンを押す。Properties
にColoring
という項目が増えるのでsid
を選ぶ。何も見えなければ左上のPipeline Browser
でGlyph1
の左の目玉がアクティブにする。Play
ボタンを押す。赤色が増える様子を確認したらFile->Save Animation...
から動画が保存できる。Macros->Add new macro...
を選び、ecell4paraview.pyからダウンロードしたecell4paraview.py
を選択する。Pipeline Browser
で読み込んだCSVファイルを選択してからMacros->ecell4paraview
を選択する。Factory
だけを切り替えることでモジュールが切り替えられる。
In [33]:
factory = ode.Factory()
# f = gillespie.Factory()
# f = meso.Factory(Integer3(4, 4, 4))
# f = spatiocyte.Factory(0.005)
w = factory.world(ones())
w.bind_to(m)
w.add_molecules(Species('C'), 60)
sim = factory.simulator(w)
obs = FixedIntervalNumberObserver(0.1, ('A', 'B', 'C'))
sim.run(10, obs)
run_simulation
でもFactory
を使うことでspatiocyte
のVoxel半径のような特殊な引数を扱える。
In [34]:
with species_attributes():
A | B | C | {'D': 1}
with reaction_rules():
A + B == C | (0.01, 0.3)
run_simulation(10, {'C': 60}, solver=('spatiocyte', 0.01))
Union
を使ってRod
を自前で作ってみる。X
分子からなる二量体はどのように表現すればよいか。また、X
の数を数えるときの扱いに関して試す。ルールベース・モデリングにおける反応則の練習: 二種類の単位分子種X
とY
があり、以下の反応が独立に成立するとき、何通りの分子種が存在するか?
X
同士は二量体を形成する。X
とY
は結合する。Y
には1つ修飾部位があり、2種類の状態のいずれかをとる。ただし、対称性に注意せよ。
FixedIntervalCSVObserver
でCSV形式のファイルに記録したが、テキストエディタや表計算ソフトなどで開いてみて実際にどのようなことが書き込まれているのか確認する。