observables.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. #include "api/observables.h"
  12. #include "api/subsystem.h"
  13. #include "bng/bng.h"
  14. #include "api/component_type.h"
  15. #include "api/component.h"
  16. #include "api/elementary_molecule_type.h"
  17. #include "api/elementary_molecule.h"
  18. #include "api/complex.h"
  19. #include "api/api_utils.h"
  20. using namespace std;
  21. using namespace BNG;
  22. namespace MCell {
  23. namespace API {
  24. void Observables::dump() const {
  25. std::cout << to_str() << "\n";
  26. }
  27. std::string Observables::get_first_viz_output_files_prefix(const char* method_name) {
  28. // use the first viz_output
  29. if (viz_outputs.empty()) {
  30. throw ValueError(
  31. S("Method ") + method_name + " requires a file argument when there are no instances of " +
  32. NAME_CLASS_VIZ_OUTPUT + " present."
  33. );
  34. }
  35. if (!is_set(viz_outputs[0]->output_files_prefix)) {
  36. throw ValueError(
  37. S("Method ") + method_name + ": the first VizOutput instance does not have its " +
  38. NAME_OUTPUT_FILES_PREFIX + " set."
  39. );
  40. }
  41. return viz_outputs[0]->output_files_prefix;
  42. }
  43. CountOutputFormat Observables::count_output_format_from_path_or_file(const std::string& path_or_file) {
  44. const string gdat = ".gdat";
  45. size_t gdat_sz = gdat.size();
  46. size_t sz = path_or_file.size();
  47. if (sz > gdat.size() && path_or_file.substr(sz - gdat_sz) == gdat) {
  48. return CountOutputFormat::GDAT;
  49. }
  50. else {
  51. return CountOutputFormat::DAT;
  52. }
  53. }
  54. CountOutputFormat Observables::get_count_output_format(
  55. const CountOutputFormat observables_output_format,
  56. const std::string& observables_path_or_file
  57. ) {
  58. CountOutputFormat fmt;
  59. if (observables_output_format == CountOutputFormat::AUTOMATIC_FROM_EXTENSION) {
  60. return count_output_format_from_path_or_file(observables_path_or_file);
  61. }
  62. else {
  63. if (observables_path_or_file == "" &&
  64. observables_output_format == CountOutputFormat::GDAT) {
  65. throw RuntimeError(S("Attribute ") + NAME_OBSERVABLES_PATH_OR_FILE + " must not be empty " +
  66. "when " + NAME_OBSERVABLES_OUTPUT_FORMAT + " is " + NAME_ENUM_COUNT_OUTPUT_FORMAT + "." +
  67. NAME_EV_GDAT + ".");
  68. }
  69. return observables_output_format;
  70. }
  71. }
  72. void Observables::load_bngl_observables(
  73. const std::string& file_name,
  74. const std::string& observables_path_or_file,
  75. const std::map<std::string, double>& parameter_overrides,
  76. const CountOutputFormat observables_output_format) {
  77. BNG::BNGData bng_data;
  78. int num_errors = BNG::parse_bngl_file(file_name, bng_data, parameter_overrides);
  79. if (num_errors != 0) {
  80. throw RuntimeError("Could not parse BNGL file " + file_name + ".");
  81. }
  82. // now convert everything we parsed into the API classes so that the user can
  83. // inspect or manipulate it if needed
  84. convert_bng_data_to_observables_data(
  85. bng_data,
  86. get_count_output_format(observables_output_format, observables_path_or_file),
  87. observables_path_or_file);
  88. }
  89. void Observables::convert_bng_data_to_observables_data(
  90. const BNG::BNGData& bng_data,
  91. const CountOutputFormat observables_output_format,
  92. const std::string& observables_path_or_file) {
  93. for (const Observable& o: bng_data.get_observables()) {
  94. convert_observable(o, bng_data, observables_path_or_file, observables_output_format);
  95. }
  96. }
  97. static void set_count_molecules_or_species_pattern(
  98. const BNG::ObservableType type,
  99. const BNG::Cplx& bng_pattern,
  100. const BNG::BNGData& bng_data,
  101. API::CountTerm& count
  102. ) {
  103. std::shared_ptr<API::Complex> pattern =
  104. Complex::construct_from_bng_cplx(bng_data, bng_pattern);
  105. if (type == ObservableType::Molecules) {
  106. count.molecules_pattern = pattern;
  107. }
  108. else if (type == ObservableType::Species) {
  109. count.species_pattern = pattern;
  110. }
  111. else {
  112. release_assert(false);
  113. }
  114. }
  115. void Observables::convert_observable(
  116. const BNG::Observable& o,
  117. const BNG::BNGData& bng_data,
  118. const std::string& observables_path_or_file,
  119. const CountOutputFormat observables_output_format) {
  120. shared_ptr<API::Count> count = make_shared<Count>(DefaultCtorArgType());
  121. count->expression = make_shared<CountTerm>(DefaultCtorArgType());
  122. count->name = o.name;
  123. if (observables_output_format == CountOutputFormat::DAT) {
  124. if (is_set(observables_path_or_file)) {
  125. count->file_name = observables_path_or_file + o.name + ".dat";
  126. }
  127. else {
  128. // will be set during conversion
  129. count->file_name = STR_UNSET;
  130. }
  131. }
  132. else if (observables_output_format == CountOutputFormat::GDAT) {
  133. count->file_name = observables_path_or_file;
  134. }
  135. else {
  136. release_assert(false && "Invalid count output format.");
  137. }
  138. count->output_format = observables_output_format;
  139. release_assert(!o.patterns.empty() && "Observable has no pattern");
  140. if (o.patterns.size() == 1) {
  141. set_count_molecules_or_species_pattern(o.type, o.patterns[0], bng_data, *count->expression);
  142. }
  143. else {
  144. shared_ptr<API::CountTerm> top_level_term = nullptr;
  145. for (const auto& pat: o.patterns) {
  146. shared_ptr<API::CountTerm> term = make_shared<CountTerm>(DefaultCtorArgType());
  147. set_count_molecules_or_species_pattern(o.type, pat, bng_data, *term);
  148. if (is_set(top_level_term)) {
  149. top_level_term = top_level_term->__add__(term);
  150. }
  151. else {
  152. top_level_term = term;
  153. }
  154. }
  155. count->expression = top_level_term;
  156. }
  157. // remember for conversion in mcell4 coverter
  158. counts.push_back(count);
  159. }
  160. } // namespace API
  161. } // namespace MCell