count_term.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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_COUNT_TERM_H
  12. #define API_COUNT_TERM_H
  13. #include "generated/gen_count_term.h"
  14. #include "api/api_common.h"
  15. #include "api/region.h"
  16. #include "api/reaction_rule.h"
  17. #include "api/complex.h"
  18. namespace MCell {
  19. namespace API {
  20. class CountTerm: public GenCountTerm, public std::enable_shared_from_this<CountTerm> {
  21. public:
  22. COUNT_TERM_CTOR()
  23. void postprocess_in_ctor() override {
  24. set_all_custom_attributes_to_default();
  25. }
  26. void set_all_custom_attributes_to_default() override {
  27. initial_reactions_count_export_override = 0;
  28. }
  29. void check_semantics() const override {
  30. GenCountTerm::check_semantics();
  31. if (is_set(reaction_rule) && is_set(reaction_rule->rev_rate)) {
  32. throw ValueError(S("Reversible reactions cannot counted because it is not clear which direction should be counted.") +
  33. " Error for " + NAME_CLASS_COUNT_TERM + " " + name + ". Split the reaction rule into its forward and reverse variants if needed.");
  34. }
  35. // TODO: add test for this case, not sure if the check works correctly because pattern does not have to be initialized
  36. if (is_set(get_pattern(false)) &&
  37. BNG::get_in_or_out_compartment_id(get_pattern()->compartment_name) != BNG::COMPARTMENT_ID_INVALID) {
  38. throw ValueError(
  39. S(NAME_CLASS_COUNT) + " or " + NAME_CLASS_COUNT_TERM + " must not use compartment class name " +
  40. get_pattern()->get_primary_compartment_name() + ".");
  41. }
  42. }
  43. // called from Count::check_semantics()
  44. void check_that_species_or_reaction_rule_is_set() {
  45. if (node_type == ExprNodeType::LEAF) {
  46. uint num_set = get_num_set(species_pattern, molecules_pattern, reaction_rule);
  47. if (num_set != 1) {
  48. // NOTE: does not give much information on where to search for the error
  49. throw ValueError(
  50. S("Exactly one of ") + NAME_SPECIES_PATTERN + ", " +
  51. NAME_MOLECULES_PATTERN + " or " + NAME_REACTION_RULE + " must be set for one of the " +
  52. NAME_CLASS_COUNT_TERM + " used in " + NAME_CLASS_COUNT + ".");
  53. }
  54. }
  55. else {
  56. left_node->check_that_species_or_reaction_rule_is_set();
  57. right_node->check_that_species_or_reaction_rule_is_set();
  58. }
  59. }
  60. std::shared_ptr<CountTerm> create_expr_term(ExprNodeType op, std::shared_ptr<CountTerm> op2) {
  61. std::shared_ptr<CountTerm> res = std::make_shared<CountTerm>(DefaultCtorArgType());
  62. res->node_type = op;
  63. res->left_node = shared_from_this();
  64. res->right_node = op2;
  65. return res;
  66. }
  67. std::shared_ptr<CountTerm> __add__(std::shared_ptr<CountTerm> op2) override {
  68. return create_expr_term(ExprNodeType::ADD, op2);
  69. }
  70. std::shared_ptr<CountTerm> __sub__(std::shared_ptr<CountTerm> op2) override {
  71. return create_expr_term(ExprNodeType::SUB, op2);
  72. }
  73. // manually added, may return empty shared_ptr if reaction_rule
  74. // is counted
  75. std::shared_ptr<Complex> get_pattern(bool must_be_present = true) const {
  76. if (is_set(species_pattern)) {
  77. return species_pattern;
  78. }
  79. else if (is_set(molecules_pattern)) {
  80. return molecules_pattern;
  81. }
  82. else {
  83. assert(!must_be_present || is_set(reaction_rule));
  84. return std::shared_ptr<Complex>(nullptr);
  85. }
  86. }
  87. std::string export_to_python(std::ostream& out, PythonExportContext& ctx) override {
  88. // we need to overwrite the current value for export however we do not want to change it
  89. // permanently
  90. uint64_t initial_reactions_count_orig = initial_reactions_count;
  91. initial_reactions_count = initial_reactions_count_export_override;
  92. std::string res = GenCountTerm::export_to_python(out, ctx);
  93. initial_reactions_count = initial_reactions_count_orig;
  94. return res;
  95. }
  96. uint64_t initial_reactions_count_export_override;
  97. };
  98. } // namespace API
  99. } // namespace MCell
  100. #endif // API_COUNT_TERM_H