Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/simple readdy example #25

Open
wants to merge 6 commits into
base: maintenance
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions env.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ name: vivarium-models
channels:
- conda-forge
dependencies:
- python=3.8
- conda-forge::readdy
- python=3.9
- readdy==2.0.9
- pip
- pip:
- "vivarium_models @ git+https://github.com/simularium/vivarium-models.git"
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"vivarium-core",
"vivarium_medyan @ git+https://github.com/vivarium-collective/vivarium-MEDYAN.git",
"vivarium_cytosim @ git+https://github.com/vivarium-collective/vivarium-cytosim.git",
"vivarium_readdy @ git+https://github.com/vivarium-collective/vivarium-ReaDDy.git@monomers-ports",
"simularium_readdy_models @ git+https://github.com/simularium/readdy-models.git",
"simulariumio",
]
Expand Down
51 changes: 3 additions & 48 deletions vivarium_models/processes/readdy_actin_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
ActinAnalyzer,
)
from simularium_readdy_models import ReaddyUtil
from vivarium_models.util import create_monomer_update, format_monomer_results
from vivarium_readdy import create_monomer_update, monomer_ports_schema
from ..util import format_monomer_results
from vivarium_models.library.scan import Scan

NAME = "ReaDDy_actin"
Expand Down Expand Up @@ -69,53 +70,7 @@ def __init__(self, parameters=None):
self.readdy_simulation = actin_simulation.simulation

def ports_schema(self):
return {
"monomers": {
"box_center": {
"_default": np.array([1000.0, 0.0, 0.0]),
"_updater": "set",
"_emit": True,
},
"box_size": {
"_default": 500.0,
"_updater": "set",
"_emit": True,
},
"topologies": {
"*": {
"type_name": {
"_default": "",
"_updater": "set",
"_emit": True,
},
"particle_ids": {
"_default": [],
"_updater": "set",
"_emit": True,
},
}
},
"particles": {
"*": {
"type_name": {
"_default": "",
"_updater": "set",
"_emit": True,
},
"position": {
"_default": np.zeros(3),
"_updater": "set",
"_emit": True,
},
"neighbor_ids": {
"_default": [],
"_updater": "set",
"_emit": True,
},
}
},
}
}
return monomer_ports_schema

def initial_state(self, config=None):
# TODO: make this more general
Expand Down
134 changes: 39 additions & 95 deletions vivarium_models/processes/simularium_emitter.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict
from typing import Any, Dict, List

from vivarium.core.emitter import Emitter

Expand All @@ -10,14 +10,16 @@
AgentData,
MetaData,
UnitData,
DisplayData,
DISPLAY_TYPE,
)


class SimulariumEmitter(Emitter):
def __init__(self, config: Dict[str, str]) -> None:
super().__init__(config)
self.configuration_data = None
self.saved_data: Dict[float, Dict[str, Any]] = {}
self.saved_data: List[Dict[str, Any]] = []

def emit(self, data: Dict[str, Any]) -> None:
"""
Expand All @@ -29,17 +31,14 @@ def emit(self, data: Dict[str, Any]) -> None:
self.configuration_data = data["data"]
assert "processes" in self.configuration_data, "please emit processes"
if data["table"] == "history":
emit_data = data["data"]
time = emit_data["time"]
self.saved_data[time] = {
key: value for key, value in emit_data.items() if key not in ["time"]
}
self.saved_data.append(data["data"])

def get_simularium_fibers(self, time, fibers, actin_radius, trajectory):
def get_simularium_fibers(self, time, fibers, trajectory):
"""
Shape fiber state data into Simularium fiber agents
"""
n_agents = 0
actin_radius = 3.0
time_index = len(trajectory["times"])
trajectory["times"].append(time)
trajectory["unique_ids"].append([])
Expand All @@ -59,7 +58,7 @@ def get_simularium_fibers(self, time, fibers, actin_radius, trajectory):
trajectory["radii"].append(n_agents * [actin_radius])
return trajectory

def get_simularium_monomers(self, time, monomers, actin_radius, trajectory):
def get_simularium_monomers(self, time, monomers, trajectory):
"""
Shape monomer state data into Simularium agents
"""
Expand All @@ -68,13 +67,21 @@ def get_simularium_monomers(self, time, monomers, actin_radius, trajectory):
trajectory["unique_ids"].append([])
trajectory["type_names"].append([])
trajectory["positions"].append([])
trajectory["radii"].append([])
edge_ids = []
edge_positions = []
for particle_id in monomers["particles"]:
particle = monomers["particles"][particle_id]
trajectory["unique_ids"][time_index].append(int(particle_id))
trajectory["type_names"][time_index].append(particle["type_name"])
# HACK needed until simulariumio default display data fix
Copy link
Contributor

@ascibisz ascibisz May 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the default display data fix got merged in simulariumio, unless there's another default display data bug then the one I'm thinking of?

if particle["type_name"] not in trajectory["display_data"]:
trajectory["display_data"][particle["type_name"]] = DisplayData(
name=particle["type_name"],
display_type=DISPLAY_TYPE.SPHERE,
)
trajectory["positions"][time_index].append(np.array(particle["position"]))
trajectory["radii"][time_index].append(particle["radius"])
# visualize edges between particles
for neighbor_id in particle["neighbor_ids"]:
neighbor_id_str = str(neighbor_id)
Expand All @@ -101,7 +108,6 @@ def get_simularium_monomers(self, time, monomers, actin_radius, trajectory):
trajectory["unique_ids"][time_index] += [1000 + i for i in range(n_edges)]
trajectory["type_names"][time_index] += ["edge" for edge in range(n_edges)]
trajectory["positions"][time_index] += n_edges * [[0.0, 0.0, 0.0]]
trajectory["radii"].append(n_agents * [actin_radius])
trajectory["radii"][time_index] += n_edges * [1.0]
trajectory["n_subpoints"].append(n_agents * [0])
trajectory["n_subpoints"][time_index] += n_edges * [2]
Expand Down Expand Up @@ -167,7 +173,7 @@ def get_agent_data_from_jagged_lists(trajectory, scale_factor) -> AgentData:
Shape a dictionary of jagged lists into a Simularium AgentData object
"""
return AgentData(
times=np.arange(len(trajectory["times"])),
times=trajectory["times"],
n_agents=np.array(trajectory["n_agents"]),
viz_types=SimulariumEmitter.fill_df(
pd.DataFrame(trajectory["viz_types"]), 1000.0
Expand All @@ -187,17 +193,17 @@ def get_agent_data_from_jagged_lists(trajectory, scale_factor) -> AgentData:
).to_numpy(dtype=int),
subpoints=scale_factor
* SimulariumEmitter.get_subpoints_numpy_array(trajectory),
display_data=trajectory["display_data"],
)

@staticmethod
def get_simularium_converter(
trajectory, box_dimensions, scale_factor
trajectory, box_dimensions, scale_factor, time_units, spatial_units
) -> TrajectoryConverter:
"""
Shape a dictionary of jagged lists into a Simularium TrajectoryData object
and provide it to a TrajectoryConverter for conversion
"""
spatial_units = UnitData("nm")
spatial_units.multiply(1 / scale_factor)
return TrajectoryConverter(
TrajectoryData(
Expand All @@ -207,36 +213,18 @@ def get_simularium_converter(
agent_data=SimulariumEmitter.get_agent_data_from_jagged_lists(
trajectory, scale_factor
),
time_units=UnitData("count"),
time_units=time_units,
spatial_units=spatial_units,
)
)

@staticmethod
def get_active_simulator(choices) -> str:
"""
Use choices from state to determine which simulator ran
"""
medyan_active = "medyan_active" in choices and choices["medyan_active"]
readdy_active = "readdy_active" in choices and choices["readdy_active"]
cytosim_active = "cytosim_active" in choices and choices["cytosim_active"]

if medyan_active and not readdy_active and not cytosim_active:
return "medyan"
elif readdy_active and not medyan_active and not cytosim_active:
return "readdy"
elif cytosim_active and not medyan_active and not readdy_active:
return "cytosim"

def get_data(self) -> dict:
"""
Save the accumulated timeseries history of "emitted" data to file
"""
if "readdy_actin" in self.configuration_data:
actin_radius = self.configuration_data["readdy_actin"]["actin_radius"]
else:
actin_radius = 3.0 # TODO add to MEDYAN config
box_dimensions = None
box_size = None
time_units = None
spatial_units = None
trajectory = {
"times": [],
"n_agents": [],
Expand All @@ -247,66 +235,22 @@ def get_data(self) -> dict:
"radii": [],
"n_subpoints": [],
"subpoints": [],
"display_data": {},
}
times = list(self.saved_data.keys())
times.sort()
vizualize_time_index = 0
for time, state in self.saved_data.items():
print(f"time = {time}")
index = times.index(time)
prev_simulator = "none"
if index > 0:
prev_simulator = SimulariumEmitter.get_active_simulator(
self.saved_data[times[index - 1]]["choices"]
)
current_simulator = SimulariumEmitter.get_active_simulator(state["choices"])
print(f"prev_simulator = {prev_simulator}")
print(f"current_simulator = {current_simulator}")
"""visualize the first frame in the simulator that started first
then subsequent frames according the the simulator that ran
right before that time point"""
if prev_simulator == "none":
if current_simulator == "medyan" or current_simulator == "cytosim":
print(f" visualize current {current_simulator}")
if box_dimensions is None:
box_dimensions = np.array(state["fibers_box_extent"])
trajectory = self.get_simularium_fibers(
vizualize_time_index,
state["fibers"],
actin_radius,
trajectory,
)
vizualize_time_index += 1
if current_simulator == "readdy":
print(" visualize current readdy")
trajectory = self.get_simularium_monomers(
vizualize_time_index,
state["monomers"],
actin_radius,
trajectory,
)
vizualize_time_index += 1
elif prev_simulator == "medyan" or prev_simulator == "cytosim":
print(f" visualize previous {prev_simulator}")
if box_dimensions is None:
box_dimensions = np.array(state["fibers_box_extent"])
trajectory = self.get_simularium_fibers(
vizualize_time_index,
state["fibers"],
actin_radius,
trajectory,
)
vizualize_time_index += 1
elif prev_simulator == "readdy":
print(" visualize readdy")
trajectory = self.get_simularium_monomers(
vizualize_time_index,
state["monomers"],
actin_radius,
trajectory,
)
vizualize_time_index += 1
for state in self.saved_data:
if box_size is None:
box_size = state["monomers"]["box_size"]
if time_units is None:
time_units = state["time_units"]
if spatial_units is None:
spatial_units = state["spatial_units"]
trajectory = self.get_simularium_monomers(
state["time"],
state["monomers"],
trajectory,
)
simularium_converter = SimulariumEmitter.get_simularium_converter(
trajectory, box_dimensions, 0.1
trajectory, box_size, 0.1, UnitData(time_units), UnitData(spatial_units)
)
simularium_converter.save("out/actin_test")
simularium_converter.save("out/test")
return {"simularium_converter": simularium_converter}
Loading