Source code for ecoli.processes.spatiality.spatial_geometry

"""
================
Spatial Geometry
================

SpatialGeometry :term:`Process`  calculates geometric parameters of nodes a
nd edges utilized in diffusion_network.py. This process assumes E. coli is
a spherocylinder with constant radius. This process is currently unfinished.
This process assumes that there are properties of the nodes that specify
which type of compartment it is such that the geometry rules below apply.
This is not currently implemented in ecoli_spatial.py in vivarium-ecoli.
Much of the geometry rules have been specified, however it should be
checked to see if it leads to consistent results.

References:
 - width of 0.73 um: Cluzel et al., Nucleic Acids Research (2008)
 - strain: K-12 Frag1
 - periplasm width of 21 nm: Matias et al., J Bacteriology (2003)
 - cell density of 1100 g/L (from WCM): Baldwin et al., Arch microbiol. (1995)

.. WARNING:: This process is unfinished.
"""

import os
import numpy as np

from vivarium.core.process import Deriver
from vivarium.core.composition import (
    simulate_process,
    PROCESS_OUT_DIR,
)
from ecoli.library.schema import array_from


NAME = "spatial_geometry"
WIDTH = 0.73  # in um
PERIPLASM_WIDTH = 21  # in nm
DENSITY = 1100  # fg/um^3


[docs] class SpatialGeometry(Deriver): name = NAME defaults = { "nodes": [ "nucleoid", "periplasm", ], "edges": {}, "density": DENSITY, "mw": {}, "width": WIDTH, } def __init__(self, parameters=None): super().__init__(parameters) self.nodes = np.asarray(self.parameters["nodes"]) self.edges = self.parameters["edges"] self.mw = self.parameters["mw"] self.molecule_ids = self.parameters["mw"].keys() self.density = self.parameters["density"]
[docs] def initial_state(self, config=None): pass
[docs] def ports_schema(self): node_schema = { node_id: { "volume": { "_default": 1.0, }, "length": { "_default": 1.0, }, "radius": { "_default": 1.0, }, "molecules": { "*": { "_default": 0, } }, } for node_id in self.parameters["nodes"] } edge_schema = { edge_id: { "nodes": [], "cross_sectional_area": 1.0, } for edge_id in self.parameters["edges"].keys() } return {"nodes": node_schema, "edges": edge_schema}
[docs] def next_update(self, timestep, states): volume = np.zeros(len(self.nodes)) nodes = states["nodes"] length = [nodes[node_id]["length"] for node_id in self.nodes] cross_sectional_area = np.zeros(len(self.edges)) inner_radius = nodes["nucleoid"]["radius"] outer_radius = nodes["periplasm"]["radius"] + inner_radius for i, node_id in enumerate(self.nodes): # if nucleoid or nucleoid region of membrane nucleoid = True volume[i] = sum(array_from(nodes[node_id]["molecules"])) * self.density if nucleoid: length[i] = volume[i] / (np.pi * inner_radius**2) for i, edge_id in enumerate(self.edges): nodes = states[edge_id]["nodes"] nucleoid = "nucleoid" in nodes cytosol = "cytosol_front" or "cytosol_rear" in nodes periplasm = "periplasm" in nodes cytosol_inner_membrane = False cytosol_outer_membrane = False nucleoid_inner_membrane = False nucleoid_outer_membrane = False # series of if statements for each interface if nucleoid and cytosol: cross_sectional_area[i] = np.pi * inner_radius**2 continue # find if node is membrane if nucleoid and nucleoid_inner_membrane: node_id = "membrane" cross_sectional_area[i] = ( 2 * np.pi * inner_radius * states["nodes"][node_id]["length"] ) continue if cytosol and cytosol_inner_membrane: cross_sectional_area[i] = 2 * np.pi * inner_radius**2 continue if periplasm and nucleoid_inner_membrane: cross_sectional_area[i] = ( 2 * np.pi * inner_radius * states["nodes"][node_id]["length"] ) continue if periplasm and nucleoid_outer_membrane: cross_sectional_area[i] = ( 2 * np.pi * outer_radius * states["nodes"][node_id]["length"] ) continue if periplasm and cytosol_inner_membrane: cross_sectional_area[i] = 2 * np.pi * inner_radius**2 continue if periplasm and cytosol_outer_membrane: cross_sectional_area[i] = 2 * np.pi * outer_radius**2 continue node_update = { node_id: { "volume": volume[np.where(self.nodes == node_id)][0], "length": volume[np.where(self.nodes == node_id)][0], } for node_id in self.nodes } edge_update = {} return {**node_update, **edge_update}
# functions to configure and run the process
[docs] def run_spatial_geometry_process(): """ Run a simulation of the process. Returns: The simulation output. """ # initialize the process by passing in parameters parameters = {} spatial_geometry_process = SpatialGeometry(parameters) # declare the initial state, mirroring the ports structure initial_state = {} # run the simulation sim_settings = {"total_time": 10, "initial_state": initial_state} output = simulate_process(spatial_geometry_process, sim_settings) return output
def test_spatial_geometry_process(return_data=False): """ Test that the process runs correctly. This will be executed by pytest. """ output = run_spatial_geometry_process() # TODO(vivarium): Add assert statements to ensure correct performance. if return_data: return output
[docs] def main(): """Simulate the process and plot results.""" # make an output directory to save plots out_dir = os.path.join(PROCESS_OUT_DIR, NAME) if not os.path.exists(out_dir): os.makedirs(out_dir) output = test_spatial_geometry_process(return_data=True) assert output is not None
if __name__ == "__main__": main()