musrfit  1.9.2
msr2data.cpp
Go to the documentation of this file.
1 /***************************************************************************
2 
3  msr2data.cpp
4 
5  Author: Bastian M. Wojek / Andreas Suter
6  e-mail: andreas.suter@psi.ch
7 
8 ***************************************************************************/
9 
10 /***************************************************************************
11  * Copyright (C) 2009-2023 by Bastian M. Wojek / Andreas Suter *
12  * andreas.suter@psi.ch *
13  * *
14  * This program is free software; you can redistribute it and/or modify *
15  * it under the terms of the GNU General Public License as published by *
16  * the Free Software Foundation; either version 2 of the License, or *
17  * (at your option) any later version. *
18  * *
19  * This program is distributed in the hope that it will be useful, *
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22  * GNU General Public License for more details. *
23  * *
24  * You should have received a copy of the GNU General Public License *
25  * along with this program; if not, write to the *
26  * Free Software Foundation, Inc., *
27  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
28  ***************************************************************************/
29 
30 // note: msr2data is on purpose implemented in a way that shows string handling can be done solely
31 // using std::string, boost and related standard C++ features
32 // This implies, however, occasionally strange constructs when interoperating with PMusr-classes
33 // which mostly rely on ROOT's TString.
34 
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38 
39 #ifdef HAVE_GIT_REV_H
40 #include "git-revision.h"
41 #endif
42 
43 #include "PMusr.h"
44 #include "PMsr2Data.h"
45 
46 #include <algorithm>
47 #include <sstream>
48 #include <iostream>
49 #include <fstream>
50 #include <cstdlib>
51 #include <limits>
52 #include <string>
53 #include <memory>
54 
55 #include <boost/algorithm/string.hpp>
56 #include <boost/algorithm/string/case_conv.hpp> // for to_lower() in std::string
57 
58 #include <boost/lexical_cast.hpp> // for atoi-replacement
59 
60 //--------------------------------------------------------------------------
70 bool isNumber(const std::string &s)
71 {
72  unsigned int number(0);
73  try {
74  number = boost::lexical_cast<unsigned int>(s);
75  return true;
76  }
77  catch(boost::bad_lexical_cast &) {
78  return false;
79  }
80 }
81 
82 //--------------------------------------------------------------------------
87 {
88  std::cout << std::endl << "usage 0: msr2data [--version] | [--help]";
89  std::cout << std::endl << "usage 1: msr2data <run> <extension> options";
90  std::cout << std::endl << "usage 2: msr2data <run1> <run2> <extension> options";
91  std::cout << std::endl << "usage 3: msr2data \\[<runList>\\] <extension> options";
92  std::cout << std::endl << "usage 4: msr2data <runListFileName> <extension> options";
93  std::cout << std::endl;
94  std::cout << std::endl << " <runList> can be:";
95  std::cout << std::endl << " (i) <run0>, <run1>, <run2>, ... <runN> : run numbers, e.g. 123 124";
96  std::cout << std::endl << " (ii) <run0>-<runN> : a range, e.g. 123-125 -> 123 124 125";
97  std::cout << std::endl << " (iii) <run0>:<runN>:<step> : a sequence, e.g. 123:127:2 -> 123 125 127";
98  std::cout << std::endl << " <step> will give the step width and has to be a positive number!";
99  std::cout << std::endl << " a <runList> can also combine (i)-(iii), e.g. 123 128-130 133, etc.";
100  std::cout << std::endl << " <runListFileName> : an ASCII file containing a list of run numbers and optional";
101  std::cout << std::endl << " external parameters is passed to msr2data. For details see";
102  std::cout << std::endl << " the online documentation: http://lmu.web.psi.ch/musrfit/user/MUSR/Msr2Data.html";
103  std::cout << std::endl << " <extension> : msr-file extension, e.g. _tf_h13 for the file name 8472_tf_h13.msr";
104  std::cout << std::endl;
105  std::cout << std::endl << "options:";
106  std::cout << std::endl << " -o<outputfile> : specify the name of the DB or column-data output file; default: out.db/out.dat";
107  std::cout << std::endl << " if the option '-o none' is used, no output file will be written.";
108  std::cout << std::endl << " new : before writing a new output file, delete the contents of any existing file with the same name";
109  std::cout << std::endl << " data : instead of to a DB file the data are written to a simple column structure";
110  std::cout << std::endl << " header : force writing of the file header to the output file";
111  std::cout << std::endl << " noheader : no file header is written to the output file";
112  std::cout << std::endl << " If either none or both of the header options are given, the file header will be written";
113  std::cout << std::endl << " if a new file is created, but not if the output file exists already!";
114  std::cout << std::endl << " nosummary : no additional data from the run data file is written to the output file";
115  std::cout << std::endl << " paramList <param> : option used to select the parameters which shall be exported.";
116  std::cout << std::endl << " <param> is a list of parameter numbers to be exported. Allowed lists are:";
117  std::cout << std::endl << " 1-16 will export parameters 1 to 16. 1 3 5 will export parameters 1 3 5.";
118  std::cout << std::endl << " A combination of both is possible, e.g. 1-16 19 31 62, and so on.";
119  std::cout << std::endl << " fit : invoke musrfit to fit the specified runs";
120  std::cout << std::endl << " All msr input files are assumed to be present, none is newly generated!";
121  std::cout << std::endl << " fit-<template>! : generate msr files for the runs to be processed from the <template> run";
122  std::cout << std::endl << " and call musrfit for fitting these runs";
123  std::cout << std::endl << " fit-<template> : same as above, but the <template> run is only used for the first file creation---";
124  std::cout << std::endl << " the successive files are generated using the musrfit output from the preceding runs";
125  std::cout << std::endl << " msr-<template> : same as above without calling musrfit";
126  std::cout << std::endl << " In case any fitting option is present, this option is ignored!";
127  std::cout << std::endl << " -k, --keep-mn2-output : if fitting is used, pass the option --keep-mn2-output to musrfit";
128  std::cout << std::endl << " -t, --title-from-data-file : if fitting is used, pass the option --title-from-data-file to musrfit";
129  std::cout << std::endl << " -e, --estimateN0: estimate N0 for single histogram fits.";
130  std::cout << std::endl << " -p, --per-run-block-chisq: will per run block chisq to the msr-file.";
131  std::cout << std::endl;
132  std::cout << std::endl << " global : switch on the global-fit mode";
133  std::cout << std::endl << " Within that mode all specified runs will be united in a single msr file!";
134  std::cout << std::endl << " The fit parameters can be either run specific or common to all runs.";
135  std::cout << std::endl << " For a complete description of this feature please refer to the manual.";
136  std::cout << std::endl;
137  std::cout << std::endl << " global+[!] : operate in the global-fit mode, however, in case a global input file is created";
138  std::cout << std::endl << " all specified runs are pre-analyzed first one by one using the given template.";
139  std::cout << std::endl << " For the generation of the global input file, the run-specific parameter values are taken";
140  std::cout << std::endl << " from this pre-analysis for each run---they are not just copied from the template.";
141  std::cout << std::endl << " The specification of '!' determines which fit mode (see above) is used for this pre-analysis.";
142  std::cout << std::endl;
143  std::cout << std::endl << " Typical examples:";
144  std::cout << std::endl;
145  std::cout << std::endl << " msr2data 2047 2050 _tf_histo fit-2046";
146  std::cout << std::endl << " will use 2046_tf_histo.msr as templete, and subsequently generating 2047_tf_histo.msr until";
147  std::cout << std::endl << " 2050_tf_histo.msr and fit them.";
148  std::cout << std::endl;
149  std::cout << std::endl << " msr2data 2047 2050 _tf_histo msr-2046";
150  std::cout << std::endl << " will use 2046_tf_histo.msr as templete, and subsequently generating 2047_tf_histo.msr until";
151  std::cout << std::endl << " 2050_tf_histo.msr, but NO fitting will be done.";
152  std::cout << std::endl;
153  std::cout << std::endl << " msr2data 2046 2050 _tf_histo -o fitParam.db";
154  std::cout << std::endl << " will collect the fit parameters from runs 2046-2050 (msr-files 2046_tf_histo.msr etc.) and";
155  std::cout << std::endl << " write them to the file fitParam.db (DB-format).";
156  std::cout << std::endl;
157  std::cout << std::endl << " msr2data [2047:2053:2 2056] _tf_histo fit-2045";
158  std::cout << std::endl << " will use 2045_tf_histo.msr as templete, and subsequently generating msr-files from the run-list:";
159  std::cout << std::endl << " 2047 2049 2051 2053 2056 (2047_tf_histo.msr etc.) and fit them.";
160  std::cout << std::endl;
161  std::cout << std::endl << " msr2data 2046 2058 _tf_histo paramList 1-12 data -o fitParam.dat";
162  std::cout << std::endl << " will export the parameters number 1 trough 12 in a column like fashion of the runs 2046 to 2058,";
163  std::cout << std::endl << " collected form the msr-files 2046_tf_histo.msr and so on.";
164  std::cout << std::endl;
165  std::cout << std::endl << " For further information please refer to";
166  std::cout << std::endl << " http://lmu.web.psi.ch/musrfit/user/html/msr2data.html#msr2data";
167  std::cout << std::endl << std::endl;
168 }
169 
170 //--------------------------------------------------------------------------
181 std::string msr2data_validArguments(const std::vector<std::string> &arg)
182 {
183  std::string word;
184 
185  for (std::vector<std::string>::const_iterator iter(arg.begin()); iter != arg.end(); ++iter) {
186  if ( (!iter->compare("header")) || (!iter->compare("noheader")) || (!iter->compare("nosummary")) \
187  || (!iter->substr(0,3).compare("fit")) || (!iter->compare("-k")) || (!iter->compare("--keep-mn2-output")) \
188  || (!iter->compare("-t")) || (!iter->compare("--title-from-data-file")) \
189  || (!iter->compare("-e")) || (!iter->compare("--estimateN0")) \
190  || (!iter->compare("-p")) || (!iter->compare("--per-run-block-chisq")) \
191  || (!iter->compare("data")) || (!iter->substr(0,4).compare("msr-")) || (!iter->compare("global")) \
192  || (!iter->compare("global+")) || (!iter->compare("global+!")) || (!iter->compare("new")) \
193  || !iter->compare("paramList") )
194  word.clear();
195  else if (!iter->substr(0,2).compare("-o")) {
196  word.clear();
197  if (!iter->compare("-o")) {
198  if (++iter == arg.end())
199  break;
200  else
201  continue;
202  }
203  } else {
204  word = *iter;
205  break;
206  }
207  }
208 
209  return word;
210 
211 }
212 
213 //--------------------------------------------------------------------------
224 std::string msr2data_outputfile(std::vector<std::string> &arg, bool db = true)
225 {
226  std::string outputFile;
227  if (db)
228  outputFile = "out.db";
229  else
230  outputFile = "out.dat";
231 
232  std::vector<std::string>::iterator iterNext(arg.begin());
233  for (std::vector<std::string>::iterator iter(arg.begin()); iter != arg.end(); ++iter) {
234  iterNext = iter + 1;
235  if (!iter->substr(0,2).compare("-o")) {
236  if (!iter->compare("-o")) {
237  if ((iterNext != arg.end()) && (iterNext->compare("header")) && (iterNext->compare("noheader")) && (iterNext->compare("nosummary")) \
238  && (iterNext->substr(0,3).compare("fit")) && (iterNext->compare("-k")) && (iterNext->compare("-t")) \
239  && (iterNext->compare("-e")) && (iterNext->compare("-p")) \
240  && (iterNext->compare("data")) && (iterNext->substr(0,3).compare("msr")) && (iterNext->compare("global")) \
241  && (iterNext->compare("global+")) && (iterNext->compare("global+!")) && (iterNext->compare("new"))) {
242  outputFile = *iterNext;
243  arg.erase(iterNext);
244  arg.erase(iter);
245  break;
246  } else {
247  std::cout << std::endl;
248  std::cout << ">> msr2data: **WARNING** You did not specify an output file! The default one (" << outputFile << ") will be used." << std::endl;
249  arg.erase(iter);
250  break;
251  }
252  } else {
253  outputFile = iter->substr(2);
254  arg.erase(iter);
255  break;
256  }
257  }
258  }
259 
260  return outputFile;
261 }
262 
263 //--------------------------------------------------------------------------
274 bool msr2data_useOption(std::vector<std::string> &arg, const std::string &s)
275 {
276  bool option(true);
277 
278  std::vector<std::string>::iterator iter;
279  iter = find(arg.begin(), arg.end(), s);
280 
281  if (iter != arg.end()) {
282  option = false;
283  arg.erase(iter);
284  }
285  return option;
286 }
287 
288 //--------------------------------------------------------------------------
303 int msr2data_doFitting(std::vector<std::string> &arg, bool &chainfit)
304 {
305  int temp(0);
306 
307  std::string s;
308  std::vector<std::string>::iterator iter(arg.begin());
309  while (iter != arg.end()) {
310  if (!iter->compare("fit")) { // fit found
311  if (temp) { // temp already found previously
312  return -2; // fatal error - another fit-<temp> option is specified
313  }
314  temp = -1; // fit only, do not prepare input files
315  chainfit = false;
316  iter = arg.erase(iter);
317  }
318  else if (!iter->substr(0,4).compare("fit-")) { // 'fit-' found
319  if (temp) {
320  return -2; // fatal error - another fit option is specified
321  }
322  s = iter->substr(4);
323  std::string::size_type loc = s.rfind('!');
324  if (loc != std::string::npos) {
325  chainfit = false;
326  s.erase(loc);
327  }
328  else
329  chainfit = true;
330  try {
331  temp = boost::lexical_cast<int>(s);
332  arg.erase(iter);
333  }
334  catch(boost::bad_lexical_cast &) {
335  return -3; // the specified template is no number
336  }
337  } else {
338  ++iter;
339  }
340  }
341 
342  return temp;
343 }
344 
345 //--------------------------------------------------------------------------
356 int msr2data_doInputCreation(std::vector<std::string> &arg, bool &inputOnly)
357 {
358  int temp(0);
359 
360  std::string s;
361  for (std::vector<std::string>::iterator iter(arg.begin()); iter != arg.end(); ++iter) {
362  if (!iter->substr(0,4).compare("msr-")) {
363  s = iter->substr(4);
364  try {
365  temp = boost::lexical_cast<int>(s);
366  arg.erase(iter);
367  }
368  catch(boost::bad_lexical_cast &) {
369  temp = -3; // the specified template is no number
370  }
371  inputOnly = true;
372  break;
373  }
374  }
375 
376  return temp;
377 }
378 
379 //--------------------------------------------------------------------------
384 int msr2data_paramList(std::vector<std::string> &arg, std::vector<unsigned int> &paramList)
385 {
386  paramList.clear(); // make sure paramList is empty
387 
388  unsigned int idx=0;
389  // check if paramList tag is present
390  for (unsigned int i=0; i<arg.size(); i++) {
391  if (!arg[i].compare("paramList")) {
392  idx = i+1;
393  break;
394  }
395  }
396 
397  if (idx == 0) { // paramList tag NOT present
398  return 0;
399  }
400 
401  // make sure there are parameter list elements to follow
402  if (idx == arg.size()) {
403  std::cerr << std::endl << "**ERROR** found paramList without any arguments!" << std::endl;
404  msr2data_syntax();
405  return -1;
406  }
407 
408  // paramList tag present and further elements present: collect them
409  std::vector<std::string> str;
410  unsigned int idx_end=0;
411  size_t pos=std::string::npos;
412  for (unsigned int i=idx; i<arg.size(); i++) {
413  pos = arg[i].find("-");
414  if (pos == 0) { // likely something like -o, -k, etc.
415  idx_end = i;
416  break;
417  } else if (pos != std::string::npos) { // looks like a parameter list like n0-n1
418  boost::split(str, arg[i], boost::is_any_of("-"));
419  if (str.size() != 2) { // something is wrong, since the structure n0-n1 is expected
420  std::cerr << std::endl << "**ERROR** found token " << arg[i] << " in paramList command which cannot be handled." << std::endl;
421  msr2data_syntax();
422  return -1;
423  }
424  if (!str[0].compare("fit") || !str[0].compare("msr")) {
425  idx_end = i;
426  break;
427  }
428  if (!isNumber(str[0]) || !isNumber(str[1])) {
429  std::cerr << std::endl << "**ERROR** found token " << arg[i] << " in paramList command which cannot be handled." << std::endl;
430  msr2data_syntax();
431  return -1;
432  }
433  unsigned int start=boost::lexical_cast<unsigned int>(str[0]);
434  unsigned int end=boost::lexical_cast<unsigned int>(str[1]);
435  for (unsigned int j=start; j<=end; j++)
436  paramList.push_back(j);
437  } else if (isNumber(arg[i])) { // a single number
438  paramList.push_back(boost::lexical_cast<unsigned int>(arg[i]));
439  } else { // likely the next argument not related to paramList
440  idx_end = i;
441  break;
442  }
443  }
444  if (idx_end == 0)
445  idx_end = arg.size();
446 
447  // remove all the paramList arguments for arg
448  arg.erase(arg.begin()+idx-1, arg.begin()+idx_end);
449 
450  // go through the parameter list and make sure the values are unique
451  for (unsigned int i=0; i<paramList.size(); i++) {
452  for (unsigned int j=i+1; j<paramList.size(); j++) {
453  if (paramList[i] == paramList[j]) {
454  std::cerr << std::endl << "**ERROR** the parameter list numbers have to be unique. Found " << paramList[i] << " at least 2 times." << std::endl;
455  msr2data_syntax();
456  return -1;
457  }
458  }
459  }
460 
461  return paramList.size();
462 }
463 
464 //--------------------------------------------------------------------------
476 int main(int argc, char *argv[])
477 {
478  // check if version dump is wanted
479  if (argc == 2) {
480  if (!strcmp(argv[1], "--help")) {
481  msr2data_syntax();
482  return 0;
483  } else if (!strcmp(argv[1], "--version")) {
484 #ifdef HAVE_CONFIG_H
485 #ifdef HAVE_GIT_REV_H
486  std::cout << std::endl << "msr2data version: " << PACKAGE_VERSION << ", git-branch: " << GIT_BRANCH << ", git-rev: " << GIT_CURRENT_SHA1 << " (" << BUILD_TYPE << "), ROOT version: " << ROOT_VERSION_USED << std::endl << std::endl;
487 #else
488  std::cout << std::endl << "msr2data version: " << PACKAGE_VERSION << " (" << BUILD_TYPE << "), ROOT version: " << ROOT_VERSION_USED << std::endl << std::endl;
489 #endif
490 #else
491 #ifdef HAVE_GIT_REV_H
492  std::cout << std::endl << "msr2data git-branch: " << GIT_BRANCH << ", git-rev: " << GIT_CURRENT_SHA1 << std::endl << std::endl;
493 #else
494  std::cout << std::endl << "msr2data version: unknown." << std::endl << std::endl;
495 #endif
496 #endif
497  return 0;
498  } else {
499  msr2data_syntax();
500  return 0;
501  }
502  }
503 
504  // check the number of arguments
505  if (argc < 2) {
506  msr2data_syntax();
507  return 0;
508  }
509 
510  // use a string-vector for the arguments to get rid of char* as far as possible...
511  std::vector<std::string> arg;
512  for (int i(1); i<argc; ++i) {
513  arg.push_back(argv[i]);
514  }
515 
516  unsigned int runTAG;
517  std::vector<unsigned int> run_vec;
518  std::string run_list;
519  std::string msrExtension;
520  std::vector<unsigned int> param_vec;
521 
522  try {
523  if (arg[0].at(0) == '[') { // In case a list of runs is given by [...]
524  runTAG = 1;
525 
526  unsigned int firstRunNumberInArg(0), lastRunNumberInArg(0);
527  unsigned int rightbracket(std::numeric_limits<unsigned int>::max());
528 
529  if (!arg[0].compare("["))
530  firstRunNumberInArg = 1;
531  else
532  arg[0]=arg[0].substr(1);
533 
534  for (unsigned int i(firstRunNumberInArg); i<arg.size(); ++i) {
535  std::string::size_type loc = arg[i].rfind(']');
536  if ( loc != std::string::npos ) {
537  rightbracket = i;
538  if (!arg[i].compare("]") && i > 0)
539  lastRunNumberInArg = i-1;
540  else {
541  arg[i]=arg[i].substr(0,loc);
542  lastRunNumberInArg = i;
543  }
544  break;
545  }
546  }
547  if (rightbracket == std::numeric_limits<unsigned int>::max()) {
548  std::cerr << std::endl;
549  std::cerr << ">> msr2data: **ERROR** You used the list specification without closing bracket (])! Quitting now." << std::endl;
550  return 0;
551  }
552 
553  // generate run_list string
554  for (unsigned int i(firstRunNumberInArg); i<=lastRunNumberInArg; ++i) {
555  run_list += arg[i] + " ";
556  }
557  // parse run_list string
558  std::unique_ptr<PStringNumberList> nl = std::make_unique<PStringNumberList>(run_list);
559  std::string errorMsg("");
560  if (!nl->Parse(errorMsg)) {
561  std::cerr << std::endl;
562  std::cerr << ">> msr2data: " << errorMsg << " - Quitting now." << std::endl;
563  return 0;
564  }
565  // get run list vector
566  run_vec = nl->GetList();
567 
568  msrExtension = arg[rightbracket + 1];
569 
570  std::vector<std::string>::iterator iter(arg.begin());
571  for (unsigned int i(0); i<rightbracket + 2; ++i) {
572  arg.erase(iter);
573  iter = arg.begin();
574  }
575 
576  } else {
577  bool argOneIsNumber(isNumber(arg[0])), argTwoIsNumber(isNumber(arg[1]));
578 
579  if (argOneIsNumber && argTwoIsNumber) { // the first two arguments are numbers: an interval of numbers is given
580  runTAG = 2;
581 
582  if (arg.size() < 3) {
583  std::cerr << std::endl;
584  std::cerr << ">> msr2data: **ERROR** No msr-file extension specified! Quitting now..." << std::endl;
585  run_vec.clear();
586  arg.clear();
587  return 0;
588  }
589 
590  run_vec.push_back(boost::lexical_cast<unsigned int>(arg[0]));
591  run_vec.push_back(boost::lexical_cast<unsigned int>(arg[1]));
592 
593  msrExtension = arg[2];
594 
595  std::vector<std::string>::iterator iter(arg.begin());
596  for (unsigned int i(0); i < 3; i++) {
597  arg.erase(iter);
598  iter = arg.begin();
599  }
600  } else if (argOneIsNumber && !argTwoIsNumber) { // only one run number is given
601  runTAG = 3;
602  run_vec.push_back(boost::lexical_cast<unsigned int>(arg[0]));
603  msrExtension = arg[1];
604 
605  std::vector<std::string>::iterator iter(arg.begin());
606  for (unsigned int i(0); i < 2; i++) {
607  arg.erase(iter);
608  iter = arg.begin();
609  }
610  } else { // assume a runlist-file with "independent variables" is given
611  runTAG = 4;
612  run_list = arg[0];
613  msrExtension = arg[1];
614 
615  std::vector<std::string>::iterator iter(arg.begin());
616  for (unsigned int i(0); i < 2; i++) {
617  arg.erase(iter);
618  iter = arg.begin();
619  }
620  }
621  }
622  }
623  catch(boost::bad_lexical_cast &) {
624  std::cerr << std::endl;
625  std::cerr << ">> msr2data: **ERROR** At least one given run number is out of range! Quitting..." << std::endl;
626  run_vec.clear();
627  arg.clear();
628  return -1;
629  }
630 
631  // check if parameter list is given
632  int noParamList(msr2data_paramList(arg, param_vec));
633  if (noParamList == -1) {
634  arg.clear();
635  return -1;
636  }
637 
638  // check the validity of the command line given command line arguments
639  std::string wrongArgument(msr2data_validArguments(arg));
640  if (!wrongArgument.empty()) {
641  std::cerr << std::endl;
642  std::cerr << ">> msr2data: **ERROR** Unknown argument: " << wrongArgument << ". Quitting..." << std::endl;
643  run_vec.clear();
644  arg.clear();
645  return -1;
646  }
647 
648  // check if the output format is DB or data
649  bool db(msr2data_useOption(arg, "data"));
650 
651  // check the arguments for the "-o" option and set the output filename
652  std::string outputFile(msr2data_outputfile(arg, db));
653 
654  // introduce check, if no output should be generated - in that case we do not need msrfile and rundata handlers later
655  bool realOutput(true);
656  if (!boost::algorithm::to_lower_copy(outputFile).compare("none"))
657  realOutput = false;
658 
659  // create the msr2data-object and set the run numbers according to the runTAG above
660  std::unique_ptr<PMsr2Data> msr2dataHandler = std::make_unique<PMsr2Data>(msrExtension);
661 
662  int status;
663 
664  switch(runTAG) {
665  case 1:
666  status = msr2dataHandler->SetRunNumbers(run_vec);
667  break;
668  case 2:
669  status = msr2dataHandler->SetRunNumbers(run_vec[0], run_vec[1]);
670  break;
671  case 3:
672  status = msr2dataHandler->SetRunNumbers(run_vec[0]);
673  break;
674  case 4:
675  status = msr2dataHandler->SetRunNumbers(run_list);
676  break;
677  default:
678  std::cerr << std::endl;
679  std::cerr << ">> msr2data: **ERROR** None of the possible run list specifications has been detected! Quitting now..." << std::endl;
680  return 0;
681  }
682 
683  if (status == 1) {
684  std::cerr << std::endl;
685  std::cerr << ">> msr2data: **ERROR** The run numbers are out of range! Quitting..." << std::endl;
686  return status;
687  } else if (status == -1) {
688  return status;
689  }
690 
691  run_vec.clear();
692 
693  // check if fitting should be done and in case, which template run number to use
694  int temp(0);
695  bool chainfit(true), onlyInputCreation(false);
696  std::string musrfitOptions;
697 
698  temp = msr2data_doFitting(arg, chainfit);
699 
700  if (temp == -2) {
701  std::cerr << std::endl;
702  std::cerr << ">> msr2data: **ERROR** More than one fitting options are specified! Quitting..." << std::endl;
703  return temp;
704  } else if (temp == -3) {
705  std::cerr << std::endl;
706  std::cerr << ">> msr2data: **ERROR** The given template has not a valid run number! Quitting..." << std::endl;
707  return temp;
708  }
709 
710 
711  // check if any options should be passed to musrfit
712  if (temp) {
713  if (!msr2data_useOption(arg, "-k") || !msr2data_useOption(arg, "--keep-mn2-output"))
714  musrfitOptions.append("-k ");
715  if (!msr2data_useOption(arg, "-t") || !msr2data_useOption(arg, "--title-from-data-file"))
716  musrfitOptions.append("-t ");
717  if (!msr2data_useOption(arg, "-e") || !msr2data_useOption(arg, "--estimateN0"))
718  musrfitOptions.append("-e ");
719  if (!msr2data_useOption(arg, "-p") || !msr2data_useOption(arg, "--per-run-block-chisq"))
720  musrfitOptions.append("-p ");
721  }
722 
723  // if no fitting should be done, check if only the input files should be created
724  if (!temp) {
725  temp = msr2data_doInputCreation(arg, onlyInputCreation);
726  if (onlyInputCreation) {
727  // if only input files should be created, do not write data to an output file (no matter, what has been determined earlier)
728  realOutput = false;
729  outputFile = "none";
730  }
731  if (temp == -3) {
732  std::cerr << std::endl;
733  std::cerr << ">> msr2data: **ERROR** The given template has not a valid run number! Quitting..." << std::endl;
734  return temp;
735  }
736  }
737 
738  // check if msr2data should work in the global fit regime
739  bool setNormalMode(msr2data_useOption(arg, "global"));
740  unsigned int globalMode(0);
741 
742  if (!msr2data_useOption(arg, "global+!")) {
743  setNormalMode = false;
744  globalMode = 1;
745  } else if (!msr2data_useOption(arg, "global+")) {
746  setNormalMode = false;
747  globalMode = 2;
748  }
749 
750  // At this point it should be clear if any template for input-file generation is given or not.
751  // Therefore, the number of digits in the run number format is determined only here.
752  if (temp > 0) {
753  status = msr2dataHandler->DetermineRunNumberDigits(temp, setNormalMode);
754  } else {
755  status = msr2dataHandler->DetermineRunNumberDigits(msr2dataHandler->GetPresentRun(), setNormalMode);
756  }
757 
758  if (status) {
759  return status;
760  }
761 
762  // Check if all given run numbers are covered by the formatting of the data file name
763  status = msr2dataHandler->CheckRunNumbersInRange();
764  if(status) {
765  std::cerr << std::endl;
766  std::cerr << ">> msr2data: **ERROR** At least one given run number is out of range! Quitting..." << std::endl;
767  return status;
768  }
769 
770  bool writeSummary(false);
771  unsigned int writeHeader(2);
772  // writeHeader: 0 - no header
773  // 1 - write header explicitly (even if the file is present already)
774  // 2 - write header automatically if a new file is created and do not if the data is appended to an existing file
775 
776  std::unique_ptr<std::fstream> fileOutput;
777  if (realOutput) {
778  // check the arguments for the "header" and "noheader" options
779  if (!msr2data_useOption(arg, "header")) {
780  if (!msr2data_useOption(arg, "noheader")) {
781  writeHeader = 2;
782  } else {
783  writeHeader = 1;
784  }
785  } else if (!msr2data_useOption(arg, "noheader")) {
786  writeHeader = 0;
787  }
788 
789  // check the arguments for the "nosummary" option
790  writeSummary = msr2data_useOption(arg, "nosummary");
791 
792  // delete old db/data file if the "new" option is given
793  if (!msr2data_useOption(arg, "new")) {
794  fileOutput = std::make_unique<std::fstream>();
795  fileOutput->open(outputFile.c_str(), std::ios::in);
796  if (fileOutput->is_open()) {
797  std::cout << std::endl << ">> msr2data: **INFO** Deleting output file " << outputFile << std::endl;
798  fileOutput->close();
799  fileOutput->open(outputFile.c_str(), std::ios::out | std::ios::trunc);
800  fileOutput->close();
801  } else {
802  std::cout << std::endl << ">> msr2data: **INFO** Ignoring the 'new' option since " << outputFile << " does not exist yet." << std::endl;
803  }
804  if (writeHeader == 2) {
805  writeHeader = 1;
806  }
807  }
808  }
809 
810  // GLOBAL MODE
811  if (!setNormalMode) {
812  std::ostringstream strInfile;
813  strInfile << msr2dataHandler->GetPresentRun() << "+global" << msrExtension << ".msr";
814 
815  // if fitting should be done, prepare a new input file
816  if (temp) {
817  if (temp > 0) { // if it is smaller no input file should be generated
818  bool success(msr2dataHandler->PrepareGlobalInputFile(temp, strInfile.str(), globalMode));
819 
820  if (!success) {
821  std::cerr << std::endl << ">> msr2data: **ERROR** Input file generation has not been successful! Quitting..." << std::endl;
822  return -1;
823  }
824  }
825 
826  // and do the fitting
827  if (!onlyInputCreation) {
828  // check if MUSRFITPATH is set, if not issue a warning
829  std::string path("");
830  bool pathSet(false);
831  char *pathPtr(getenv("MUSRFITPATH"));
832  if (pathPtr) {
833  path = boost::lexical_cast<std::string>(pathPtr);
834  if (!path.empty()) {
835  pathSet = true;
836  path.append("/");
837  }
838  }
839  if (!pathSet) {
840  std::cerr << std::endl << ">> msr2data: **WARNING** The MUSRFITPATH environment variable is not set!";
841  std::cerr << std::endl << ">> msr2data: **WARNING** Please set it or at least ensure that musrfit can be found on the PATH!" << std::endl;
842  }
843  std::ostringstream oss;
844  oss << path << "musrfit" << " " << strInfile.str() << " " << musrfitOptions;
845  std::cout << std::endl << ">> msr2data: **INFO** Calling " << oss.str() << std::endl;
846  if (system(oss.str().c_str()) == -1) {
847  std::cerr << "**ERROR** cmd: " << oss.str().c_str() << " failed." << std::endl;
848  }
849  }
850  }
851 
852  if (realOutput) {
853  // read musrfit startup file
854  if (writeSummary) {
855  status = msr2dataHandler->ParseXmlStartupFile();
856  }
857 
858  // Read msr file
859  status = msr2dataHandler->ReadMsrFile(strInfile.str());
860  if (status != PMUSR_SUCCESS) {
861  arg.clear();
862  return status;
863  }
864 
865  // read data files
866  if (writeSummary)
867  status = msr2dataHandler->ReadRunDataFile();
868 
869  unsigned int counter(0);
870 
871  while (msr2dataHandler->GetPresentRun()) {
872  // write DB or dat file
873  status = msr2dataHandler->WriteOutput(outputFile, param_vec, db, writeHeader, !setNormalMode, counter);
874  if (status == -1) {
875  return status;
876  }
877  ++counter;
878  }
879  }
880  } else { // NORMAL MODE - one msr-file for each run
881 
882  // read musrfit startup file
883  if (writeSummary) {
884  status = msr2dataHandler->ParseXmlStartupFile();
885  }
886 
887  // Processing the run list, do the fitting and write the data to the DB or data output file
888  bool firstrun(true);
889  unsigned int oldtemp(0); // should be accessed only when updated before...
890  std::ostringstream strInfile;
891 
892  while (msr2dataHandler->GetPresentRun()) {
893  strInfile.clear();
894  strInfile.str("");
895  strInfile << msr2dataHandler->GetPresentRun() << msrExtension << ".msr";
896 
897  // if fitting should be done, prepare a new input file
898  if (temp) {
899  if (temp > 0) {
900  bool success(true);
901  if (firstrun || !chainfit)
902  success = msr2dataHandler->PrepareNewInputFile(temp, false);
903  else
904  success = msr2dataHandler->PrepareNewInputFile(oldtemp, false);
905  if (firstrun)
906  firstrun = false;
907  oldtemp = msr2dataHandler->GetPresentRun();
908 
909  if (!success) {
910  std::cerr << std::endl << ">> msr2data: **ERROR** Input file generation has not been successful! Quitting..." << std::endl;
911  return -1;
912  }
913  }
914 
915  // and do the fitting
916  if (!onlyInputCreation) {
917  // check if MUSRFITPATH is set, if not issue a warning
918  std::string path("");
919  bool pathSet(false);
920  char *pathPtr(getenv("MUSRFITPATH"));
921  if (pathPtr) {
922  path = boost::lexical_cast<std::string>(pathPtr);
923  if (!path.empty()) {
924  pathSet = true;
925  path.append("/");
926  }
927  }
928  if (!pathSet) {
929  std::cerr << std::endl << ">> msr2data: **WARNING** The MUSRFITPATH environment variable is not set!";
930  std::cerr << std::endl << ">> msr2data: **WARNING** Please set it or at least ensure that musrfit can be found on the PATH!" << std::endl;
931  }
932  std::ostringstream oss;
933  oss << path << "musrfit" << " " << strInfile.str() << " " << musrfitOptions;
934  std::cout << std::endl << ">> msr2data: **INFO** Calling " << oss.str() << std::endl;
935  if (system(oss.str().c_str()) == -1) {
936  std::cerr << "**ERROR** cmd: " << oss.str().c_str() << " failed." << std::endl;
937  }
938  }
939  }
940 
941  // read msr-file
942  if (realOutput) {
943  status = msr2dataHandler->ReadMsrFile(strInfile.str());
944  if (status != PMUSR_SUCCESS) {
945  // if the msr-file cannot be read, write no output but proceed to the next run
946  status = msr2dataHandler->WriteOutput("none", param_vec, db, writeHeader);
947  if (status == -1) {
948  return status;
949  } else {
950  continue;
951  }
952  }
953  }
954 
955  // read data files
956  if (writeSummary)
957  status = msr2dataHandler->ReadRunDataFile();
958 
959  // write DB or dat file
960  status = msr2dataHandler->WriteOutput(outputFile, param_vec, db, writeHeader);
961  if (status == -1) {
962  return status;
963  }
964  }
965  }
966 
967  // Make sure that the empty line at the end of the output file gets written
968  // This is needed to create a "valid db-file", however, we do it for all output files
969  // Unfortunately, this can be done in a coherent way only on that level
970  // Unfortunately, there are also problems with boost::filesystem::exists(outputFile)
971  // Therefore, first try to open the file for reading and if this works, write to it - not clean but it works
972  if (realOutput) {
973  fileOutput = std::make_unique<std::fstream>();
974  fileOutput->open(outputFile.c_str(), std::ios::in);
975  if (fileOutput->is_open()) {
976  fileOutput->close();
977  fileOutput->open(outputFile.c_str(), std::ios::out | std::ios::app);
978  if (fileOutput->is_open()) {
979  *fileOutput << std::endl << std::endl;
980  fileOutput->close();
981  } else {
982  std::cerr << std::endl << ">> msr2data: **ERROR** The output file " << outputFile << " cannot be opened! Please check!";
983  std::cerr << std::endl;
984  }
985  } else {
986  std::cerr << std::endl << ">> msr2data: **WARNING** No output has been written to the file " << outputFile << "!";
987  std::cerr << std::endl << ">> msr2data: **WARNING** Please check the range of runs and the specified options!" << std::endl;
988  }
989  }
990 
991  if (!arg.empty()) {
992  std::cout << std::endl << ">> msr2data: **INFO** The following command line arguments have been specified but not been used: " << std::endl;
993  std::cout << ">> msr2data: **INFO**";
994  for (unsigned int i(0); i<arg.size(); ++i)
995  std::cout << " " << arg[i];
996  std::cout << std::endl;
997  }
998 
999  std::cout << std::endl << ">> msr2data: done ..." << std::endl;
1000 
1001  return 1;
1002 }
int msr2data_doInputCreation(std::vector< std::string > &arg, bool &inputOnly)
Definition: msr2data.cpp:356
int main(int argc, char *argv[])
Definition: any2many.cpp:154
std::string msr2data_validArguments(const std::vector< std::string > &arg)
Definition: msr2data.cpp:181
std::string msr2data_outputfile(std::vector< std::string > &arg, bool db=true)
Definition: msr2data.cpp:224
int msr2data_paramList(std::vector< std::string > &arg, std::vector< unsigned int > &paramList)
Definition: msr2data.cpp:384
bool msr2data_useOption(std::vector< std::string > &arg, const std::string &s)
Definition: msr2data.cpp:274
void msr2data_syntax()
Definition: msr2data.cpp:86
int msr2data_doFitting(std::vector< std::string > &arg, bool &chainfit)
Definition: msr2data.cpp:303
#define PMUSR_SUCCESS
Definition: PMusr.h:44
return status
bool isNumber(const std::string &s)
Definition: msr2data.cpp:70