-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcomplexation.py
158 lines (130 loc) · 5.04 KB
/
complexation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
"""
============
Complexation
============
This process encodes molecular simulation of macromolecular complexation,
in which monomers are assembled into complexes. Macromolecular complexation
is done by identifying complexation reactions that are possible (which are
reactions that have sufficient counts of all sub-components), performing one
randomly chosen possible reaction, and re-identifying all possible complexation
reactions. This process assumes that macromolecular complexes form spontaneously,
and that complexation reactions are fast and complete within the time step of the
simulation.
"""
# TODO(wcEcoli):
# - allow for shuffling when appropriate (maybe in another process)
# - handle protein complex dissociation
import numpy as np
from stochastic_arrow import StochasticSystem
from vivarium.core.composition import simulate_process
from ecoli.library.schema import numpy_schema, bulk_name_to_idx, counts, listener_schema
from ecoli.processes.registries import topology_registry
from ecoli.processes.partition import PartitionedProcess
# Register default topology for this process, associating it with process name
NAME = "ecoli-complexation"
TOPOLOGY = {"bulk": ("bulk",), "listeners": ("listeners",), "timestep": ("timestep",)}
topology_registry.register(NAME, TOPOLOGY)
class Complexation(PartitionedProcess):
"""Complexation PartitionedProcess"""
name = NAME
topology = TOPOLOGY
defaults = {
"stoichiometry": np.array([[]]),
"rates": np.array([]),
"molecule_names": [],
"seed": 0,
"reaction_ids": [],
"complex_ids": [],
"time_step": 1,
}
def __init__(self, parameters=None):
super().__init__(parameters)
self.stoichiometry = self.parameters["stoichiometry"]
self.rates = self.parameters["rates"]
self.molecule_names = self.parameters["molecule_names"]
self.molecule_idx = None
self.reaction_ids = self.parameters["reaction_ids"]
self.complex_ids = self.parameters["complex_ids"]
self.randomState = np.random.RandomState(seed=self.parameters["seed"])
self.seed = self.randomState.randint(2**31)
self.system = StochasticSystem(self.stoichiometry, random_seed=self.seed)
def ports_schema(self):
return {
"bulk": numpy_schema("bulk"),
"listeners": {
"complexation_listener": {
**listener_schema(
{
"complexation_events": (
[0] * len(self.reaction_ids),
self.reaction_ids,
)
}
)
},
},
"timestep": {"_default": self.parameters["time_step"]},
}
def calculate_request(self, timestep, states):
timestep = states["timestep"]
if self.molecule_idx is None:
self.molecule_idx = bulk_name_to_idx(
self.molecule_names, states["bulk"]["id"]
)
moleculeCounts = counts(states["bulk"], self.molecule_idx)
result = self.system.evolve(timestep, moleculeCounts, self.rates)
updatedMoleculeCounts = result["outcome"]
requests = {}
requests["bulk"] = [
(self.molecule_idx, np.fmax(moleculeCounts - updatedMoleculeCounts, 0))
]
return requests
def evolve_state(self, timestep, states):
timestep = states["timestep"]
substrate = counts(states["bulk"], self.molecule_idx)
result = self.system.evolve(timestep, substrate, self.rates)
complexationEvents = result["occurrences"]
outcome = result["outcome"] - substrate
# Write outputs to listeners
update = {
"bulk": [(self.molecule_idx, outcome)],
"listeners": {
"complexation_listener": {
"complexation_events": complexationEvents.astype(int)
}
},
}
return update
def test_complexation():
test_config = {
"stoichiometry": np.array(
[[-1, 1, 0], [0, -1, 1], [1, 0, -1], [-1, 0, 1], [1, -1, 0], [0, 1, -1]],
np.int64,
),
"rates": np.array([1, 1, 1, 1, 1, 1], np.float64),
"molecule_names": ["A", "B", "C"],
"seed": 1,
"reaction_ids": [1, 2, 3, 4, 5, 6],
"complex_ids": [1, 2, 3, 4, 5, 6],
}
complexation = Complexation(test_config)
state = {
"bulk": np.array(
[
("A", 10),
("B", 20),
("C", 30),
],
dtype=[("id", "U40"), ("count", int)],
)
}
settings = {"total_time": 10, "initial_state": state}
data = simulate_process(complexation, settings)
complexation_events = data["listeners"]["complexation_listener"][
"complexation_events"
]
assert isinstance(complexation_events[0], list)
assert isinstance(complexation_events[1], list)
print(data)
if __name__ == "__main__":
test_complexation()