gen_subsystem.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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_subsystem.h"
  15. #include "api/subsystem.h"
  16. #include "api/elementary_molecule_type.h"
  17. #include "api/reaction_rule.h"
  18. #include "api/species.h"
  19. #include "api/surface_class.h"
  20. namespace MCell {
  21. namespace API {
  22. std::shared_ptr<Subsystem> GenSubsystem::copy_subsystem() const {
  23. std::shared_ptr<Subsystem> res = std::make_shared<Subsystem>(DefaultCtorArgType());
  24. res->species = species;
  25. res->reaction_rules = reaction_rules;
  26. res->surface_classes = surface_classes;
  27. res->elementary_molecule_types = elementary_molecule_types;
  28. return res;
  29. }
  30. std::shared_ptr<Subsystem> GenSubsystem::deepcopy_subsystem(py::dict) const {
  31. std::shared_ptr<Subsystem> res = std::make_shared<Subsystem>(DefaultCtorArgType());
  32. for (const auto& item: species) {
  33. res->species.push_back((is_set(item)) ? item->deepcopy_species() : nullptr);
  34. }
  35. for (const auto& item: reaction_rules) {
  36. res->reaction_rules.push_back((is_set(item)) ? item->deepcopy_reaction_rule() : nullptr);
  37. }
  38. for (const auto& item: surface_classes) {
  39. res->surface_classes.push_back((is_set(item)) ? item->deepcopy_surface_class() : nullptr);
  40. }
  41. for (const auto& item: elementary_molecule_types) {
  42. res->elementary_molecule_types.push_back((is_set(item)) ? item->deepcopy_elementary_molecule_type() : nullptr);
  43. }
  44. return res;
  45. }
  46. bool GenSubsystem::__eq__(const Subsystem& other) const {
  47. return
  48. vec_ptr_eq(species, other.species) &&
  49. vec_ptr_eq(reaction_rules, other.reaction_rules) &&
  50. vec_ptr_eq(surface_classes, other.surface_classes) &&
  51. vec_ptr_eq(elementary_molecule_types, other.elementary_molecule_types);
  52. }
  53. bool GenSubsystem::eq_nonarray_attributes(const Subsystem& other, const bool ignore_name) const {
  54. return
  55. true /*species*/ &&
  56. true /*reaction_rules*/ &&
  57. true /*surface_classes*/ &&
  58. true /*elementary_molecule_types*/;
  59. }
  60. std::string GenSubsystem::to_str(const bool all_details, const std::string ind) const {
  61. std::stringstream ss;
  62. ss << "Subsystem" << ": " <<
  63. "\n" << ind + " " << "species=" << vec_ptr_to_str(species, all_details, ind + " ") << ", " << "\n" << ind + " " <<
  64. "reaction_rules=" << vec_ptr_to_str(reaction_rules, all_details, ind + " ") << ", " << "\n" << ind + " " <<
  65. "surface_classes=" << vec_ptr_to_str(surface_classes, all_details, ind + " ") << ", " << "\n" << ind + " " <<
  66. "elementary_molecule_types=" << vec_ptr_to_str(elementary_molecule_types, all_details, ind + " ");
  67. return ss.str();
  68. }
  69. py::class_<Subsystem> define_pybinding_Subsystem(py::module& m) {
  70. return py::class_<Subsystem, std::shared_ptr<Subsystem>>(m, "Subsystem", "Subsystem usually defines a reaction network. It is a collection of \nspecies and reaction rules that use these species. \nThe main motivation for introducing such an object to MCell4 is to have \na class independent on that particular initial model state and observables that \nonly contains reactions. This way, one can define independent reusable subsystems\nand possibly merge them together when creating a model that includes multiple reaction \nnetworks. \n")
  71. .def(
  72. py::init<
  73. const std::vector<std::shared_ptr<Species>>,
  74. const std::vector<std::shared_ptr<ReactionRule>>,
  75. const std::vector<std::shared_ptr<SurfaceClass>>,
  76. const std::vector<std::shared_ptr<ElementaryMoleculeType>>
  77. >(),
  78. py::arg("species") = std::vector<std::shared_ptr<Species>>(),
  79. py::arg("reaction_rules") = std::vector<std::shared_ptr<ReactionRule>>(),
  80. py::arg("surface_classes") = std::vector<std::shared_ptr<SurfaceClass>>(),
  81. py::arg("elementary_molecule_types") = std::vector<std::shared_ptr<ElementaryMoleculeType>>()
  82. )
  83. .def("__copy__", &Subsystem::copy_subsystem)
  84. .def("__deepcopy__", &Subsystem::deepcopy_subsystem, py::arg("memo"))
  85. .def("__str__", &Subsystem::to_str, py::arg("all_details") = false, py::arg("ind") = std::string(""))
  86. .def("__eq__", &Subsystem::__eq__, py::arg("other"))
  87. .def("add_species", &Subsystem::add_species, py::arg("s"), "Add a reference to a Species object to the species list.\n- s\n")
  88. .def("find_species", &Subsystem::find_species, py::arg("name"), "Find a Species object using name in the species list. \nReturns None if no such species is found.\n\n- name\n")
  89. .def("add_reaction_rule", &Subsystem::add_reaction_rule, py::arg("r"), "Add a reference to a ReactionRule object to the reaction_rules list.\n- r\n")
  90. .def("find_reaction_rule", &Subsystem::find_reaction_rule, py::arg("name"), "Find a ReactionRule object using name in the reaction_rules list. \nReturns None if no such reaction rule is found.\n\n- name\n")
  91. .def("add_surface_class", &Subsystem::add_surface_class, py::arg("sc"), "Add a reference to a SurfaceClass object to the surface_classes list.\n- sc\n")
  92. .def("find_surface_class", &Subsystem::find_surface_class, py::arg("name"), "Find a SurfaceClass object using name in the surface_classes list. \nReturns None if no such surface class is found.\n\n- name\n")
  93. .def("add_elementary_molecule_type", &Subsystem::add_elementary_molecule_type, py::arg("mt"), "Add a reference to an ElementaryMoleculeType object to the elementary_molecule_types list.\n- mt\n")
  94. .def("find_elementary_molecule_type", &Subsystem::find_elementary_molecule_type, py::arg("name"), "Find an ElementaryMoleculeType object using name in the elementary_molecule_types list. \nReturns None if no such elementary molecule type is found.\n\n- name\n")
  95. .def("load_bngl_molecule_types_and_reaction_rules", &Subsystem::load_bngl_molecule_types_and_reaction_rules, py::arg("file_name"), py::arg("parameter_overrides") = std::map<std::string, double>(), "Parses a BNGL file, only reads molecule types and reaction rules sections, \ni.e. ignores observables and seed species. \nParameter values are evaluated and the result value is directly used. \nCompartments names are stored in rxn rules as strings because compartments belong \nto geometry objects and the subsystem is independent on specific geometry.\nHowever, the compartments and their objects must be defined before initialization.\n\n- file_name: Path to the BNGL file to be loaded.\n\n- parameter_overrides: For each key k in the parameter_overrides, if it is defined in the BNGL's parameters section,\nits value is ignored and instead value parameter_overrides[k] is used.\n\n\n")
  96. .def("dump", &Subsystem::dump)
  97. .def_property("species", &Subsystem::get_species, &Subsystem::set_species, py::return_value_policy::reference, "List of species to be included in the model for initialization.\nUsed usually only for simple species (species that are defined using a\nsingle molecule type without components such as 'A').\nOther species may be created inside simulation \n")
  98. .def_property("reaction_rules", &Subsystem::get_reaction_rules, &Subsystem::set_reaction_rules, py::return_value_policy::reference)
  99. .def_property("surface_classes", &Subsystem::get_surface_classes, &Subsystem::set_surface_classes, py::return_value_policy::reference)
  100. .def_property("elementary_molecule_types", &Subsystem::get_elementary_molecule_types, &Subsystem::set_elementary_molecule_types, py::return_value_policy::reference, "Contains list of elementary molecule types with their diffusion constants and other information. \nPopulated when a BNGL file is loaded and also on initialization from Species objects present in \nthe species list.\n")
  101. ;
  102. }
  103. std::string GenSubsystem::export_to_python(std::ostream& out, PythonExportContext& ctx) {
  104. std::string exported_name = "subsystem";
  105. bool str_export = export_as_string_without_newlines();
  106. std::string nl = "";
  107. std::string ind = " ";
  108. std::stringstream ss;
  109. if (!str_export) {
  110. nl = "\n";
  111. ind = " ";
  112. ss << exported_name << " = ";
  113. }
  114. ss << "m.Subsystem(" << nl;
  115. if (species != std::vector<std::shared_ptr<Species>>() && !skip_vectors_export()) {
  116. ss << ind << "species = " << export_vec_species(out, ctx, exported_name) << "," << nl;
  117. }
  118. if (reaction_rules != std::vector<std::shared_ptr<ReactionRule>>() && !skip_vectors_export()) {
  119. ss << ind << "reaction_rules = " << export_vec_reaction_rules(out, ctx, exported_name) << "," << nl;
  120. }
  121. if (surface_classes != std::vector<std::shared_ptr<SurfaceClass>>() && !skip_vectors_export()) {
  122. ss << ind << "surface_classes = " << export_vec_surface_classes(out, ctx, exported_name) << "," << nl;
  123. }
  124. if (elementary_molecule_types != std::vector<std::shared_ptr<ElementaryMoleculeType>>() && !skip_vectors_export()) {
  125. ss << ind << "elementary_molecule_types = " << export_vec_elementary_molecule_types(out, ctx, exported_name) << "," << nl;
  126. }
  127. ss << ")" << nl << nl;
  128. if (!str_export) {
  129. out << ss.str();
  130. return exported_name;
  131. }
  132. else {
  133. return ss.str();
  134. }
  135. }
  136. std::string GenSubsystem::export_vec_species(std::ostream& out, PythonExportContext& ctx, const std::string& parent_name) {
  137. // prints vector into 'out' and returns name of the generated list
  138. std::stringstream ss;
  139. std::string exported_name;
  140. if (parent_name != ""){
  141. exported_name = parent_name+ "_species";
  142. }
  143. else {
  144. exported_name = "species";
  145. }
  146. ss << exported_name << " = [\n";
  147. for (size_t i = 0; i < species.size(); i++) {
  148. const auto& item = species[i];
  149. if (i == 0) {
  150. ss << " ";
  151. }
  152. else if (i % 16 == 0) {
  153. ss << "\n ";
  154. }
  155. if (!item->skip_python_export()) {
  156. std::string name = item->export_to_python(out, ctx);
  157. ss << name << ", ";
  158. }
  159. }
  160. ss << "\n]\n\n";
  161. out << ss.str();
  162. return exported_name;
  163. }
  164. std::string GenSubsystem::export_vec_reaction_rules(std::ostream& out, PythonExportContext& ctx, const std::string& parent_name) {
  165. // prints vector into 'out' and returns name of the generated list
  166. std::stringstream ss;
  167. std::string exported_name;
  168. if (parent_name != ""){
  169. exported_name = parent_name+ "_reaction_rules";
  170. }
  171. else {
  172. exported_name = "reaction_rules";
  173. }
  174. ss << exported_name << " = [\n";
  175. for (size_t i = 0; i < reaction_rules.size(); i++) {
  176. const auto& item = reaction_rules[i];
  177. if (i == 0) {
  178. ss << " ";
  179. }
  180. else if (i % 16 == 0) {
  181. ss << "\n ";
  182. }
  183. if (!item->skip_python_export()) {
  184. std::string name = item->export_to_python(out, ctx);
  185. ss << name << ", ";
  186. }
  187. }
  188. ss << "\n]\n\n";
  189. out << ss.str();
  190. return exported_name;
  191. }
  192. std::string GenSubsystem::export_vec_surface_classes(std::ostream& out, PythonExportContext& ctx, const std::string& parent_name) {
  193. // prints vector into 'out' and returns name of the generated list
  194. std::stringstream ss;
  195. std::string exported_name;
  196. if (parent_name != ""){
  197. exported_name = parent_name+ "_surface_classes";
  198. }
  199. else {
  200. exported_name = "surface_classes";
  201. }
  202. ss << exported_name << " = [\n";
  203. for (size_t i = 0; i < surface_classes.size(); i++) {
  204. const auto& item = surface_classes[i];
  205. if (i == 0) {
  206. ss << " ";
  207. }
  208. else if (i % 16 == 0) {
  209. ss << "\n ";
  210. }
  211. if (!item->skip_python_export()) {
  212. std::string name = item->export_to_python(out, ctx);
  213. ss << name << ", ";
  214. }
  215. }
  216. ss << "\n]\n\n";
  217. out << ss.str();
  218. return exported_name;
  219. }
  220. std::string GenSubsystem::export_vec_elementary_molecule_types(std::ostream& out, PythonExportContext& ctx, const std::string& parent_name) {
  221. // prints vector into 'out' and returns name of the generated list
  222. std::stringstream ss;
  223. std::string exported_name;
  224. if (parent_name != ""){
  225. exported_name = parent_name+ "_elementary_molecule_types";
  226. }
  227. else {
  228. exported_name = "elementary_molecule_types";
  229. }
  230. ss << exported_name << " = [\n";
  231. for (size_t i = 0; i < elementary_molecule_types.size(); i++) {
  232. const auto& item = elementary_molecule_types[i];
  233. if (i == 0) {
  234. ss << " ";
  235. }
  236. else if (i % 16 == 0) {
  237. ss << "\n ";
  238. }
  239. if (!item->skip_python_export()) {
  240. std::string name = item->export_to_python(out, ctx);
  241. ss << name << ", ";
  242. }
  243. }
  244. ss << "\n]\n\n";
  245. out << ss.str();
  246. return exported_name;
  247. }
  248. } // namespace API
  249. } // namespace MCell