gen_release_site.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  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_release_site.h"
  15. #include "api/release_site.h"
  16. #include "api/complex.h"
  17. #include "api/molecule_release_info.h"
  18. #include "api/region.h"
  19. #include "api/release_pattern.h"
  20. namespace MCell {
  21. namespace API {
  22. void GenReleaseSite::check_semantics() const {
  23. if (!is_set(name)) {
  24. throw ValueError("Parameter 'name' must be set.");
  25. }
  26. }
  27. void GenReleaseSite::set_initialized() {
  28. if (is_set(complex)) {
  29. complex->set_initialized();
  30. }
  31. vec_set_initialized(molecule_list);
  32. if (is_set(release_pattern)) {
  33. release_pattern->set_initialized();
  34. }
  35. if (is_set(region)) {
  36. region->set_initialized();
  37. }
  38. initialized = true;
  39. }
  40. void GenReleaseSite::set_all_attributes_as_default_or_unset() {
  41. class_name = "ReleaseSite";
  42. name = STR_UNSET;
  43. complex = nullptr;
  44. molecule_list = std::vector<std::shared_ptr<MoleculeReleaseInfo>>();
  45. release_time = 0;
  46. release_pattern = nullptr;
  47. shape = Shape::UNSET;
  48. region = nullptr;
  49. location = std::vector<double>();
  50. site_diameter = 0;
  51. site_radius = FLT_UNSET;
  52. number_to_release = FLT_UNSET;
  53. density = FLT_UNSET;
  54. concentration = FLT_UNSET;
  55. release_probability = 1;
  56. }
  57. std::shared_ptr<ReleaseSite> GenReleaseSite::copy_release_site() const {
  58. std::shared_ptr<ReleaseSite> res = std::make_shared<ReleaseSite>(DefaultCtorArgType());
  59. res->class_name = class_name;
  60. res->name = name;
  61. res->complex = complex;
  62. res->molecule_list = molecule_list;
  63. res->release_time = release_time;
  64. res->release_pattern = release_pattern;
  65. res->shape = shape;
  66. res->region = region;
  67. res->location = location;
  68. res->site_diameter = site_diameter;
  69. res->site_radius = site_radius;
  70. res->number_to_release = number_to_release;
  71. res->density = density;
  72. res->concentration = concentration;
  73. res->release_probability = release_probability;
  74. return res;
  75. }
  76. std::shared_ptr<ReleaseSite> GenReleaseSite::deepcopy_release_site(py::dict) const {
  77. std::shared_ptr<ReleaseSite> res = std::make_shared<ReleaseSite>(DefaultCtorArgType());
  78. res->class_name = class_name;
  79. res->name = name;
  80. res->complex = is_set(complex) ? complex->deepcopy_complex() : nullptr;
  81. for (const auto& item: molecule_list) {
  82. res->molecule_list.push_back((is_set(item)) ? item->deepcopy_molecule_release_info() : nullptr);
  83. }
  84. res->release_time = release_time;
  85. res->release_pattern = is_set(release_pattern) ? release_pattern->deepcopy_release_pattern() : nullptr;
  86. res->shape = shape;
  87. res->region = is_set(region) ? region->deepcopy_region() : nullptr;
  88. res->location = location;
  89. res->site_diameter = site_diameter;
  90. res->site_radius = site_radius;
  91. res->number_to_release = number_to_release;
  92. res->density = density;
  93. res->concentration = concentration;
  94. res->release_probability = release_probability;
  95. return res;
  96. }
  97. bool GenReleaseSite::__eq__(const ReleaseSite& other) const {
  98. return
  99. name == other.name &&
  100. (
  101. (is_set(complex)) ?
  102. (is_set(other.complex) ?
  103. (complex->__eq__(*other.complex)) :
  104. false
  105. ) :
  106. (is_set(other.complex) ?
  107. false :
  108. true
  109. )
  110. ) &&
  111. vec_ptr_eq(molecule_list, other.molecule_list) &&
  112. release_time == other.release_time &&
  113. (
  114. (is_set(release_pattern)) ?
  115. (is_set(other.release_pattern) ?
  116. (release_pattern->__eq__(*other.release_pattern)) :
  117. false
  118. ) :
  119. (is_set(other.release_pattern) ?
  120. false :
  121. true
  122. )
  123. ) &&
  124. shape == other.shape &&
  125. (
  126. (is_set(region)) ?
  127. (is_set(other.region) ?
  128. (region->__eq__(*other.region)) :
  129. false
  130. ) :
  131. (is_set(other.region) ?
  132. false :
  133. true
  134. )
  135. ) &&
  136. location == other.location &&
  137. site_diameter == other.site_diameter &&
  138. site_radius == other.site_radius &&
  139. number_to_release == other.number_to_release &&
  140. density == other.density &&
  141. concentration == other.concentration &&
  142. release_probability == other.release_probability;
  143. }
  144. bool GenReleaseSite::eq_nonarray_attributes(const ReleaseSite& other, const bool ignore_name) const {
  145. return
  146. (ignore_name || name == other.name) &&
  147. (
  148. (is_set(complex)) ?
  149. (is_set(other.complex) ?
  150. (complex->__eq__(*other.complex)) :
  151. false
  152. ) :
  153. (is_set(other.complex) ?
  154. false :
  155. true
  156. )
  157. ) &&
  158. true /*molecule_list*/ &&
  159. release_time == other.release_time &&
  160. (
  161. (is_set(release_pattern)) ?
  162. (is_set(other.release_pattern) ?
  163. (release_pattern->__eq__(*other.release_pattern)) :
  164. false
  165. ) :
  166. (is_set(other.release_pattern) ?
  167. false :
  168. true
  169. )
  170. ) &&
  171. shape == other.shape &&
  172. (
  173. (is_set(region)) ?
  174. (is_set(other.region) ?
  175. (region->__eq__(*other.region)) :
  176. false
  177. ) :
  178. (is_set(other.region) ?
  179. false :
  180. true
  181. )
  182. ) &&
  183. true /*location*/ &&
  184. site_diameter == other.site_diameter &&
  185. site_radius == other.site_radius &&
  186. number_to_release == other.number_to_release &&
  187. density == other.density &&
  188. concentration == other.concentration &&
  189. release_probability == other.release_probability;
  190. }
  191. std::string GenReleaseSite::to_str(const bool all_details, const std::string ind) const {
  192. std::stringstream ss;
  193. ss << get_object_name() << ": " <<
  194. "name=" << name << ", " <<
  195. "\n" << ind + " " << "complex=" << "(" << ((complex != nullptr) ? complex->to_str(all_details, ind + " ") : "null" ) << ")" << ", " << "\n" << ind + " " <<
  196. "molecule_list=" << vec_ptr_to_str(molecule_list, all_details, ind + " ") << ", " << "\n" << ind + " " <<
  197. "release_time=" << release_time << ", " <<
  198. "\n" << ind + " " << "release_pattern=" << "(" << ((release_pattern != nullptr) ? release_pattern->to_str(all_details, ind + " ") : "null" ) << ")" << ", " << "\n" << ind + " " <<
  199. "shape=" << shape << ", " <<
  200. "\n" << ind + " " << "region=" << "(" << ((region != nullptr) ? region->to_str(all_details, ind + " ") : "null" ) << ")" << ", " << "\n" << ind + " " <<
  201. "location=" << vec_nonptr_to_str(location, all_details, ind + " ") << ", " <<
  202. "site_diameter=" << site_diameter << ", " <<
  203. "site_radius=" << site_radius << ", " <<
  204. "number_to_release=" << number_to_release << ", " <<
  205. "density=" << density << ", " <<
  206. "concentration=" << concentration << ", " <<
  207. "release_probability=" << release_probability;
  208. return ss.str();
  209. }
  210. py::class_<ReleaseSite> define_pybinding_ReleaseSite(py::module& m) {
  211. return py::class_<ReleaseSite, std::shared_ptr<ReleaseSite>>(m, "ReleaseSite", "Defines a release site that specifies where, when and how should molecules be released. \n")
  212. .def(
  213. py::init<
  214. const std::string&,
  215. std::shared_ptr<Complex>,
  216. const std::vector<std::shared_ptr<MoleculeReleaseInfo>>,
  217. const double,
  218. std::shared_ptr<ReleasePattern>,
  219. const Shape,
  220. std::shared_ptr<Region>,
  221. const std::vector<double>,
  222. const double,
  223. const double,
  224. const double,
  225. const double,
  226. const double,
  227. const double
  228. >(),
  229. py::arg("name"),
  230. py::arg("complex") = nullptr,
  231. py::arg("molecule_list") = std::vector<std::shared_ptr<MoleculeReleaseInfo>>(),
  232. py::arg("release_time") = 0,
  233. py::arg("release_pattern") = nullptr,
  234. py::arg("shape") = Shape::UNSET,
  235. py::arg("region") = nullptr,
  236. py::arg("location") = std::vector<double>(),
  237. py::arg("site_diameter") = 0,
  238. py::arg("site_radius") = FLT_UNSET,
  239. py::arg("number_to_release") = FLT_UNSET,
  240. py::arg("density") = FLT_UNSET,
  241. py::arg("concentration") = FLT_UNSET,
  242. py::arg("release_probability") = 1
  243. )
  244. .def("check_semantics", &ReleaseSite::check_semantics)
  245. .def("__copy__", &ReleaseSite::copy_release_site)
  246. .def("__deepcopy__", &ReleaseSite::deepcopy_release_site, py::arg("memo"))
  247. .def("__str__", &ReleaseSite::to_str, py::arg("all_details") = false, py::arg("ind") = std::string(""))
  248. .def("__eq__", &ReleaseSite::__eq__, py::arg("other"))
  249. .def("dump", &ReleaseSite::dump)
  250. .def_property("name", &ReleaseSite::get_name, &ReleaseSite::set_name, "Name of the release site")
  251. .def_property("complex", &ReleaseSite::get_complex, &ReleaseSite::set_complex, "Defines the species of the molecule that will be released. Not used for the LIST shape. \nMust be set when molecule_list is empty and unset when molecule_list is not empty.\nOrientation of the complex instance is used to define orientation of the released molecule,\nwhen Orientation.DEFAULT is set, volume molecules are released with Orientation.NONE and\nsurface molecules are released with Orientation.UP.\nWhen compartment is specified and region is not set, this sets shape to Shape.COMPARTMENT and \nthe molecules are released into the compartment.\nWhen this is a release of volume molecules, and both compartment and region are set, \nthis sets shape to Shape.REGION_EXPR and the target region is the intersection \nof the region and the compartment.\n")
  252. .def_property("molecule_list", &ReleaseSite::get_molecule_list, &ReleaseSite::set_molecule_list, py::return_value_policy::reference, "Used for LIST shape release mode. \nOnly one of number_to_release, density, concentration or molecule_list can be set.\n")
  253. .def_property("release_time", &ReleaseSite::get_release_time, &ReleaseSite::set_release_time, "Specifies time in seconds when the release event is executed.\nIn case when a release pattern is used, this is the time of the first release. \nEquivalent to MDL's RELEASE_PATTERN command DELAY.\n")
  254. .def_property("release_pattern", &ReleaseSite::get_release_pattern, &ReleaseSite::set_release_pattern, "Use the release pattern to define schedule of releases. \nThe default is to release the specified number of molecules at the set release_time. \n")
  255. .def_property("shape", &ReleaseSite::get_shape, &ReleaseSite::set_shape, "Defines how the molecules shoudl be released. \nSet automatically for these cases to the following values: \nregion is set - Shape.REGION_EXPR,\nregion is not set and complex uses a compartment - Shape.COMPARTMENT,\nmolecule_list is set - Shape.LIST,\nlocation is set - Shape.SPHERICAL.\n")
  256. .def_property("region", &ReleaseSite::get_region, &ReleaseSite::set_region, "Defines a volume or surface region where to release molecules. \nSetting it sets shape to Shape.REGION_EXPR. \nWhen this is a release of volume molecules, and both compartment and region are set, \nthis sets shape to Shape.REGION_EXPR and the target region is the intersection \nof the region and the compartment.\n \n")
  257. .def_property("location", &ReleaseSite::get_location, &ReleaseSite::set_location, py::return_value_policy::reference, "Defines center of a sphere where to release molecules. \nSetting it sets shape to Shape.SPHERICAL.\n")
  258. .def_property("site_diameter", &ReleaseSite::get_site_diameter, &ReleaseSite::set_site_diameter, "For a geometrical release site, this releases molecules uniformly within\na radius r computed as site_diameter/2. \nUsed only when shape is Shape.SPHERICAL.\nMaximum one of site_diameter or site_radius may be set.\n")
  259. .def_property("site_radius", &ReleaseSite::get_site_radius, &ReleaseSite::set_site_radius, "For a geometrical release site, this releases molecules uniformly within\na radius site_radius.\nUsed only when shape is Shape.SPHERICAL.\nMaximum one of site_diameter or site_radius may be set.\n")
  260. .def_property("number_to_release", &ReleaseSite::get_number_to_release, &ReleaseSite::set_number_to_release, "Sets number of molecules to release. Cannot be set when shape is Shape.LIST. \nOnly one of number_to_release, density, concentration or molecule_list can be set.\nValue is truncated (floored) to an integer.\n")
  261. .def_property("density", &ReleaseSite::get_density, &ReleaseSite::set_density, "Unit is molecules per square micron (for surfaces). \nOnly one of number_to_release, density, concentration or molecule_list can be set.\nCannot be set when shape is Shape.LIST.\n")
  262. .def_property("concentration", &ReleaseSite::get_concentration, &ReleaseSite::set_concentration, "Unit is molar (moles per liter) for volumes.\nOnly one of number_to_release, density, concentration or molecule_list can be set.\nCannot be set when shape is Shape.LIST.\n")
  263. .def_property("release_probability", &ReleaseSite::get_release_probability, &ReleaseSite::set_release_probability, "This release does not occur every time, but rather with probability p. \nEither the whole release occurs or none of it does; the probability does not \napply molecule-by-molecule. release_probability must be in the interval [0, 1].\n")
  264. ;
  265. }
  266. std::string GenReleaseSite::export_to_python(std::ostream& out, PythonExportContext& ctx) {
  267. if (!export_even_if_already_exported() && ctx.already_exported(this)) {
  268. return ctx.get_exported_name(this);
  269. }
  270. std::string exported_name = std::string("release_site") + "_" + (is_set(name) ? fix_id(name) : std::to_string(ctx.postinc_counter("release_site")));
  271. if (!export_even_if_already_exported()) {
  272. ctx.add_exported(this, exported_name);
  273. }
  274. bool str_export = export_as_string_without_newlines();
  275. std::string nl = "";
  276. std::string ind = " ";
  277. std::stringstream ss;
  278. if (!str_export) {
  279. nl = "\n";
  280. ind = " ";
  281. ss << exported_name << " = ";
  282. }
  283. ss << "m.ReleaseSite(" << nl;
  284. ss << ind << "name = " << "'" << name << "'" << "," << nl;
  285. if (is_set(complex)) {
  286. ss << ind << "complex = " << complex->export_to_python(out, ctx) << "," << nl;
  287. }
  288. if (molecule_list != std::vector<std::shared_ptr<MoleculeReleaseInfo>>() && !skip_vectors_export()) {
  289. ss << ind << "molecule_list = " << export_vec_molecule_list(out, ctx, exported_name) << "," << nl;
  290. }
  291. if (release_time != 0) {
  292. ss << ind << "release_time = " << f_to_str(release_time) << "," << nl;
  293. }
  294. if (is_set(release_pattern)) {
  295. ss << ind << "release_pattern = " << release_pattern->export_to_python(out, ctx) << "," << nl;
  296. }
  297. if (shape != Shape::UNSET) {
  298. ss << ind << "shape = " << shape << "," << nl;
  299. }
  300. if (is_set(region)) {
  301. ss << ind << "region = " << region->export_to_python(out, ctx) << "," << nl;
  302. }
  303. if (location != std::vector<double>() && !skip_vectors_export()) {
  304. ss << ind << "location = " << export_vec_location(out, ctx, exported_name) << "," << nl;
  305. }
  306. if (site_diameter != 0) {
  307. ss << ind << "site_diameter = " << f_to_str(site_diameter) << "," << nl;
  308. }
  309. if (site_radius != FLT_UNSET) {
  310. ss << ind << "site_radius = " << f_to_str(site_radius) << "," << nl;
  311. }
  312. if (number_to_release != FLT_UNSET) {
  313. ss << ind << "number_to_release = " << f_to_str(number_to_release) << "," << nl;
  314. }
  315. if (density != FLT_UNSET) {
  316. ss << ind << "density = " << f_to_str(density) << "," << nl;
  317. }
  318. if (concentration != FLT_UNSET) {
  319. ss << ind << "concentration = " << f_to_str(concentration) << "," << nl;
  320. }
  321. if (release_probability != 1) {
  322. ss << ind << "release_probability = " << f_to_str(release_probability) << "," << nl;
  323. }
  324. ss << ")" << nl << nl;
  325. if (!str_export) {
  326. out << ss.str();
  327. return exported_name;
  328. }
  329. else {
  330. return ss.str();
  331. }
  332. }
  333. std::string GenReleaseSite::export_vec_molecule_list(std::ostream& out, PythonExportContext& ctx, const std::string& parent_name) {
  334. // does not print the array itself to 'out' and returns the whole list
  335. std::stringstream ss;
  336. ss << "[";
  337. for (size_t i = 0; i < molecule_list.size(); i++) {
  338. const auto& item = molecule_list[i];
  339. if (i == 0) {
  340. ss << " ";
  341. }
  342. else if (i % 16 == 0) {
  343. ss << "\n ";
  344. }
  345. if (!item->skip_python_export()) {
  346. std::string name = item->export_to_python(out, ctx);
  347. ss << name << ", ";
  348. }
  349. }
  350. ss << "]";
  351. return ss.str();
  352. }
  353. std::string GenReleaseSite::export_vec_location(std::ostream& out, PythonExportContext& ctx, const std::string& parent_name) {
  354. // does not print the array itself to 'out' and returns the whole list
  355. std::stringstream ss;
  356. ss << "[";
  357. for (size_t i = 0; i < location.size(); i++) {
  358. const auto& item = location[i];
  359. if (i == 0) {
  360. ss << " ";
  361. }
  362. else if (i % 16 == 0) {
  363. ss << "\n ";
  364. }
  365. ss << f_to_str(item) << ", ";
  366. }
  367. ss << "]";
  368. return ss.str();
  369. }
  370. } // namespace API
  371. } // namespace MCell