BioDynaMo  v1.03.58-27764645
command_line_options.cc
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------
2 //
3 // Copyright (C) 2021 CERN & University of Surrey for the benefit of the
4 // BioDynaMo collaboration. All Rights Reserved.
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 //
9 // See the LICENSE file distributed with this work for details.
10 // See the NOTICE file distributed with this work for additional information
11 // regarding copyright ownership.
12 //
13 // -----------------------------------------------------------------------------
14 
16 #include <TEnv.h>
17 #include <utility>
18 #include "core/param/param.h"
19 #include "core/util/io.h"
20 #include "core/util/log.h"
21 
22 namespace bdm {
23 
24 using cxxopts::value;
25 using std::string;
26 
27 CommandLineOptions::CommandLineOptions(int argc, const char** argv)
28  : argc_(argc),
29  argv_(argv),
30  options_(argv[0], " -- BioDynaMo command line options\n") {
32  ExtractSimulationName(argv[0]);
33 }
34 
36  if (parser_) {
37  delete parser_;
38  parser_ = nullptr;
39  }
40 }
41 
42 cxxopts::OptionAdder CommandLineOptions::AddOption(string group) {
43  if (parser_ != nullptr) {
44  Log::Fatal("CommandLineOptions::AddOption",
45  "Please add all your command line options before:\n 1) Using "
46  "the Get() method.\n 2) Creating a Simulation object.");
47  }
48  return cxxopts::OptionAdder(options_, std::move(group));
49 }
50 
52 
55  // Make a non-const deep copy of argv
56  char** argv_copy = (char**)malloc((argc_ + 1) * sizeof(char*));
57  int argc_copy = argc_;
58  for (int i = 0; i < argc_; ++i) {
59  size_t length = strlen(argv_[i]) + 1;
60  argv_copy[i] = (char*)malloc(length);
61  memcpy(argv_copy[i], argv_[i], length);
62  }
63  argv_copy[argc_] = NULL;
64 
65  // Perform parsing (consumes argc_copy and argv_copy)
66  if (parser_) {
67  delete parser_;
68  parser_ = nullptr;
69  }
70 
71  try {
72  parser_ = new cxxopts::ParseResult(options_.parse(argc_copy, argv_copy));
73  } catch (const cxxopts::option_not_exists_exception& option) {
74  Log::Fatal("CommandLineOptions::ParseResult", option.what(),
75  " Perhaps you are constructing multiple Simulation objects with "
76  "different CommandLineOptions.");
77  }
78 
79  if (first_parse_) {
80  // Perform operations on core command line options
82  first_parse_ = false;
83  }
84 
85  // free memory
86  for (int i = 0; i < argc_; ++i) {
87  free(argv_copy[i]);
88  }
89  free(argv_copy);
90 }
91 
92 bool CommandLineOptions::IsSet(std::string option) {
93  if (parser_ == nullptr) {
94  this->Parse();
95  }
96  return parser_->count(option) == 0 ? false : true;
97 }
98 
99 // clang-format off
101  options_.add_options("Core")
102  ("h, help", "Print this help message.")
103  ("version", "Print version number of BioDynaMo.")
104  ("opencl", "Enable GPU acceleration through OpenCL.")
105  ("cuda", "Enable GPU acceleration through CUDA.")
106  ("visualize", "Enable exporting of visualization.")
107  ("vis-frequency", "Set the frequency of exporting the visualization.", value<uint32_t>()->default_value("10"), "FREQ")
108  ("v, verbose", "Verbose mode. Causes BioDynaMo to print debugging messages. Multiple "
109  "-v options increases the verbosity. The maximum is 3.", value<bool>())
110  ("r, restore", "Restores the simulation from the checkpoint found in FILE and "
111  "continues simulation from that point.", value<string>()->default_value(""), "FILE")
112  ("b, backup", "Periodically create full simulation backup to the specified file. "
113  "NOTA BENE: File will be overriden if it exists.", value<string>()->default_value(""), "FILE")
114  ("c, config", "The TOML or JSON configuration that should be used. The JSON file must be in JSON merge patch format (https://tools.ietf.org/html/rfc7386). This option can be used multiple times.", value<std::vector<string>>()->default_value(""), "FILE")
115  ("inline-config", "JSON configuration string passed directly on the command line. Overwrites values specified in config file. The JSON string must be in JSON merge patch format (https://tools.ietf.org/html/rfc7386). This option can be used multiple times.", value<std::vector<string>>()->default_value(""), "JSON_STRING")
116  ("output-default-json", "Prints a JSON string with all parameters and their default values and exits.")
117  ("toml-to-json", "Converts a TOML file to a JSON patch. After printing the JSON patch the application will exit.", value<string>()->default_value(""), "TOML_FILE");
118 }
119 // clang-format on
120 
122  string s(path);
123  auto pos = s.find_last_of('/');
124  if (pos == std::string::npos) {
125  sim_name_ = s;
126  } else {
127  sim_name_ = s.substr(pos + 1, s.length() - 1);
128  }
129 }
130 
132  // Handle "help" argument
133  if (parser_->count("help")) {
134  auto groups = options_.groups();
135  auto it = std::find(groups.begin(), groups.end(), "Core");
136  std::rotate(it, it + 1, groups.end());
137  std::cout << options_.help(groups) << std::endl;
138  exit(0);
139  }
140 
141  if (IsSet("version")) {
142  std::cout << "BioDynaMo Version: " << Version::String() << std::endl;
143  exit(0);
144  }
145 
146  // Handle "verbose" argument
147  // If set in etc/bdm.rootrc use that value, command line argument will
148  // override it
149  Int_t ll = kWarning;
150  TString slevel = "Warning";
151  TEnvRec* rec = gEnv->Lookup("Root.ErrorIgnoreLevel");
152  if (rec) {
153  if (rec->GetLevel() == kEnvUser)
154  slevel = rec->GetValue();
155  }
156  if (!slevel.CompareTo("Print", TString::kIgnoreCase))
157  ll = kPrint;
158  else if (!slevel.CompareTo("Info", TString::kIgnoreCase))
159  ll = kInfo;
160  else if (!slevel.CompareTo("Warning", TString::kIgnoreCase))
161  ll = kWarning;
162  else if (!slevel.CompareTo("Error", TString::kIgnoreCase))
163  ll = kError;
164 
165  if (IsSet("verbose")) {
166  auto verbosity = parser_->count("verbose");
167 
168  switch (verbosity) {
169  // case 0 can never occur; we wouldn't go into this if statement
170  case 1:
171  ll = kWarning;
172  break;
173  case 2:
174  ll = kInfo;
175  break;
176  case 3:
177  ll = kPrint;
178  break;
179  default:
180  ll = kPrint;
181  break;
182  }
183  }
184  // Global variable of ROOT that determines verbosity of logging functions
185  gErrorIgnoreLevel = ll;
186 
187  if (parser_->count("output-default-json")) {
188  Param param;
189  std::cout << "Below you can find a JSON string with all available "
190  "parameters and their default values.\n"
191  << "Have a look at https://biodynamo.org/bioapi/ for more "
192  "details about each parameter."
193  << std::endl;
194  std::cout << param.ToJsonString() << std::endl;
195  exit(0);
196  }
197 
198  auto toml_file = (*parser_)["toml-to-json"].as<std::string>();
199  if (toml_file != "") {
200  if (!FileExists(toml_file)) {
201  Log::Fatal("CommandLineOptions::HandleCoreOptions",
202  "Specified TOML file (", toml_file, ") does not exist.");
203  }
204  auto toml = cpptoml::parse_file(toml_file);
205  Param param;
206  param.AssignFromConfig(toml);
207  std::cout << param.ToJsonString() << std::endl;
208  exit(0);
209  }
210 }
211 
212 std::ostream& operator<<(std::ostream& os, const CommandLineOptions& clo) {
213  for (int i = 0; i < clo.argc_; ++i) {
214  os << clo.argv_[i] << " ";
215  }
216  return os;
217 }
218 
219 } // namespace bdm
bdm::CommandLineOptions::options_
cxxopts::Options options_
Definition: command_line_options.h:94
bdm::CommandLineOptions::IsSet
bool IsSet(std::string option)
Check if the argument for the specified option was set.
Definition: command_line_options.cc:92
bdm::CommandLineOptions::argv_
const char ** argv_
Definition: command_line_options.h:88
bdm::CommandLineOptions::sim_name_
std::string sim_name_
Definition: command_line_options.h:90
bdm
Definition: agent.cc:39
bdm::CommandLineOptions::AddOption
void AddOption(const std::string &opt, std::string def, const std::string &description="", std::string group="Simulation")
Add an extra command line option.
Definition: command_line_options.h:45
bdm::CommandLineOptions::parser_
cxxopts::ParseResult * parser_
Definition: command_line_options.h:95
bdm::Param::ToJsonString
std::string ToJsonString() const
Definition: param.cc:108
bdm::CommandLineOptions::first_parse_
bool first_parse_
Definition: command_line_options.h:93
bdm::CommandLineOptions::CommandLineOptions
CommandLineOptions(int argc, const char **argv)
Definition: command_line_options.cc:27
bdm::CommandLineOptions::Parse
void Parse()
Parse the options with the given command line arguments.
Definition: command_line_options.cc:54
bdm::CommandLineOptions::ExtractSimulationName
void ExtractSimulationName(const char *path)
Definition: command_line_options.cc:121
command_line_options.h
bdm::FileExists
bool FileExists(const std::string &file_name)
Definition: io.cc:78
bdm::Log::Fatal
static void Fatal(const std::string &location, const Args &... parts)
Prints fatal error message.
Definition: log.h:115
log.h
bdm::Param::AssignFromConfig
void AssignFromConfig(const std::shared_ptr< cpptoml::table > &)
Assign values from config file to variables.
Definition: param.cc:220
bdm::CommandLineOptions::GetSimulationName
std::string GetSimulationName()
Return the simulation name that was parsed from argv[0].
Definition: command_line_options.cc:51
bdm::operator<<
std::ostream & operator<<(std::ostream &o, const MathArray< T, N > &arr)
Definition: math_array.h:412
io.h
param.h
bdm::Param
Definition: param.h:35
bdm::CommandLineOptions::AddCoreOptions
void AddCoreOptions()
Definition: command_line_options.cc:100
bdm::CommandLineOptions::HandleCoreOptions
void HandleCoreOptions()
Takes care of core options.
Definition: command_line_options.cc:131
bdm::CommandLineOptions
Class to contain and parse command line options.
Definition: command_line_options.h:37
bdm::CommandLineOptions::~CommandLineOptions
~CommandLineOptions()
Definition: command_line_options.cc:35
bdm::CommandLineOptions::argc_
int argc_
Definition: command_line_options.h:87