Coverage for src/cell_abm_pipeline/tasks/physicell/convert_physicell_to_simularium.py: 0%
44 statements
« prev ^ index » next coverage.py v7.1.0, created at 2024-06-05 19:14 +0000
« prev ^ index » next coverage.py v7.1.0, created at 2024-06-05 19:14 +0000
1import json
2import tempfile
3from tarfile import TarFile
5import numpy as np
6from simulariumio import DISPLAY_TYPE, CameraData, DisplayData, JsonWriter, MetaData, UnitData
7from simulariumio.filters import TranslateFilter
8from simulariumio.physicell import PhysicellConverter, PhysicellData
11def convert_physicell_to_simularium(
12 tar_file: TarFile,
13 box_size: tuple[float, float, float],
14 timestep: float,
15 frame_spec: tuple[float, float, float],
16 substrate_color: str,
17 cell_colors: list[str],
18 max_owner_cells: int = 10000,
19) -> str:
20 with tempfile.TemporaryDirectory() as temp_directory:
21 # Extract specified contents of archive into temporary directory.
22 tar_file.extract("initial_mesh0.mat", temp_directory)
23 for timepoint in np.arange(*frame_spec):
24 tar_file.extract(f"output{timepoint:08d}.xml", temp_directory)
25 tar_file.extract(f"output{timepoint:08d}_cells_physicell.mat", temp_directory)
27 # Set sizing.
28 box_size_array = np.array(box_size)
29 scale = 0.1
30 offset = scale * (-0.5 * box_size_array)
32 # Create data object.
33 data = PhysicellData(
34 timestep=timestep,
35 path_to_output_dir=temp_directory,
36 meta_data=MetaData(
37 box_size=box_size_array,
38 scale_factor=scale,
39 camera_defaults=CameraData(position=np.array([30.0, -10.0, 30.0])),
40 ),
41 display_data={
42 0: DisplayData(
43 name="Substrate",
44 display_type=DISPLAY_TYPE.SPHERE,
45 )
46 },
47 time_units=UnitData("min"),
48 )
50 # Create converter object.
51 converter = PhysicellConverter(data)
52 converter._data.spatial_units = UnitData(name="micron", magnitude=10.0)
54 # Update agent names.
55 type_names = []
56 for time_index, _ in enumerate(converter._data.agent_data.types):
57 for agent_index, _ in enumerate(converter._data.agent_data.types[time_index]):
58 tn = converter._data.agent_data.types[time_index][agent_index]
59 new_name = ""
61 if "Substrate" in tn:
62 new_name = "Substrate"
64 if "cell" in tn:
65 cell_id = int(tn[4 : tn.index("#")])
67 while cell_id > max_owner_cells:
68 cell_id -= max_owner_cells
70 new_name = "Stem cell#" + str(cell_id)
72 if new_name not in type_names:
73 type_names.append(new_name)
75 if not new_name:
76 continue
78 converter._data.agent_data.types[time_index][agent_index] = new_name
80 # Set substrate agent color.
81 converter._data.agent_data.display_data = {
82 "Substrate": DisplayData(
83 name="Substrate",
84 display_type=DISPLAY_TYPE.SPHERE,
85 color=substrate_color,
86 )
87 }
89 # Set cell agent colors.
90 color_map = {
91 type_name: cell_colors[type_index % len(cell_colors)]
92 for type_index, type_name in enumerate(type_names)
93 }
94 for type_name in type_names:
95 converter._data.agent_data.display_data[type_name] = DisplayData(
96 name=type_name,
97 display_type=DISPLAY_TYPE.SPHERE,
98 color=color_map[type_name],
99 )
101 # Remove the huge cell artifact.
102 converter._data.agent_data.n_agents[0] -= 1
104 # Center cells in box.
105 filtered_data = converter.filter_data([TranslateFilter(default_translation=offset)])
107 json_data = JsonWriter.format_trajectory_data(filtered_data)
108 return json.dumps(json_data)