gen_surface_region.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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_surface_region.h"
  15. #include "api/surface_region.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. namespace MCell {
  21. namespace API {
  22. void GenSurfaceRegion::check_semantics() const {
  23. if (!is_set(name)) {
  24. throw ValueError("Parameter 'name' must be set.");
  25. }
  26. if (!is_set(wall_indices)) {
  27. throw ValueError("Parameter 'wall_indices' must be set and the value must not be an empty list.");
  28. }
  29. }
  30. void GenSurfaceRegion::set_initialized() {
  31. if (is_set(surface_class)) {
  32. surface_class->set_initialized();
  33. }
  34. vec_set_initialized(initial_surface_releases);
  35. if (is_set(initial_color)) {
  36. initial_color->set_initialized();
  37. }
  38. if (is_set(left_node)) {
  39. left_node->set_initialized();
  40. }
  41. if (is_set(right_node)) {
  42. right_node->set_initialized();
  43. }
  44. initialized = true;
  45. }
  46. void GenSurfaceRegion::set_all_attributes_as_default_or_unset() {
  47. class_name = "SurfaceRegion";
  48. name = STR_UNSET;
  49. wall_indices = std::vector<int>();
  50. surface_class = nullptr;
  51. initial_surface_releases = std::vector<std::shared_ptr<InitialSurfaceRelease>>();
  52. initial_color = nullptr;
  53. node_type = RegionNodeType::UNSET;
  54. left_node = nullptr;
  55. right_node = nullptr;
  56. }
  57. std::shared_ptr<SurfaceRegion> GenSurfaceRegion::copy_surface_region() const {
  58. std::shared_ptr<SurfaceRegion> res = std::make_shared<SurfaceRegion>(DefaultCtorArgType());
  59. res->class_name = class_name;
  60. res->name = name;
  61. res->wall_indices = wall_indices;
  62. res->surface_class = surface_class;
  63. res->initial_surface_releases = initial_surface_releases;
  64. res->initial_color = initial_color;
  65. res->node_type = node_type;
  66. res->left_node = left_node;
  67. res->right_node = right_node;
  68. return res;
  69. }
  70. std::shared_ptr<SurfaceRegion> GenSurfaceRegion::deepcopy_surface_region(py::dict) const {
  71. std::shared_ptr<SurfaceRegion> res = std::make_shared<SurfaceRegion>(DefaultCtorArgType());
  72. res->class_name = class_name;
  73. res->name = name;
  74. res->wall_indices = wall_indices;
  75. res->surface_class = is_set(surface_class) ? surface_class->deepcopy_surface_class() : nullptr;
  76. for (const auto& item: initial_surface_releases) {
  77. res->initial_surface_releases.push_back((is_set(item)) ? item->deepcopy_initial_surface_release() : nullptr);
  78. }
  79. res->initial_color = is_set(initial_color) ? initial_color->deepcopy_color() : nullptr;
  80. res->node_type = node_type;
  81. res->left_node = is_set(left_node) ? left_node->deepcopy_region() : nullptr;
  82. res->right_node = is_set(right_node) ? right_node->deepcopy_region() : nullptr;
  83. return res;
  84. }
  85. bool GenSurfaceRegion::__eq__(const SurfaceRegion& other) const {
  86. return
  87. name == other.name &&
  88. wall_indices == other.wall_indices &&
  89. (
  90. (is_set(surface_class)) ?
  91. (is_set(other.surface_class) ?
  92. (surface_class->__eq__(*other.surface_class)) :
  93. false
  94. ) :
  95. (is_set(other.surface_class) ?
  96. false :
  97. true
  98. )
  99. ) &&
  100. vec_ptr_eq(initial_surface_releases, other.initial_surface_releases) &&
  101. (
  102. (is_set(initial_color)) ?
  103. (is_set(other.initial_color) ?
  104. (initial_color->__eq__(*other.initial_color)) :
  105. false
  106. ) :
  107. (is_set(other.initial_color) ?
  108. false :
  109. true
  110. )
  111. ) &&
  112. node_type == other.node_type &&
  113. (
  114. (is_set(left_node)) ?
  115. (is_set(other.left_node) ?
  116. (left_node->__eq__(*other.left_node)) :
  117. false
  118. ) :
  119. (is_set(other.left_node) ?
  120. false :
  121. true
  122. )
  123. ) &&
  124. (
  125. (is_set(right_node)) ?
  126. (is_set(other.right_node) ?
  127. (right_node->__eq__(*other.right_node)) :
  128. false
  129. ) :
  130. (is_set(other.right_node) ?
  131. false :
  132. true
  133. )
  134. ) ;
  135. }
  136. bool GenSurfaceRegion::eq_nonarray_attributes(const SurfaceRegion& other, const bool ignore_name) const {
  137. return
  138. (ignore_name || name == other.name) &&
  139. true /*wall_indices*/ &&
  140. (
  141. (is_set(surface_class)) ?
  142. (is_set(other.surface_class) ?
  143. (surface_class->__eq__(*other.surface_class)) :
  144. false
  145. ) :
  146. (is_set(other.surface_class) ?
  147. false :
  148. true
  149. )
  150. ) &&
  151. true /*initial_surface_releases*/ &&
  152. (
  153. (is_set(initial_color)) ?
  154. (is_set(other.initial_color) ?
  155. (initial_color->__eq__(*other.initial_color)) :
  156. false
  157. ) :
  158. (is_set(other.initial_color) ?
  159. false :
  160. true
  161. )
  162. ) &&
  163. node_type == other.node_type &&
  164. (
  165. (is_set(left_node)) ?
  166. (is_set(other.left_node) ?
  167. (left_node->__eq__(*other.left_node)) :
  168. false
  169. ) :
  170. (is_set(other.left_node) ?
  171. false :
  172. true
  173. )
  174. ) &&
  175. (
  176. (is_set(right_node)) ?
  177. (is_set(other.right_node) ?
  178. (right_node->__eq__(*other.right_node)) :
  179. false
  180. ) :
  181. (is_set(other.right_node) ?
  182. false :
  183. true
  184. )
  185. ) ;
  186. }
  187. std::string GenSurfaceRegion::to_str(const bool all_details, const std::string ind) const {
  188. std::stringstream ss;
  189. ss << get_object_name() << ": " <<
  190. "name=" << name << ", " <<
  191. "wall_indices=" << vec_nonptr_to_str(wall_indices, all_details, ind + " ") << ", " <<
  192. "\n" << ind + " " << "surface_class=" << "(" << ((surface_class != nullptr) ? surface_class->to_str(all_details, ind + " ") : "null" ) << ")" << ", " << "\n" << ind + " " <<
  193. "initial_surface_releases=" << vec_ptr_to_str(initial_surface_releases, all_details, ind + " ") << ", " << "\n" << ind + " " <<
  194. "initial_color=" << "(" << ((initial_color != nullptr) ? initial_color->to_str(all_details, ind + " ") : "null" ) << ")" << ", " << "\n" << ind + " " <<
  195. "node_type=" << node_type << ", " <<
  196. "\n" << ind + " " << "left_node=" << "(" << ((left_node != nullptr) ? left_node->to_str(all_details, ind + " ") : "null" ) << ")" << ", " << "\n" << ind + " " <<
  197. "right_node=" << "(" << ((right_node != nullptr) ? right_node->to_str(all_details, ind + " ") : "null" ) << ")";
  198. return ss.str();
  199. }
  200. py::class_<SurfaceRegion> define_pybinding_SurfaceRegion(py::module& m) {
  201. return py::class_<SurfaceRegion, Region, std::shared_ptr<SurfaceRegion>>(m, "SurfaceRegion", "Defines a region on the object. The extent of a region is given by the wall_indices list. \nMolecules can be added and surface properties can be set with the optional regional surface commands. \nYou can have an arbitrary number of regions on an object, and they may overlap if\nyou wish. Molecules added to overlapping regions accumulate. Triangles belonging to \nmultiple regions inherit all parent regions’ surface properties. Users\nhave to make sure that in case of overlapped regions their surface properties\nare compatible. \n")
  202. .def(
  203. py::init<
  204. const std::string&,
  205. const std::vector<int>,
  206. std::shared_ptr<SurfaceClass>,
  207. const std::vector<std::shared_ptr<InitialSurfaceRelease>>,
  208. std::shared_ptr<Color>,
  209. const RegionNodeType,
  210. std::shared_ptr<Region>,
  211. std::shared_ptr<Region>
  212. >(),
  213. py::arg("name"),
  214. py::arg("wall_indices"),
  215. py::arg("surface_class") = nullptr,
  216. py::arg("initial_surface_releases") = std::vector<std::shared_ptr<InitialSurfaceRelease>>(),
  217. py::arg("initial_color") = nullptr,
  218. py::arg("node_type") = RegionNodeType::UNSET,
  219. py::arg("left_node") = nullptr,
  220. py::arg("right_node") = nullptr
  221. )
  222. .def("check_semantics", &SurfaceRegion::check_semantics)
  223. .def("__copy__", &SurfaceRegion::copy_surface_region)
  224. .def("__deepcopy__", &SurfaceRegion::deepcopy_surface_region, py::arg("memo"))
  225. .def("__str__", &SurfaceRegion::to_str, py::arg("all_details") = false, py::arg("ind") = std::string(""))
  226. .def("__eq__", &SurfaceRegion::__eq__, py::arg("other"))
  227. .def("dump", &SurfaceRegion::dump)
  228. .def_property("name", &SurfaceRegion::get_name, &SurfaceRegion::set_name, "Name of this region.")
  229. .def_property("wall_indices", &SurfaceRegion::get_wall_indices, &SurfaceRegion::set_wall_indices, py::return_value_policy::reference, "Surface region must be a part of a GeometryObject, items in this list are indices to \nits wall_list array.\n")
  230. .def_property("surface_class", &SurfaceRegion::get_surface_class, &SurfaceRegion::set_surface_class, "Optional surface class assigned to this surface region.\nIf not set, it is inherited from the parent geometry object's surface_class.\n")
  231. .def_property("initial_surface_releases", &SurfaceRegion::get_initial_surface_releases, &SurfaceRegion::set_initial_surface_releases, py::return_value_policy::reference, "Each item of this list defines either density or number of molecules to be released on this surface \nregions when simulation starts.\n")
  232. .def_property("initial_color", &SurfaceRegion::get_initial_color, &SurfaceRegion::set_initial_color, "Initial color for this specific surface region. If not set, color of the parent's GeometryObject is used.")
  233. ;
  234. }
  235. std::string GenSurfaceRegion::export_to_python(std::ostream& out, PythonExportContext& ctx) {
  236. if (!export_even_if_already_exported() && ctx.already_exported(this)) {
  237. return ctx.get_exported_name(this);
  238. }
  239. std::string exported_name = std::string("surface_region") + "_" + (is_set(name) ? fix_id(name) : std::to_string(ctx.postinc_counter("surface_region")));
  240. if (!export_even_if_already_exported()) {
  241. ctx.add_exported(this, exported_name);
  242. }
  243. bool str_export = export_as_string_without_newlines();
  244. std::string nl = "";
  245. std::string ind = " ";
  246. std::stringstream ss;
  247. if (!str_export) {
  248. nl = "\n";
  249. ind = " ";
  250. ss << exported_name << " = ";
  251. }
  252. ss << "m.SurfaceRegion(" << nl;
  253. if (node_type != RegionNodeType::UNSET) {
  254. ss << ind << "node_type = " << node_type << "," << nl;
  255. }
  256. if (is_set(left_node)) {
  257. ss << ind << "left_node = " << left_node->export_to_python(out, ctx) << "," << nl;
  258. }
  259. if (is_set(right_node)) {
  260. ss << ind << "right_node = " << right_node->export_to_python(out, ctx) << "," << nl;
  261. }
  262. ss << ind << "name = " << "'" << name << "'" << "," << nl;
  263. ss << ind << "wall_indices = " << export_vec_wall_indices(out, ctx, exported_name) << "," << nl;
  264. if (is_set(surface_class)) {
  265. ss << ind << "surface_class = " << surface_class->export_to_python(out, ctx) << "," << nl;
  266. }
  267. if (initial_surface_releases != std::vector<std::shared_ptr<InitialSurfaceRelease>>() && !skip_vectors_export()) {
  268. ss << ind << "initial_surface_releases = " << export_vec_initial_surface_releases(out, ctx, exported_name) << "," << nl;
  269. }
  270. if (is_set(initial_color)) {
  271. ss << ind << "initial_color = " << initial_color->export_to_python(out, ctx) << "," << nl;
  272. }
  273. ss << ")" << nl << nl;
  274. if (!str_export) {
  275. out << ss.str();
  276. return exported_name;
  277. }
  278. else {
  279. return ss.str();
  280. }
  281. }
  282. std::string GenSurfaceRegion::export_vec_wall_indices(std::ostream& out, PythonExportContext& ctx, const std::string& parent_name) {
  283. // does not print the array itself to 'out' and returns the whole list
  284. std::stringstream ss;
  285. ss << "[";
  286. for (size_t i = 0; i < wall_indices.size(); i++) {
  287. const auto& item = wall_indices[i];
  288. if (i == 0) {
  289. ss << " ";
  290. }
  291. else if (i % 16 == 0) {
  292. ss << "\n ";
  293. }
  294. ss << item << ", ";
  295. }
  296. ss << "]";
  297. return ss.str();
  298. }
  299. std::string GenSurfaceRegion::export_vec_initial_surface_releases(std::ostream& out, PythonExportContext& ctx, const std::string& parent_name) {
  300. // does not print the array itself to 'out' and returns the whole list
  301. std::stringstream ss;
  302. ss << "[";
  303. for (size_t i = 0; i < initial_surface_releases.size(); i++) {
  304. const auto& item = initial_surface_releases[i];
  305. if (i == 0) {
  306. ss << " ";
  307. }
  308. else if (i % 16 == 0) {
  309. ss << "\n ";
  310. }
  311. if (!item->skip_python_export()) {
  312. std::string name = item->export_to_python(out, ctx);
  313. ss << name << ", ";
  314. }
  315. }
  316. ss << "]";
  317. return ss.str();
  318. }
  319. } // namespace API
  320. } // namespace MCell