species.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /******************************************************************************
  2. *
  3. * Copyright (C) 2020 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. #ifndef API_SPECIES_H
  12. #define API_SPECIES_H
  13. #include "generated/gen_species.h"
  14. #include "generated/gen_constants.h"
  15. #include "api/api_common.h"
  16. #include "api/api_utils.h"
  17. #include "api/complex.h"
  18. #include "elementary_molecule_type.h"
  19. #include "bng/bng_defines.h"
  20. namespace MCell {
  21. namespace API {
  22. class Species: public GenSpecies {
  23. public:
  24. SPECIES_CTOR()
  25. Species(Complex& cplx_inst)
  26. : GenSpecies(cplx_inst.to_bngl_str()) {
  27. set_all_custom_attributes_to_default();
  28. set_all_attributes_as_default_or_unset();
  29. // set copied value, cannot use GenSpecies ctor because we need to reset the attributes
  30. // warning: must be updated if Complex class' attributes change
  31. name = cplx_inst.name;
  32. elementary_molecules = cplx_inst.elementary_molecules;
  33. // should not be really used in Species but copying it as well for consistency
  34. orientation = cplx_inst.orientation;
  35. }
  36. void set_name(const std::string& name_) override {
  37. BaseDataClass::set_name(name_);
  38. // rerun initialization because the name is parsed as a BNGL string
  39. elementary_molecules.clear();
  40. postprocess_in_ctor();
  41. }
  42. void check_no_extra_fields_are_set() const {
  43. std::string msg =
  44. " must not be set for complex species because it is derived from its elementary molecule types.";
  45. if (is_set(diffusion_constant_2d)) {
  46. throw ValueError(S("Field ") + NAME_DIFFUSION_CONSTANT_2D + msg);
  47. }
  48. if (is_set(diffusion_constant_3d)) {
  49. throw ValueError(S("Field ") + NAME_DIFFUSION_CONSTANT_3D + msg);
  50. }
  51. if (is_set(custom_time_step)) {
  52. throw ValueError(S("Field ") + NAME_CUSTOM_TIME_STEP + msg);
  53. }
  54. if (is_set(custom_space_step)) {
  55. throw ValueError(S("Field ") + NAME_CUSTOM_SPACE_STEP + msg);
  56. }
  57. if (target_only) {
  58. throw ValueError(S("Field ") + NAME_TARGET_ONLY + msg);
  59. }
  60. }
  61. // we are making changes, so semantic checks are here instead of in const check_semantics
  62. void postprocess_in_ctor() override {
  63. // initialization
  64. set_all_custom_attributes_to_default();
  65. // not calling derived check semantics
  66. if (get_num_set(name, elementary_molecules) != 1) {
  67. throw ValueError(
  68. S("Exactly one of ") + NAME_NAME + " or " + NAME_ELEMENTARY_MOLECULES +
  69. " must be set for " + NAME_CLASS_SPECIES + ".");
  70. }
  71. // 1) simple species defined by name
  72. if (is_set(name) && !is_set(elementary_molecules) &&
  73. (is_set(diffusion_constant_2d) || is_set(diffusion_constant_3d))) {
  74. if (!is_simple_species(name)) {
  75. throw ValueError("Only simple species can be fully defined by setting name and diffusion constant. "
  76. "For complex species, it cannot be usually deduced what the diffusion constants of elementary molecule types should be.");
  77. }
  78. if (name.find('.') != std::string::npos) {
  79. throw ValueError("Simple species name must not contain '.', this is incompatible with BNGL definition"
  80. ", error for " + name + ".");
  81. }
  82. if (is_set(diffusion_constant_2d) && is_set(diffusion_constant_3d)) {
  83. throw ValueError("Only one of fields diffusion_constant_2d or diffusion_constant_3d can be set for simple species.");
  84. }
  85. if (get_num_set(custom_time_step, custom_space_step) > 1) {
  86. throw ValueError(S("Only one of ") + NAME_CUSTOM_TIME_STEP + " or " + NAME_CUSTOM_SPACE_STEP +
  87. " may be set at the same time.");
  88. }
  89. // create a single ElementaryMoleculeType
  90. // will be added on initialization to model's elementary_molecule_types
  91. auto mt = std::make_shared<ElementaryMoleculeType>(
  92. name, std::vector<std::shared_ptr<ComponentType>>(),
  93. diffusion_constant_2d, diffusion_constant_3d,
  94. custom_time_step, custom_space_step,
  95. target_only
  96. );
  97. // and then molecule instance out of it
  98. elementary_molecules.push_back(
  99. std::make_shared<ElementaryMolecule>(mt)
  100. );
  101. }
  102. // 2) complex species defined through elementary_molecule_instances, or
  103. // 3) declaration (name is parsed in Complex::postprocess_in_ctor)
  104. else {
  105. // do semantic check
  106. check_no_extra_fields_are_set();
  107. }
  108. // need to finalize the initialization, also processes compartments
  109. Complex::postprocess_in_ctor();
  110. if (get_primary_compartment_name() == BNG::COMPARTMENT_NAME_IN ||
  111. get_primary_compartment_name() == BNG::COMPARTMENT_NAME_OUT) {
  112. throw ValueError(S(NAME_CLASS_SPECIES) + " with " + NAME_NAME + " " + name +
  113. " must not use compartments " + BNG::COMPARTMENT_NAME_IN + " or " + BNG::COMPARTMENT_NAME_OUT + ".");
  114. }
  115. }
  116. void set_all_custom_attributes_to_default() override {
  117. Complex::set_all_custom_attributes_to_default();
  118. species_id = SPECIES_ID_INVALID;
  119. }
  120. // using shorter printout when all_details is false
  121. std::string to_str(const bool all_details=false, const std::string ind="") const override;
  122. bool __eq__(const Species& other) const override;
  123. std::shared_ptr<Complex> inst(const Orientation orientation = Orientation::DEFAULT, const std::string& compartment_name = "") override {
  124. if (orientation != Orientation::DEFAULT && is_set(compartment_name)) {
  125. throw ValueError(S("Maximum one of ") + NAME_ORIENTATION + " or " + NAME_COMPARTMENT_NAME + " can be set not both.");
  126. }
  127. // make a deep copy and set extra attributes
  128. std::shared_ptr<Complex> res = deepcopy_complex();
  129. res->orientation = orientation;
  130. res->set_compartment_name(compartment_name);
  131. return res;
  132. }
  133. bool skip_python_export() const override {
  134. return is_species_superclass();
  135. }
  136. // default generated variant exports all details, we do not want this because
  137. // we export just the BNGL name and recompute the diffusion constant
  138. // and other fields from the elementary molecule types this species uses
  139. std::string export_to_python(std::ostream& out, PythonExportContext& ctx) override;
  140. bool is_species_superclass() const {
  141. return BNG::is_species_superclass(name);
  142. }
  143. bool warn_if_adding_identical_object() const { return true; }
  144. // simulation engine mapping
  145. species_id_t species_id;
  146. };
  147. } // namespace API
  148. } // namespace MCell
  149. #endif // API_SPECIES_H