gen_geometry_object.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. /******************************************************************************
  2. *
  3. * Copyright (C) 2021 by
  4. * The Salk Institute for Biological Studies
  5. *
  6. * Use of this source code is governed by an MIT-style
  7. * license that can be found in the LICENSE file or at
  8. * https://opensource.org/licenses/MIT.
  9. *
  10. ******************************************************************************/
  11. #include <sstream>
  12. #include "api/pybind11_stl_include.h"
  13. #include "api/python_export_utils.h"
  14. #include "gen_geometry_object.h"
  15. #include "api/geometry_object.h"
  16. #include "api/color.h"
  17. #include "api/initial_surface_release.h"
  18. #include "api/region.h"
  19. #include "api/surface_class.h"
  20. #include "api/surface_region.h"
  21. namespace MCell {
  22. namespace API {
  23. void GenGeometryObject::check_semantics() const {
  24. if (!is_set(name)) {
  25. throw ValueError("Parameter 'name' must be set.");
  26. }
  27. if (!is_set(vertex_list)) {
  28. throw ValueError("Parameter 'vertex_list' must be set and the value must not be an empty list.");
  29. }
  30. if (!is_set(wall_list)) {
  31. throw ValueError("Parameter 'wall_list' must be set and the value must not be an empty list.");
  32. }
  33. }
  34. void GenGeometryObject::set_initialized() {
  35. vec_set_initialized(surface_regions);
  36. if (is_set(surface_class)) {
  37. surface_class->set_initialized();
  38. }
  39. vec_set_initialized(initial_surface_releases);
  40. if (is_set(initial_color)) {
  41. initial_color->set_initialized();
  42. }
  43. if (is_set(left_node)) {
  44. left_node->set_initialized();
  45. }
  46. if (is_set(right_node)) {
  47. right_node->set_initialized();
  48. }
  49. initialized = true;
  50. }
  51. void GenGeometryObject::set_all_attributes_as_default_or_unset() {
  52. class_name = "GeometryObject";
  53. name = STR_UNSET;
  54. vertex_list = std::vector<std::vector<double>>();
  55. wall_list = std::vector<std::vector<int>>();
  56. is_bngl_compartment = false;
  57. surface_compartment_name = STR_UNSET;
  58. surface_regions = std::vector<std::shared_ptr<SurfaceRegion>>();
  59. surface_class = nullptr;
  60. initial_surface_releases = std::vector<std::shared_ptr<InitialSurfaceRelease>>();
  61. initial_color = nullptr;
  62. node_type = RegionNodeType::UNSET;
  63. left_node = nullptr;
  64. right_node = nullptr;
  65. }
  66. std::shared_ptr<GeometryObject> GenGeometryObject::copy_geometry_object() const {
  67. std::shared_ptr<GeometryObject> res = std::make_shared<GeometryObject>(DefaultCtorArgType());
  68. res->class_name = class_name;
  69. res->name = name;
  70. res->vertex_list = vertex_list;
  71. res->wall_list = wall_list;
  72. res->is_bngl_compartment = is_bngl_compartment;
  73. res->surface_compartment_name = surface_compartment_name;
  74. res->surface_regions = surface_regions;
  75. res->surface_class = surface_class;
  76. res->initial_surface_releases = initial_surface_releases;
  77. res->initial_color = initial_color;
  78. res->node_type = node_type;
  79. res->left_node = left_node;
  80. res->right_node = right_node;
  81. return res;
  82. }
  83. std::shared_ptr<GeometryObject> GenGeometryObject::deepcopy_geometry_object(py::dict) const {
  84. std::shared_ptr<GeometryObject> res = std::make_shared<GeometryObject>(DefaultCtorArgType());
  85. res->class_name = class_name;
  86. res->name = name;
  87. res->vertex_list = vertex_list;
  88. res->wall_list = wall_list;
  89. res->is_bngl_compartment = is_bngl_compartment;
  90. res->surface_compartment_name = surface_compartment_name;
  91. for (const auto& item: surface_regions) {
  92. res->surface_regions.push_back((is_set(item)) ? item->deepcopy_surface_region() : nullptr);
  93. }
  94. res->surface_class = is_set(surface_class) ? surface_class->deepcopy_surface_class() : nullptr;
  95. for (const auto& item: initial_surface_releases) {
  96. res->initial_surface_releases.push_back((is_set(item)) ? item->deepcopy_initial_surface_release() : nullptr);
  97. }
  98. res->initial_color = is_set(initial_color) ? initial_color->deepcopy_color() : nullptr;
  99. res->node_type = node_type;
  100. res->left_node = is_set(left_node) ? left_node->deepcopy_region() : nullptr;
  101. res->right_node = is_set(right_node) ? right_node->deepcopy_region() : nullptr;
  102. return res;
  103. }
  104. bool GenGeometryObject::__eq__(const GeometryObject& other) const {
  105. return
  106. name == other.name &&
  107. vertex_list == other.vertex_list &&
  108. wall_list == other.wall_list &&
  109. is_bngl_compartment == other.is_bngl_compartment &&
  110. surface_compartment_name == other.surface_compartment_name &&
  111. vec_ptr_eq(surface_regions, other.surface_regions) &&
  112. (
  113. (is_set(surface_class)) ?
  114. (is_set(other.surface_class) ?
  115. (surface_class->__eq__(*other.surface_class)) :
  116. false
  117. ) :
  118. (is_set(other.surface_class) ?
  119. false :
  120. true
  121. )
  122. ) &&
  123. vec_ptr_eq(initial_surface_releases, other.initial_surface_releases) &&
  124. (
  125. (is_set(initial_color)) ?
  126. (is_set(other.initial_color) ?
  127. (initial_color->__eq__(*other.initial_color)) :
  128. false
  129. ) :
  130. (is_set(other.initial_color) ?
  131. false :
  132. true
  133. )
  134. ) &&
  135. node_type == other.node_type &&
  136. (
  137. (is_set(left_node)) ?
  138. (is_set(other.left_node) ?
  139. (left_node->__eq__(*other.left_node)) :
  140. false
  141. ) :
  142. (is_set(other.left_node) ?
  143. false :
  144. true
  145. )
  146. ) &&
  147. (
  148. (is_set(right_node)) ?
  149. (is_set(other.right_node) ?
  150. (right_node->__eq__(*other.right_node)) :
  151. false
  152. ) :
  153. (is_set(other.right_node) ?
  154. false :
  155. true
  156. )
  157. ) ;
  158. }
  159. bool GenGeometryObject::eq_nonarray_attributes(const GeometryObject& other, const bool ignore_name) const {
  160. return
  161. (ignore_name || name == other.name) &&
  162. true /*vertex_list*/ &&
  163. true /*wall_list*/ &&
  164. is_bngl_compartment == other.is_bngl_compartment &&
  165. surface_compartment_name == other.surface_compartment_name &&
  166. true /*surface_regions*/ &&
  167. (
  168. (is_set(surface_class)) ?
  169. (is_set(other.surface_class) ?
  170. (surface_class->__eq__(*other.surface_class)) :
  171. false
  172. ) :
  173. (is_set(other.surface_class) ?
  174. false :
  175. true
  176. )
  177. ) &&
  178. true /*initial_surface_releases*/ &&
  179. (
  180. (is_set(initial_color)) ?
  181. (is_set(other.initial_color) ?
  182. (initial_color->__eq__(*other.initial_color)) :
  183. false
  184. ) :
  185. (is_set(other.initial_color) ?
  186. false :
  187. true
  188. )
  189. ) &&
  190. node_type == other.node_type &&
  191. (
  192. (is_set(left_node)) ?
  193. (is_set(other.left_node) ?
  194. (left_node->__eq__(*other.left_node)) :
  195. false
  196. ) :
  197. (is_set(other.left_node) ?
  198. false :
  199. true
  200. )
  201. ) &&
  202. (
  203. (is_set(right_node)) ?
  204. (is_set(other.right_node) ?
  205. (right_node->__eq__(*other.right_node)) :
  206. false
  207. ) :
  208. (is_set(other.right_node) ?
  209. false :
  210. true
  211. )
  212. ) ;
  213. }
  214. std::string GenGeometryObject::to_str(const bool all_details, const std::string ind) const {
  215. std::stringstream ss;
  216. ss << get_object_name() << ": " <<
  217. "name=" << name << ", " <<
  218. "vertex_list=" << vec_nonptr_to_str(vertex_list, all_details, ind + " ") << ", " <<
  219. "wall_list=" << vec_nonptr_to_str(wall_list, all_details, ind + " ") << ", " <<
  220. "is_bngl_compartment=" << is_bngl_compartment << ", " <<
  221. "surface_compartment_name=" << surface_compartment_name << ", " <<
  222. "\n" << ind + " " << "surface_regions=" << vec_ptr_to_str(surface_regions, all_details, ind + " ") << ", " << "\n" << ind + " " <<
  223. "surface_class=" << "(" << ((surface_class != nullptr) ? surface_class->to_str(all_details, ind + " ") : "null" ) << ")" << ", " << "\n" << ind + " " <<
  224. "initial_surface_releases=" << vec_ptr_to_str(initial_surface_releases, all_details, ind + " ") << ", " << "\n" << ind + " " <<
  225. "initial_color=" << "(" << ((initial_color != nullptr) ? initial_color->to_str(all_details, ind + " ") : "null" ) << ")" << ", " << "\n" << ind + " " <<
  226. "node_type=" << node_type << ", " <<
  227. "\n" << ind + " " << "left_node=" << "(" << ((left_node != nullptr) ? left_node->to_str(all_details, ind + " ") : "null" ) << ")" << ", " << "\n" << ind + " " <<
  228. "right_node=" << "(" << ((right_node != nullptr) ? right_node->to_str(all_details, ind + " ") : "null" ) << ")";
  229. return ss.str();
  230. }
  231. py::class_<GeometryObject> define_pybinding_GeometryObject(py::module& m) {
  232. return py::class_<GeometryObject, Region, std::shared_ptr<GeometryObject>>(m, "GeometryObject", "Class represents geometry objects defined by triangular surface elements.")
  233. .def(
  234. py::init<
  235. const std::string&,
  236. const std::vector<std::vector<double>>,
  237. const std::vector<std::vector<int>>,
  238. const bool,
  239. const std::string&,
  240. const std::vector<std::shared_ptr<SurfaceRegion>>,
  241. std::shared_ptr<SurfaceClass>,
  242. const std::vector<std::shared_ptr<InitialSurfaceRelease>>,
  243. std::shared_ptr<Color>,
  244. const RegionNodeType,
  245. std::shared_ptr<Region>,
  246. std::shared_ptr<Region>
  247. >(),
  248. py::arg("name"),
  249. py::arg("vertex_list"),
  250. py::arg("wall_list"),
  251. py::arg("is_bngl_compartment") = false,
  252. py::arg("surface_compartment_name") = STR_UNSET,
  253. py::arg("surface_regions") = std::vector<std::shared_ptr<SurfaceRegion>>(),
  254. py::arg("surface_class") = nullptr,
  255. py::arg("initial_surface_releases") = std::vector<std::shared_ptr<InitialSurfaceRelease>>(),
  256. py::arg("initial_color") = nullptr,
  257. py::arg("node_type") = RegionNodeType::UNSET,
  258. py::arg("left_node") = nullptr,
  259. py::arg("right_node") = nullptr
  260. )
  261. .def("check_semantics", &GeometryObject::check_semantics)
  262. .def("__copy__", &GeometryObject::copy_geometry_object)
  263. .def("__deepcopy__", &GeometryObject::deepcopy_geometry_object, py::arg("memo"))
  264. .def("__str__", &GeometryObject::to_str, py::arg("all_details") = false, py::arg("ind") = std::string(""))
  265. .def("__eq__", &GeometryObject::__eq__, py::arg("other"))
  266. .def("translate", &GeometryObject::translate, py::arg("move"), "Move object by a specified vector. \nCannot be called after model was initialized.\n\n- move: 3D vector [x, y, z] that will be added to each vertex of this object.\n\n")
  267. .def("dump", &GeometryObject::dump)
  268. .def_property("name", &GeometryObject::get_name, &GeometryObject::set_name, "Name of the object. Also represents BNGL compartment name if 'is_bngl_compartment' is True.\n")
  269. .def_property("vertex_list", &GeometryObject::get_vertex_list, &GeometryObject::set_vertex_list, py::return_value_policy::reference, "List of [x,y,z] triplets specifying positions of individual vertices of each triangle.\n \n")
  270. .def_property("wall_list", &GeometryObject::get_wall_list, &GeometryObject::set_wall_list, py::return_value_policy::reference, "List of [a,b,c] triplets specifying each wall, individual values are indices into the \nvertex_list attribute.\n")
  271. .def_property("is_bngl_compartment", &GeometryObject::get_is_bngl_compartment, &GeometryObject::set_is_bngl_compartment, "Set to True if this object represents a 3D BNGL compartment. \nIts name will be then the BNGL compartment name. \n")
  272. .def_property("surface_compartment_name", &GeometryObject::get_surface_compartment_name, &GeometryObject::set_surface_compartment_name, "When is_bngl_compartment is True, this attribute can be set to specify its \nmembrane (2D) compartment name.\n")
  273. .def_property("surface_regions", &GeometryObject::get_surface_regions, &GeometryObject::set_surface_regions, py::return_value_policy::reference, "All surface regions associated with this geometry object.\n")
  274. .def_property("surface_class", &GeometryObject::get_surface_class, &GeometryObject::set_surface_class, "Surface class for the whole object's surface. It is applied to the whole surface of this object \nexcept for those surface regions that have their specific surface class set explicitly.\n")
  275. .def_property("initial_surface_releases", &GeometryObject::get_initial_surface_releases, &GeometryObject::set_initial_surface_releases, py::return_value_policy::reference, "Each item in this list defines either density or number of molecules to be released on this surface \nregions when simulation starts.\n")
  276. .def_property("initial_color", &GeometryObject::get_initial_color, &GeometryObject::set_initial_color, "Initial color for this geometry object. If a surface region has its color set, its value \nis used for the walls of that surface region.\n")
  277. ;
  278. }
  279. std::string GenGeometryObject::export_to_python(std::ostream& out, PythonExportContext& ctx) {
  280. if (!export_even_if_already_exported() && ctx.already_exported(this)) {
  281. return ctx.get_exported_name(this);
  282. }
  283. std::string exported_name = std::string("geometry_object") + "_" + (is_set(name) ? fix_id(name) : std::to_string(ctx.postinc_counter("geometry_object")));
  284. if (!export_even_if_already_exported()) {
  285. ctx.add_exported(this, exported_name);
  286. }
  287. bool str_export = export_as_string_without_newlines();
  288. std::string nl = "";
  289. std::string ind = " ";
  290. std::stringstream ss;
  291. if (!str_export) {
  292. nl = "\n";
  293. ind = " ";
  294. ss << exported_name << " = ";
  295. }
  296. ss << "m.GeometryObject(" << nl;
  297. if (node_type != RegionNodeType::UNSET) {
  298. ss << ind << "node_type = " << node_type << "," << nl;
  299. }
  300. if (is_set(left_node)) {
  301. ss << ind << "left_node = " << left_node->export_to_python(out, ctx) << "," << nl;
  302. }
  303. if (is_set(right_node)) {
  304. ss << ind << "right_node = " << right_node->export_to_python(out, ctx) << "," << nl;
  305. }
  306. ss << ind << "name = " << "'" << name << "'" << "," << nl;
  307. ss << ind << "vertex_list = " << export_vec_vertex_list(out, ctx, exported_name) << "," << nl;
  308. ss << ind << "wall_list = " << export_vec_wall_list(out, ctx, exported_name) << "," << nl;
  309. if (is_bngl_compartment != false) {
  310. ss << ind << "is_bngl_compartment = " << is_bngl_compartment << "," << nl;
  311. }
  312. if (surface_compartment_name != STR_UNSET) {
  313. ss << ind << "surface_compartment_name = " << "'" << surface_compartment_name << "'" << "," << nl;
  314. }
  315. if (surface_regions != std::vector<std::shared_ptr<SurfaceRegion>>() && !skip_vectors_export()) {
  316. ss << ind << "surface_regions = " << export_vec_surface_regions(out, ctx, exported_name) << "," << nl;
  317. }
  318. if (is_set(surface_class)) {
  319. ss << ind << "surface_class = " << surface_class->export_to_python(out, ctx) << "," << nl;
  320. }
  321. if (initial_surface_releases != std::vector<std::shared_ptr<InitialSurfaceRelease>>() && !skip_vectors_export()) {
  322. ss << ind << "initial_surface_releases = " << export_vec_initial_surface_releases(out, ctx, exported_name) << "," << nl;
  323. }
  324. if (is_set(initial_color)) {
  325. ss << ind << "initial_color = " << initial_color->export_to_python(out, ctx) << "," << nl;
  326. }
  327. ss << ")" << nl << nl;
  328. if (!str_export) {
  329. out << ss.str();
  330. return exported_name;
  331. }
  332. else {
  333. return ss.str();
  334. }
  335. }
  336. std::string GenGeometryObject::export_vec_vertex_list(std::ostream& out, PythonExportContext& ctx, const std::string& parent_name) {
  337. // does not print the array itself to 'out' and returns the whole list
  338. std::stringstream ss;
  339. ss << "[";
  340. for (size_t i = 0; i < vertex_list.size(); i++) {
  341. const auto& item = vertex_list[i];
  342. if (i == 0) {
  343. ss << " ";
  344. }
  345. else if (i % 16 == 0) {
  346. ss << "\n ";
  347. }
  348. ss << "[";
  349. for (const auto& value: item) {
  350. ss << f_to_str(value) << ", ";
  351. }
  352. ss << "], ";
  353. }
  354. ss << "]";
  355. return ss.str();
  356. }
  357. std::string GenGeometryObject::export_vec_wall_list(std::ostream& out, PythonExportContext& ctx, const std::string& parent_name) {
  358. // does not print the array itself to 'out' and returns the whole list
  359. std::stringstream ss;
  360. ss << "[";
  361. for (size_t i = 0; i < wall_list.size(); i++) {
  362. const auto& item = wall_list[i];
  363. if (i == 0) {
  364. ss << " ";
  365. }
  366. else if (i % 16 == 0) {
  367. ss << "\n ";
  368. }
  369. ss << "[";
  370. for (const auto& value: item) {
  371. ss << value << ", ";
  372. }
  373. ss << "], ";
  374. }
  375. ss << "]";
  376. return ss.str();
  377. }
  378. std::string GenGeometryObject::export_vec_surface_regions(std::ostream& out, PythonExportContext& ctx, const std::string& parent_name) {
  379. // does not print the array itself to 'out' and returns the whole list
  380. std::stringstream ss;
  381. ss << "[";
  382. for (size_t i = 0; i < surface_regions.size(); i++) {
  383. const auto& item = surface_regions[i];
  384. if (i == 0) {
  385. ss << " ";
  386. }
  387. else if (i % 16 == 0) {
  388. ss << "\n ";
  389. }
  390. if (!item->skip_python_export()) {
  391. std::string name = item->export_to_python(out, ctx);
  392. ss << name << ", ";
  393. }
  394. }
  395. ss << "]";
  396. return ss.str();
  397. }
  398. std::string GenGeometryObject::export_vec_initial_surface_releases(std::ostream& out, PythonExportContext& ctx, const std::string& parent_name) {
  399. // does not print the array itself to 'out' and returns the whole list
  400. std::stringstream ss;
  401. ss << "[";
  402. for (size_t i = 0; i < initial_surface_releases.size(); i++) {
  403. const auto& item = initial_surface_releases[i];
  404. if (i == 0) {
  405. ss << " ";
  406. }
  407. else if (i % 16 == 0) {
  408. ss << "\n ";
  409. }
  410. if (!item->skip_python_export()) {
  411. std::string name = item->export_to_python(out, ctx);
  412. ss << name << ", ";
  413. }
  414. }
  415. ss << "]";
  416. return ss.str();
  417. }
  418. } // namespace API
  419. } // namespace MCell