data_model_to_pymcell.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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 _MSC_VER
  12. #include <getopt.h>
  13. #else
  14. #include "win_getopt/win_getopt.h"
  15. #endif
  16. #include <iostream>
  17. #include <cassert>
  18. #include <string>
  19. #include <ctype.h>
  20. #include "mcell4_generator.h"
  21. #include "generator_structs.h"
  22. #include "version.h"
  23. using namespace std;
  24. /* Command-line arguments structure:
  25. * long arg name
  26. * has argument
  27. * pointer to flag (should always be 0)
  28. * short argument letter
  29. */
  30. static const option long_options[] = {
  31. { "help", 0, 0, 'h' },
  32. { "version", 0, 0, 'v' },
  33. { "debug", 0, 0, 'g' },
  34. { "testing", 0, 0, 't' },
  35. { "checkpoint_iters", 1, 0, 'k' },
  36. { "bng", 0, 0, 'b' },
  37. { "not_overridable_python_params", 0, 0, 'p'},
  38. { "output_file_prefix", 1, 0, 'o'},
  39. { nullptr, 0, 0, 0 }
  40. };
  41. void print_usage(const char* argv0) {
  42. cout << argv0 << " options:\n";
  43. size_t i = 0;
  44. while (long_options[i].name != nullptr) {
  45. cout << " -" << (char)long_options[i].val << "| -" << long_options[i].name << "\n";
  46. i++;
  47. }
  48. }
  49. void print_version(const char* argv0) {
  50. cout << argv0 << " version:" << MCELL_VERSION << "\n";
  51. }
  52. // iters_arg is a list of integers separated by comma
  53. std::vector<int> parse_checkpoint_iters(char* iters_arg) {
  54. assert(iters_arg != nullptr);
  55. std::vector<int> res;
  56. string current;
  57. char* c = iters_arg;
  58. while (*c != '\0') {
  59. if (*c == ' ') {
  60. // continue
  61. }
  62. if (isdigit(*c)) {
  63. current += *c;
  64. }
  65. else if (*c == ',') {
  66. if (current == "") {
  67. cerr <<
  68. "Could not parse comma-separated list of integers for argument -k: '" <<
  69. iters_arg << "'.\n";
  70. exit(1);
  71. }
  72. // conversion is safe because we are in
  73. res.push_back(stoi(current));
  74. current = "";
  75. }
  76. else {
  77. cerr <<
  78. "Could not parse comma-separated list of integers for argument -k: '" <<
  79. iters_arg << "'.\n";
  80. exit(1);
  81. }
  82. c++;
  83. }
  84. if (current != "") {
  85. res.push_back(stoi(current));
  86. }
  87. return res;
  88. }
  89. const int ARG_PARSE_ERROR = 1;
  90. const int ARG_PARSE_QUIT = 0;
  91. const int ARG_PARSE_OK = -1;
  92. // returns ARG_PARSE_OK if execution should continue
  93. // ARG_PARSE_END to end with exit code 0,
  94. // ARG_PARSE_ERROR to end with exit code 1,
  95. int process_args(
  96. const int argc, char* argv[],
  97. MCell::SharedGenData& opts
  98. ) {
  99. opts.reset();
  100. assert(argc > 0);
  101. while (1) {
  102. // get the next argument
  103. int c = getopt_long_only(argc, argv, "hvgtk:cbo:", long_options, nullptr);
  104. if (c == -1)
  105. break;
  106. switch (c) {
  107. case 'h':
  108. print_usage(argv[0]);
  109. return ARG_PARSE_QUIT;
  110. case 'v':
  111. print_version(argv[0]);
  112. return ARG_PARSE_QUIT;
  113. case 'g':
  114. opts.debug_mode = true;
  115. break;
  116. case 't':
  117. opts.testing_mode = true;
  118. break;
  119. case 'p':
  120. opts.not_overridable_python_params = true;
  121. break;
  122. case 'k':
  123. opts.checkpoint_iterations = parse_checkpoint_iters(optarg);
  124. opts.testing_mode = true;
  125. break;
  126. case 'b':
  127. opts.bng_mode = true;
  128. break;
  129. case 'o':
  130. opts.output_files_prefix = optarg;
  131. break;
  132. default:
  133. cerr << "Invalid arguments.\n";
  134. print_usage(argv[0]);
  135. return ARG_PARSE_ERROR;
  136. }
  137. }
  138. if (optind < argc) {
  139. if (argc - optind > 1) {
  140. cerr << "Only one input data model file can be specified.\n";
  141. return ARG_PARSE_ERROR;
  142. }
  143. opts.input_file = argv[optind];
  144. }
  145. else {
  146. cerr << "Input data model file file was not specified.\n";
  147. return ARG_PARSE_ERROR;
  148. }
  149. if (opts.output_files_prefix == "Untitled" || opts.output_files_prefix == "Scene") {
  150. cout << "Ignoring files prefix '" << opts.output_files_prefix << "'.\n";
  151. opts.output_files_prefix = "";
  152. }
  153. return ARG_PARSE_OK;
  154. }
  155. int main(const int argc, char* argv[]) {
  156. MCell::SharedGenData opts;
  157. int arg_process_res = process_args(argc, argv, opts);
  158. if (arg_process_res != ARG_PARSE_OK) {
  159. return arg_process_res;
  160. }
  161. MCell::MCell4Generator converter;
  162. bool ok = converter.generate(opts);
  163. if (!ok) {
  164. cerr << "There was an error while converting " << opts.input_file << " to pymcell code.\n";
  165. return 1;
  166. }
  167. return 0;
  168. }