Calibrator  0.1
Command line tool for 14C calibration
main.cpp
Go to the documentation of this file.
1 
12 #include "../include/cal_curve.h"
13 #include "../include/uncal_date.h"
14 #include "../include/cal_date.h"
15 #include "../include/uncal_date_list.h"
16 #include "../include/cal_date_list.h"
17 
18 // Include the headers relevant to the boost::program_options
19 // library
20 #include <boost/program_options/options_description.hpp>
21 #include <boost/program_options/parsers.hpp>
22 #include <boost/program_options/variables_map.hpp>
23 #include <iostream>
24 #include <fstream>
25 #include <string>
26 #include <vector>
27 #include <istream>
28 #include <cctype>
29 
30 using namespace boost;
31 using namespace boost::program_options;
32 
39 int validate_numeric_string ( string &a )
40 {
41  unsigned i;
42  for ( i = 0; i < a.size(); i++ )
43  if ( !isdigit ( a[i] ) ) return 1;
44  return 0;
45 }
46 
55 int check_input_format(string &input_string) {
56  if( !input_string.empty() ) {
57  char first_char = input_string[0];
58  if (first_char == '{' || first_char == '['){
59  return 1; //json
60  } else if (first_char == '"' || first_char == '\'' || isalpha(first_char)) {
61  return 2; //csv
62  } else {
63  return 0;
64  }
65  }
66 }
67 
74 json csv_input_to_json(string &in) {
75  bool err = false;
76  json return_value;
77  unsigned head_length = 0;
78  char first_char = in.front();
79  if (isalpha(first_char)) head_length = 1;
80  string line;
81  int counter = 0;
82  std::istringstream iss(in);
83 
84  while (getline(iss, line)) {
85  json temp_json;
86  int bp = -1;
87  int std = -1;
88  if (counter >= head_length) {
89  std::stringstream iss(line);
90  if ( !iss.good() )
91  break;
92  std::string name_str;
93  std::getline(iss, name_str, ',');
94  std::string bp_str;
95  std::getline(iss, bp_str, ',');
96  std::string std_str;
97  std::getline(iss, std_str, ',');
98  if (!name_str.empty() && !bp_str.empty() && !std_str.empty()) {
99  if (validate_numeric_string(bp_str)==0) bp=atoi(bp_str.c_str());
100  if (validate_numeric_string(std_str)==0) std=atoi(std_str.c_str());
101  if (bp > 0 && std > 0) {
102  name_str.erase(remove( name_str.begin(), name_str.end(), '\"' ),name_str.end());
103  name_str.erase(remove( name_str.begin(), name_str.end(), '\'' ),name_str.end());
104  temp_json["bp"] = bp;
105  temp_json["std"] = std;
106  return_value[name_str] = temp_json;
107  } else {
108  err = true;
109  break;
110  }
111  } else {
112  err = true;
113  break;
114  }
115  }
116  counter++;
117  }
118  if (err) {
119  cout << "Invalid file format!" << std::endl;
120  cout << "Please use \"DateName\",bp,std" << std::endl;
121  return EXIT_FAILURE;
122  } else {
123  return return_value;
124  }
125 }
126 
131 int main(int argc , char **argv) {
132  json j;
133 
134  /*
135  * Defines the cli input parameters via boost.
136  */
137 
138  options_description desc(
139  "\nA tool for 14C calibration from the command line.\n\nAllowed arguments");
140 
141  desc.add_options()
142  ("help,h", "Produce this help message.")
143  ("input-file,i", value< vector<string> >(),
144  "Specifies input file.")
145  ("bp,b", value< vector<int> >(),
146  "The BP Value.")
147  ("std,s", value< vector<int> >(),
148  "The standard deviation.")
149  ("json-string,j", value< vector<string> >(),
150  "Input as as JSON string. Format: {\"bp\": xx, \"std\": xx}")
151  ("ranges,r", "calculate sigma ranges (only for json output).")
152  ("sum", "calculate sum probability.")
153  ("output,o", value<string>()->default_value("json"),
154  "csv for csv-output, json for json (default).");
155 
156  positional_options_description p;
157  p.add("input-file", -1);
158 
159  // Map the input parameters
160  variables_map vm;
161 
162  // Parse the input parameters
163  try {
164  store(command_line_parser(
165  argc, argv).options(desc).positional(p).run(), vm);
166  notify(vm);
167  } catch (std::exception &e) {
168  cout << endl << e.what() << endl;
169  cout << desc << endl;
170  }
171 
172  // Display help text when requested
173  if (vm.count("help")) {
174  cout << "–help specified" << endl;
175  cout << desc << endl;
176  return EXIT_SUCCESS;
177  }
178 
179  // Handles input files
180  if (vm.count("input-file")) {
181  vector<string> inputFilename =
182  vm["input-file"].as< vector<string> >();
183 
184  string line;
185  string file_content;
186  ifstream myfile(inputFilename[0]);
187  if (myfile.is_open()) {
188  while ( getline (myfile, line) ) {
189  file_content += line + '\n';
190  }
191  myfile.close();
192  } else {
193  cout << "Unable to open file";
194  }
195  int file_format = check_input_format(file_content);
196  switch(file_format){
197  case 1:
198  j = json::parse(file_content);
199  break;
200  case 2:
201  j = csv_input_to_json(file_content);
202  break;
203  default:
204  cout << "Invalid file format!";
205  return EXIT_FAILURE;
206  }
207  }
208 
209  // Handles json strings
210  if (vm.count("json-string")) {
211  vector<string> json_string =
212  vm["json-string"].as< vector<string> >();
213  j = json::parse(json_string[0]);
214  }
215 
216  // Handles output format parameter
217  string output_format =
218  vm["output"].as<string>();
219 
220  // Handles bp and std as cli parameters
221  if (vm.count("bp") && vm.count("std")) {
222  json j_temp;
223  vector<int> bp =
224  vm["bp"].as< vector<int> >();
225  vector<int> std =
226  vm["std"].as< vector<int> >();
227  j_temp["bp"] = bp[0];
228  j_temp["std"] = std[0];
229  j["date"] = j_temp;
230  }
231 
232  // Should the sigma ranges be calculated?
233  bool calc_sigma_ranges = false;
234  if (vm.count("ranges")) {
235  calc_sigma_ranges = true;
236  }
237 
238  // Instantize an uncalibrated date an a list for uncalibrated dates
239  UncalDate my_date;
240  UncalDateList my_date_list;
241 
242  for (json::iterator it = j.begin(); it != j.end(); ++it) {
243  my_date = UncalDate(it.key(), it.value()["bp"], it.value()["std"]);
244  my_date_list.push_back(my_date);
245  }
246 
247  // Read the calibration curve
248  string filename = "data/intcal13.14c";
249  CalCurve my_cal_curve = CalCurve();
250  my_cal_curve.import(filename);
251 
252  // Calibrate all dates in the uncalibrated date list
253  // and return a list of calibrated dates
254  CalDateList my_cal_date_list = my_date_list.calibrate(my_cal_curve);
255 
256  // If requested calculate the sum probability
257  if (vm.count("sum")) {
258  my_cal_date_list.sum();
259  }
260 
261  // If requested, and output format is not csv,
262  // calculate the sigma ranges
263  if (calc_sigma_ranges && output_format != "csv") {
264  for (auto &this_date : my_cal_date_list._dates) {
265  this_date.calculate_sigma_ranges();
266  }
267  }
268 
269  // If output format is set to json, export a json string
270  if (output_format == "json") {
271  std::cout << my_cal_date_list.to_json() << std::endl;
272  } else if (output_format == "csv") { // If output format is set to csv, export a csv string
273  std::cout << my_cal_date_list.to_csv() << std::endl;
274  } else {
275  cout << "Invalid output format!";
276  return EXIT_FAILURE;
277  }
278 
279  return EXIT_SUCCESS;
280 }
string to_csv()
void push_back(UncalDate date)
nlohmann::json json
Definition: cal_date.h:29
int main(int argc, char **argv)
Main function.
Definition: main.cpp:131
int import(string file)
Definition: cal_curve.cpp:15
Represents a list of uncalibrated dates.
vector< CalDate > _dates
Definition: cal_date_list.h:34
CalDateList calibrate(CalCurve &calcurve)
json csv_input_to_json(string &in)
Converts a csv input string to json.
Definition: main.cpp:74
int validate_numeric_string(string &a)
Method to validate that a string contains numbers only.
Definition: main.cpp:39
Represents a list of calibrated dates.
Definition: cal_date_list.h:27
Represents an uncalibrated date.
Definition: uncal_date.h:30
Represents the calibration curve.
Definition: cal_curve.h:32
int check_input_format(string &input_string)
Checks whether a string contains json or csv.
Definition: main.cpp:55