895 lines
31 KiB
C++
895 lines
31 KiB
C++
/***************************************************************************
|
|
|
|
msr2data.cpp
|
|
|
|
Author: Bastian M. Wojek / Andreas Suter
|
|
e-mail: andreas.suter@psi.ch
|
|
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* Copyright (C) 2009-2014 by Bastian M. Wojek / Andreas Suter *
|
|
* andreas.suter@psi.ch *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
***************************************************************************/
|
|
|
|
// note: msr2data is on purpose implemented in a way that shows string handling can be done solely
|
|
// using std::string, boost and related standard C++ features
|
|
// This implies, however, occasionally strange constructs when interoperating with PMusr-classes
|
|
// which mostly rely on ROOT's TString.
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "git-revision.h"
|
|
#include "PMsr2Data.h"
|
|
|
|
#include <algorithm>
|
|
#include <sstream>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <cstdlib>
|
|
#include <limits>
|
|
using namespace std;
|
|
|
|
|
|
#include <boost/algorithm/string/case_conv.hpp> // for to_lower() in std::string
|
|
using namespace boost::algorithm;
|
|
|
|
#include <boost/lexical_cast.hpp> // for atoi-replacement
|
|
// #include <boost/filesystem.hpp> // for a clean way to check if a file exists
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Checks if a string is an integer
|
|
*
|
|
* <p><b>return:</b>
|
|
* - true if s is a number string
|
|
* - false otherwise
|
|
*
|
|
* \param s string
|
|
*/
|
|
bool isNumber(const string &s)
|
|
{
|
|
unsigned int number;
|
|
try {
|
|
number = boost::lexical_cast<unsigned int>(s);
|
|
return true;
|
|
}
|
|
catch(boost::bad_lexical_cast &) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Sends the usage description to the standard output.
|
|
*/
|
|
void msr2data_syntax()
|
|
{
|
|
cout << endl << "usage 0: msr2data [--version] | [--help]";
|
|
cout << endl << "usage 1: msr2data <run> <extension> [-o<outputfile>] [new] [data] [[no]header] [nosummary] [global[+[!]]]";
|
|
cout << endl << " [fit [-k] [-t] | fit-<template>[!] [-k] [-t] | msr-<template>]";
|
|
cout << endl << "usage 2: msr2data <run1> <run2> <extension> [-o<outputfile>] [new] [data] [[no]header] [nosummary] [global[+[!]]]";
|
|
cout << endl << " [fit [-k] [-t] | fit-<template>[!] [-k] [-t] | msr-<template>]";
|
|
cout << endl << "usage 3: msr2data \\[<run1> <run2> ... <runN>\\] <extension> [-o<outputfile> ] [new] [data] [[no]header] [nosummary] [global[+[!]]]";
|
|
cout << endl << " [fit [-k] [-t] | fit-<template>[!] [-k] [-t] | msr-<template>]";
|
|
cout << endl << "usage 4: msr2data <runlist> <extension> [-o<outputfile>] [new] [data] [[no]header] [nosummary] [global[+[!]]]";
|
|
cout << endl << " [fit [-k] [-t] | fit-<template>[!] [-k] [-t] | msr-<template>]";
|
|
cout << endl;
|
|
cout << endl << " <run>, <run1>, <run2>, ... <runN> : run numbers";
|
|
cout << endl << " <extension> : msr-file extension, e.g. _tf_h13 for the file name 8472_tf_h13.msr";
|
|
cout << endl << " -o<outputfile> : specify the name of the DB or column-data output file; default: out.db/out.dat";
|
|
cout << endl << " if the option '-o none' is used, no output file will be written.";
|
|
cout << endl << " new : before writing a new output file, delete the contents of any existing file with the same name";
|
|
cout << endl << " data : instead of to a DB file the data are written to a simple column structure";
|
|
cout << endl << " header : force writing of the file header to the output file";
|
|
cout << endl << " noheader : no file header is written to the output file";
|
|
cout << endl << " If either none or both of the header options are given, the file header will be written";
|
|
cout << endl << " if a new file is created, but not if the output file exists already!";
|
|
cout << endl << " nosummary : no additional data from the run data file is written to the output file";
|
|
cout << endl << " fit : invoke musrfit to fit the specified runs";
|
|
cout << endl << " All msr input files are assumed to be present, none is newly generated!";
|
|
cout << endl << " fit-<template>! : generate msr files for the runs to be processed from the <template> run";
|
|
cout << endl << " and call musrfit for fitting these runs";
|
|
cout << endl << " fit-<template> : same as above, but the <template> run is only used for the first file creation---";
|
|
cout << endl << " the successive files are generated using the musrfit output from the preceding runs";
|
|
cout << endl << " msr-<template> : same as above without calling musrfit";
|
|
cout << endl << " In case any fitting option is present, this option is ignored!";
|
|
cout << endl << " -k : if fitting is used, pass the option --keep-mn2-output to musrfit";
|
|
cout << endl << " -t : if fitting is used, pass the option --title-from-data-file to musrfit";
|
|
cout << endl;
|
|
cout << endl << " global : switch on the global-fit mode";
|
|
cout << endl << " Within that mode all specified runs will be united in a single msr file!";
|
|
cout << endl << " The fit parameters can be either run specific or common to all runs.";
|
|
cout << endl << " For a complete description of this feature please refer to the manual.";
|
|
cout << endl;
|
|
cout << endl << " global+[!] : operate in the global-fit mode, however, in case a global input file is created";
|
|
cout << endl << " all specified runs are pre-analyzed first one by one using the given template.";
|
|
cout << endl << " For the generation of the global input file, the run-specific parameter values are taken";
|
|
cout << endl << " from this pre-analysis for each run---they are not just copied from the template.";
|
|
cout << endl << " The specification of '!' determines which fit mode (see above) is used for this pre-analysis.";
|
|
cout << endl;
|
|
cout << endl << " For further information please refer to";
|
|
cout << endl << " https://intranet.psi.ch/MUSR/Msr2Data";
|
|
cout << endl << " http://lmu.web.psi.ch/facilities/software/musrfit/user/intranet.psi.ch/MUSR/Msr2Data.html";
|
|
cout << endl << endl;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Cleaning up some used variables
|
|
*
|
|
* \param msr2dataHandler pointer to PMsr2Data object
|
|
* \param run_vec vector containing the run numbers
|
|
* \param arg vector containing the command line arguments
|
|
*
|
|
*/
|
|
void msr2data_cleanup(PMsr2Data *msr2dataHandler, vector<unsigned int> &run_vec, vector<string> &arg)
|
|
{
|
|
delete msr2dataHandler;
|
|
msr2dataHandler = 0;
|
|
run_vec.clear();
|
|
arg.clear();
|
|
return;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Cleaning up some used variables
|
|
*
|
|
* \param msr2dataHandler pointer to PMsr2Data object
|
|
* \param arg vector containing the command line arguments
|
|
*
|
|
*/
|
|
void msr2data_cleanup(PMsr2Data *msr2dataHandler, vector<string> &arg)
|
|
{
|
|
delete msr2dataHandler;
|
|
msr2dataHandler = 0;
|
|
arg.clear();
|
|
return;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Checks if only valid options appear in the argument list
|
|
*
|
|
* <p><b>return:</b>
|
|
* - empty string if everything is fine
|
|
* - first found wrong argument in case of an error
|
|
*
|
|
* \param arg list of arguments
|
|
*
|
|
*/
|
|
string msr2data_validArguments(const vector<string> &arg)
|
|
{
|
|
string word;
|
|
|
|
for (vector<string>::const_iterator iter(arg.begin()); iter != arg.end(); ++iter) {
|
|
if ( (!iter->compare("header")) || (!iter->compare("noheader")) || (!iter->compare("nosummary")) \
|
|
|| (!iter->substr(0,3).compare("fit")) || (!iter->compare("-k")) || (!iter->compare("-t")) \
|
|
|| (!iter->compare("data")) || (!iter->substr(0,4).compare("msr-")) || (!iter->compare("global")) \
|
|
|| (!iter->compare("global+")) || (!iter->compare("global+!")) || (!iter->compare("new")) )
|
|
word.clear();
|
|
else if (!iter->substr(0,2).compare("-o")) {
|
|
word.clear();
|
|
if (!iter->compare("-o")) {
|
|
if (++iter == arg.end())
|
|
break;
|
|
else
|
|
continue;
|
|
}
|
|
} else {
|
|
word = *iter;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return word;
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>filters out the output file name from the argument string
|
|
*
|
|
* <p><b>return:</b>
|
|
* - output file name if present in the argument list
|
|
* - otherwise 'out.db' (db==true), 'out.dat' (db==false)
|
|
*
|
|
* \param arg argument string list from the msr2data call
|
|
* \param db true if output file is a db-file
|
|
*/
|
|
string msr2data_outputfile(vector<string> &arg, bool db = true)
|
|
{
|
|
string outputFile;
|
|
if (db)
|
|
outputFile = "out.db";
|
|
else
|
|
outputFile = "out.dat";
|
|
|
|
vector<string>::iterator iterNext(arg.begin());
|
|
for (vector<string>::iterator iter(arg.begin()); iter != arg.end(); ++iter) {
|
|
iterNext = iter + 1;
|
|
if (!iter->substr(0,2).compare("-o")) {
|
|
if (!iter->compare("-o")) {
|
|
if ((iterNext != arg.end()) && (iterNext->compare("header")) && (iterNext->compare("noheader")) && (iterNext->compare("nosummary")) \
|
|
&& (iterNext->substr(0,3).compare("fit")) && (iterNext->compare("-k")) && (iterNext->compare("-t")) \
|
|
&& (iterNext->compare("data")) && (iterNext->substr(0,3).compare("msr")) && (iterNext->compare("global")) \
|
|
&& (iterNext->compare("global+")) && (iterNext->compare("global+!")) && (iterNext->compare("new"))) {
|
|
outputFile = *iterNext;
|
|
arg.erase(iterNext);
|
|
arg.erase(iter);
|
|
break;
|
|
} else {
|
|
cout << endl;
|
|
cout << ">> msr2data: **WARNING** You did not specify an output file! The default one (" << outputFile << ") will be used." << endl;
|
|
arg.erase(iter);
|
|
break;
|
|
}
|
|
} else {
|
|
outputFile = iter->substr(2);
|
|
arg.erase(iter);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return outputFile;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Checks if option string is present in the argument input list
|
|
*
|
|
* <p><b>return:</b>
|
|
* - true if option is <b>not</b> present
|
|
* - false otherwise
|
|
*
|
|
* \param arg list of arguments
|
|
* \param s option string
|
|
*/
|
|
bool msr2data_useOption(vector<string> &arg, const string &s)
|
|
{
|
|
bool option(true);
|
|
|
|
vector<string>::iterator iter;
|
|
iter = find(arg.begin(), arg.end(), s);
|
|
|
|
if (iter != arg.end()) {
|
|
option = false;
|
|
arg.erase(iter);
|
|
}
|
|
return option;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Filters out the template run number (if present) and check at the
|
|
* same time if only already existing msr-files shall be fitted (no template).
|
|
*
|
|
* <p><b>return:</b>
|
|
* - template runNo if everything is OK
|
|
* - -1 : tag: fit only, do not prepare input files
|
|
* - -2 : fatal error - more than one fit-<temp> options are specified
|
|
* - -3 : fit-<temp> option found, but <temp> is not a valid number
|
|
*
|
|
* \param arg list of arguments
|
|
* \param chainfit if true
|
|
*
|
|
*/
|
|
int msr2data_doFitting(vector<string> &arg, bool &chainfit)
|
|
{
|
|
int temp(0);
|
|
|
|
string s;
|
|
vector<string>::iterator iter(arg.begin());
|
|
while (iter != arg.end()) {
|
|
if (!iter->compare("fit")) { // fit found
|
|
if (temp) { // temp already found previously
|
|
return -2; // fatal error - another fit-<temp> option is specified
|
|
}
|
|
temp = -1; // fit only, do not prepare input files
|
|
chainfit = false;
|
|
iter = arg.erase(iter);
|
|
}
|
|
else if (!iter->substr(0,4).compare("fit-")) { // 'fit-' found
|
|
if (temp) {
|
|
return -2; // fatal error - another fit option is specified
|
|
}
|
|
s = iter->substr(4);
|
|
string::size_type loc = s.rfind('!');
|
|
if (loc != string::npos) {
|
|
chainfit = false;
|
|
s.erase(loc);
|
|
}
|
|
else
|
|
chainfit = true;
|
|
try {
|
|
temp = boost::lexical_cast<int>(s);
|
|
arg.erase(iter);
|
|
}
|
|
catch(boost::bad_lexical_cast &) {
|
|
return -3; // the specified template is no number
|
|
}
|
|
} else {
|
|
++iter;
|
|
}
|
|
}
|
|
|
|
return temp;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Filters out the template run number from which the new msr-files should be created.
|
|
*
|
|
* <b>return:</b>
|
|
* - template run number, or
|
|
* - -3 if the string after 'msr-' is not a number
|
|
*
|
|
* \param arg list of arguments
|
|
* \param inputOnly flag, if true create msr-files only (no fitting)
|
|
*/
|
|
int msr2data_doInputCreation(vector<string> &arg, bool &inputOnly)
|
|
{
|
|
int temp(0);
|
|
|
|
string s;
|
|
for (vector<string>::iterator iter(arg.begin()); iter != arg.end(); ++iter) {
|
|
if (!iter->substr(0,4).compare("msr-")) {
|
|
s = iter->substr(4);
|
|
try {
|
|
temp = boost::lexical_cast<int>(s);
|
|
arg.erase(iter);
|
|
}
|
|
catch(boost::bad_lexical_cast &) {
|
|
temp = -3; // the specified template is no number
|
|
}
|
|
inputOnly = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return temp;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>msr2data is used to generate msr-files based on template msr-files, automatically fit these new msr-files,
|
|
* collect fitting parameters, etc. For a detailed description see
|
|
* \htmlonly <a href="https://intranet.psi.ch/MUSR/Msr2Data">musr2data online help</a>
|
|
* \endhtmlonly
|
|
* \latexonly msr2data online help: \texttt{https://intranet.psi.ch/MUSR/Msr2Data}
|
|
* \endlatexonly
|
|
*
|
|
* \param argc number of arguments
|
|
* \param argv list of arguments
|
|
*/
|
|
int main(int argc, char *argv[])
|
|
{
|
|
// check if version dump is wanted
|
|
if (argc == 2) {
|
|
if (!strcmp(argv[1], "--help")) {
|
|
msr2data_syntax();
|
|
return 0;
|
|
} else if (!strcmp(argv[1], "--version")) {
|
|
#ifdef HAVE_CONFIG_H
|
|
cout << endl << "msr2data version: " << PACKAGE_VERSION << ", git-rev: " << GIT_REVISION << endl << endl;
|
|
#else
|
|
cout << endl << "msr2data git-rev: " << GIT_REVISION << endl << endl;
|
|
#endif
|
|
return 0;
|
|
} else {
|
|
msr2data_syntax();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// check the number of arguments
|
|
if (argc < 2) {
|
|
msr2data_syntax();
|
|
return 0;
|
|
}
|
|
|
|
// use a string-vector for the arguments to get rid of char* as far as possible...
|
|
vector<string> arg;
|
|
for (int i(1); i<argc; ++i) {
|
|
arg.push_back(argv[i]);
|
|
}
|
|
|
|
unsigned int runTAG;
|
|
vector<unsigned int> run_vec;
|
|
string run_list;
|
|
string msrExtension;
|
|
|
|
try {
|
|
if (arg[0].at(0) == '[') { // In case a list of runs is given by [...]
|
|
runTAG = 1;
|
|
|
|
unsigned int firstRunNumberInArg(0), lastRunNumberInArg(0);
|
|
unsigned int rightbracket(numeric_limits<unsigned int>::max());
|
|
|
|
if (!arg[0].compare("["))
|
|
firstRunNumberInArg = 1;
|
|
else
|
|
arg[0]=arg[0].substr(1);
|
|
|
|
for (unsigned int i(firstRunNumberInArg); i<arg.size(); ++i) {
|
|
string::size_type loc = arg[i].rfind(']');
|
|
if ( loc != string::npos ) {
|
|
rightbracket = i;
|
|
if (!arg[i].compare("]") && i > 0)
|
|
lastRunNumberInArg = i-1;
|
|
else {
|
|
arg[i]=arg[i].substr(0,loc);
|
|
lastRunNumberInArg = i;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (rightbracket == numeric_limits<unsigned int>::max()) {
|
|
cerr << endl;
|
|
cerr << ">> msr2data: **ERROR** You used the list specification without closing bracket (])! Quitting now." << endl;
|
|
return 0;
|
|
}
|
|
|
|
for (unsigned int i(firstRunNumberInArg); i<=lastRunNumberInArg; ++i)
|
|
run_vec.push_back(boost::lexical_cast<unsigned int>(arg[i]));
|
|
|
|
msrExtension = arg[rightbracket + 1];
|
|
|
|
vector<string>::iterator iter(arg.begin());
|
|
for (unsigned int i(0); i<rightbracket + 2; ++i) {
|
|
arg.erase(iter);
|
|
iter = arg.begin();
|
|
}
|
|
|
|
} else {
|
|
bool argOneIsNumber(isNumber(arg[0])), argTwoIsNumber(isNumber(arg[1]));
|
|
|
|
if (argOneIsNumber && argTwoIsNumber) { // the first two arguments are numbers: an interval of numbers is given
|
|
runTAG = 2;
|
|
|
|
if (arg.size() < 3) {
|
|
cerr << endl;
|
|
cerr << ">> msr2data: **ERROR** No msr-file extension specified! Quitting now..." << endl;
|
|
run_vec.clear();
|
|
arg.clear();
|
|
return 0;
|
|
}
|
|
|
|
run_vec.push_back(boost::lexical_cast<unsigned int>(arg[0]));
|
|
run_vec.push_back(boost::lexical_cast<unsigned int>(arg[1]));
|
|
|
|
msrExtension = arg[2];
|
|
|
|
vector<string>::iterator iter(arg.begin());
|
|
for (unsigned int i(0); i < 3; i++) {
|
|
arg.erase(iter);
|
|
iter = arg.begin();
|
|
}
|
|
} else if (argOneIsNumber && !argTwoIsNumber) { // only one run number is given
|
|
runTAG = 3;
|
|
run_vec.push_back(boost::lexical_cast<unsigned int>(arg[0]));
|
|
msrExtension = arg[1];
|
|
|
|
vector<string>::iterator iter(arg.begin());
|
|
for (unsigned int i(0); i < 2; i++) {
|
|
arg.erase(iter);
|
|
iter = arg.begin();
|
|
}
|
|
} else { // assume a runlist-file with "independent variables" is given
|
|
runTAG = 4;
|
|
run_list = arg[0];
|
|
msrExtension = arg[1];
|
|
|
|
vector<string>::iterator iter(arg.begin());
|
|
for (unsigned int i(0); i < 2; i++) {
|
|
arg.erase(iter);
|
|
iter = arg.begin();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(boost::bad_lexical_cast &) {
|
|
cerr << endl;
|
|
cerr << ">> msr2data: **ERROR** At least one given run number is out of range! Quitting..." << endl;
|
|
run_vec.clear();
|
|
arg.clear();
|
|
return -1;
|
|
}
|
|
|
|
// check the validity of the command line given command line arguments
|
|
string wrongArgument(msr2data_validArguments(arg));
|
|
if (!wrongArgument.empty()) {
|
|
cerr << endl;
|
|
cerr << ">> msr2data: **ERROR** Unknown argument: " << wrongArgument << ". Quitting..." << endl;
|
|
run_vec.clear();
|
|
arg.clear();
|
|
return -1;
|
|
}
|
|
|
|
// check if the output format is DB or data
|
|
bool db(msr2data_useOption(arg, "data"));
|
|
|
|
// check the arguments for the "-o" option and set the output filename
|
|
string outputFile(msr2data_outputfile(arg, db));
|
|
|
|
// introduce check, if no output should be generated - in that case we do not need msrfile and rundata handlers later
|
|
bool realOutput(true);
|
|
if (!to_lower_copy(outputFile).compare("none"))
|
|
realOutput = false;
|
|
|
|
// create the msr2data-object and set the run numbers according to the runTAG above
|
|
PMsr2Data *msr2dataHandler = new PMsr2Data(msrExtension);
|
|
|
|
int status;
|
|
|
|
switch(runTAG) {
|
|
case 1:
|
|
status = msr2dataHandler->SetRunNumbers(run_vec);
|
|
break;
|
|
case 2:
|
|
status = msr2dataHandler->SetRunNumbers(run_vec[0], run_vec[1]);
|
|
break;
|
|
case 3:
|
|
status = msr2dataHandler->SetRunNumbers(run_vec[0]);
|
|
break;
|
|
case 4:
|
|
status = msr2dataHandler->SetRunNumbers(run_list);
|
|
break;
|
|
default:
|
|
cerr << endl;
|
|
cerr << ">> msr2data: **ERROR** None of the possible run list specifications has been detected! Quitting now..." << endl;
|
|
msr2data_cleanup(msr2dataHandler, run_vec, arg);
|
|
return 0;
|
|
}
|
|
|
|
if (status == 1) {
|
|
cerr << endl;
|
|
cerr << ">> msr2data: **ERROR** The run numbers are out of range! Quitting..." << endl;
|
|
msr2data_cleanup(msr2dataHandler, run_vec, arg);
|
|
return status;
|
|
} else if (status == -1) {
|
|
msr2data_cleanup(msr2dataHandler, run_vec, arg);
|
|
return status;
|
|
}
|
|
|
|
run_vec.clear();
|
|
|
|
// check if fitting should be done and in case, which template run number to use
|
|
int temp(0);
|
|
bool chainfit(true), onlyInputCreation(false);
|
|
string musrfitOptions;
|
|
|
|
temp = msr2data_doFitting(arg, chainfit);
|
|
|
|
if (temp == -2) {
|
|
cerr << endl;
|
|
cerr << ">> msr2data: **ERROR** More than one fitting options are specified! Quitting..." << endl;
|
|
msr2data_cleanup(msr2dataHandler, arg);
|
|
return temp;
|
|
} else if (temp == -3) {
|
|
cerr << endl;
|
|
cerr << ">> msr2data: **ERROR** The given template has not a valid run number! Quitting..." << endl;
|
|
msr2data_cleanup(msr2dataHandler, arg);
|
|
return temp;
|
|
}
|
|
|
|
|
|
// check if any options should be passed to musrfit
|
|
if (temp) {
|
|
if (!msr2data_useOption(arg, "-k"))
|
|
musrfitOptions.append("-k ");
|
|
if (!msr2data_useOption(arg, "-t"))
|
|
musrfitOptions.append("-t ");
|
|
}
|
|
|
|
// if no fitting should be done, check if only the input files should be created
|
|
|
|
if(!temp) {
|
|
temp = msr2data_doInputCreation(arg, onlyInputCreation);
|
|
if (onlyInputCreation) {
|
|
// if only input files should be created, do not write data to an output file (no matter, what has been determined earlier)
|
|
realOutput = false;
|
|
outputFile = "none";
|
|
}
|
|
if (temp == -3) {
|
|
cerr << endl;
|
|
cerr << ">> msr2data: **ERROR** The given template has not a valid run number! Quitting..." << endl;
|
|
msr2data_cleanup(msr2dataHandler, arg);
|
|
return temp;
|
|
}
|
|
}
|
|
|
|
// check if msr2data should work in the global fit regime
|
|
bool setNormalMode(msr2data_useOption(arg, "global"));
|
|
unsigned int globalMode(0);
|
|
|
|
if (!msr2data_useOption(arg, "global+!")) {
|
|
setNormalMode = false;
|
|
globalMode = 1;
|
|
} else if (!msr2data_useOption(arg, "global+")) {
|
|
setNormalMode = false;
|
|
globalMode = 2;
|
|
}
|
|
|
|
// At this point it should be clear if any template for input-file generation is given or not.
|
|
// Therefore, the number of digits in the run number format is determined only here.
|
|
if(temp > 0) {
|
|
status = msr2dataHandler->DetermineRunNumberDigits(temp, setNormalMode);
|
|
} else {
|
|
status = msr2dataHandler->DetermineRunNumberDigits(msr2dataHandler->GetPresentRun(), setNormalMode);
|
|
}
|
|
|
|
if(status) {
|
|
msr2data_cleanup(msr2dataHandler, arg);
|
|
return status;
|
|
}
|
|
|
|
// Check if all given run numbers are covered by the formatting of the data file name
|
|
status = msr2dataHandler->CheckRunNumbersInRange();
|
|
if(status) {
|
|
cerr << endl;
|
|
cerr << ">> msr2data: **ERROR** At least one given run number is out of range! Quitting..." << endl;
|
|
msr2data_cleanup(msr2dataHandler, arg);
|
|
return status;
|
|
}
|
|
|
|
bool writeSummary(false);
|
|
unsigned int writeHeader(2);
|
|
// writeHeader: 0 - no header
|
|
// 1 - write header explicitly (even if the file is present already)
|
|
// 2 - write header automatically if a new file is created and do not if the data is appended to an existing file
|
|
|
|
fstream *fileOutput = 0;
|
|
if (realOutput) {
|
|
// check the arguments for the "header" and "noheader" options
|
|
if (!msr2data_useOption(arg, "header")) {
|
|
if (!msr2data_useOption(arg, "noheader")) {
|
|
writeHeader = 2;
|
|
} else {
|
|
writeHeader = 1;
|
|
}
|
|
} else if (!msr2data_useOption(arg, "noheader")) {
|
|
writeHeader = 0;
|
|
}
|
|
|
|
// check the arguments for the "nosummary" option
|
|
writeSummary = msr2data_useOption(arg, "nosummary");
|
|
|
|
// delete old db/data file if the "new" option is given
|
|
if (!msr2data_useOption(arg, "new")) {
|
|
fileOutput = new fstream;
|
|
fileOutput->open(outputFile.c_str(), ios::in);
|
|
if (fileOutput->is_open()) {
|
|
cout << endl << ">> msr2data: **INFO** Deleting output file " << outputFile << endl;
|
|
fileOutput->close();
|
|
fileOutput->open(outputFile.c_str(), ios::out | ios::trunc);
|
|
fileOutput->close();
|
|
} else {
|
|
cout << endl << ">> msr2data: **INFO** Ignoring the 'new' option since " << outputFile << " does not exist yet." << endl;
|
|
}
|
|
delete fileOutput;
|
|
fileOutput = 0;
|
|
if (writeHeader == 2) {
|
|
writeHeader = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// GLOBAL MODE
|
|
if (!setNormalMode) {
|
|
ostringstream strInfile;
|
|
strInfile << msr2dataHandler->GetPresentRun() << "+global" << msrExtension << ".msr";
|
|
|
|
// if fitting should be done, prepare a new input file
|
|
if (temp) {
|
|
if (temp > 0) { // if it is smaller no input file should be generated
|
|
bool success(msr2dataHandler->PrepareGlobalInputFile(temp, strInfile.str(), globalMode));
|
|
|
|
if (!success) {
|
|
cerr << endl << ">> msr2data: **ERROR** Input file generation has not been successful! Quitting..." << endl;
|
|
msr2data_cleanup(msr2dataHandler, arg);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// and do the fitting
|
|
if (!onlyInputCreation) {
|
|
// check if MUSRFITPATH is set, if not issue a warning
|
|
string path("");
|
|
bool pathSet(false);
|
|
char *pathPtr(getenv("MUSRFITPATH"));
|
|
if (pathPtr) {
|
|
path = boost::lexical_cast<string>(pathPtr);
|
|
if (!path.empty()) {
|
|
pathSet = true;
|
|
path.append("/");
|
|
}
|
|
}
|
|
if (!pathSet) {
|
|
cerr << endl << ">> msr2data: **WARNING** The MUSRFITPATH environment variable is not set!";
|
|
cerr << endl << ">> msr2data: **WARNING** Please set it or at least ensure that musrfit can be found on the PATH!" << endl;
|
|
}
|
|
ostringstream oss;
|
|
oss << path << "musrfit" << " " << strInfile.str() << " " << musrfitOptions;
|
|
cout << endl << ">> msr2data: **INFO** Calling " << oss.str() << endl;
|
|
system(oss.str().c_str());
|
|
}
|
|
}
|
|
|
|
if (realOutput) {
|
|
// read musrfit startup file
|
|
if (writeSummary) {
|
|
status = msr2dataHandler->ParseXmlStartupFile();
|
|
}
|
|
|
|
// Read msr file
|
|
status = msr2dataHandler->ReadMsrFile(strInfile.str());
|
|
if (status != PMUSR_SUCCESS) {
|
|
arg.clear();
|
|
return status;
|
|
}
|
|
|
|
// read data files
|
|
if (writeSummary)
|
|
status = msr2dataHandler->ReadRunDataFile();
|
|
|
|
unsigned int counter(0);
|
|
|
|
while (msr2dataHandler->GetPresentRun()) {
|
|
// write DB or dat file
|
|
status = msr2dataHandler->WriteOutput(outputFile, db, writeHeader, !setNormalMode, counter);
|
|
if (status == -1) {
|
|
msr2data_cleanup(msr2dataHandler, arg);
|
|
return status;
|
|
}
|
|
++counter;
|
|
}
|
|
}
|
|
} else { // NORMAL MODE - one msr-file for each run
|
|
|
|
// read musrfit startup file
|
|
if (writeSummary) {
|
|
status = msr2dataHandler->ParseXmlStartupFile();
|
|
}
|
|
|
|
// Processing the run list, do the fitting and write the data to the DB or data output file
|
|
bool firstrun(true);
|
|
unsigned int oldtemp(0); // should be accessed only when updated before...
|
|
ostringstream strInfile;
|
|
|
|
while (msr2dataHandler->GetPresentRun()) {
|
|
strInfile.clear();
|
|
strInfile.str("");
|
|
strInfile << msr2dataHandler->GetPresentRun() << msrExtension << ".msr";
|
|
|
|
// if fitting should be done, prepare a new input file
|
|
if (temp) {
|
|
if (temp > 0) {
|
|
bool success(true);
|
|
if (firstrun || !chainfit)
|
|
success = msr2dataHandler->PrepareNewInputFile(temp, false);
|
|
else
|
|
success = msr2dataHandler->PrepareNewInputFile(oldtemp, false);
|
|
if (firstrun)
|
|
firstrun = false;
|
|
oldtemp = msr2dataHandler->GetPresentRun();
|
|
|
|
if (!success) {
|
|
cerr << endl << ">> msr2data: **ERROR** Input file generation has not been successful! Quitting..." << endl;
|
|
msr2data_cleanup(msr2dataHandler, arg);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// and do the fitting
|
|
if (!onlyInputCreation) {
|
|
// check if MUSRFITPATH is set, if not issue a warning
|
|
string path("");
|
|
bool pathSet(false);
|
|
char *pathPtr(getenv("MUSRFITPATH"));
|
|
if (pathPtr) {
|
|
path = boost::lexical_cast<string>(pathPtr);
|
|
if (!path.empty()) {
|
|
pathSet = true;
|
|
path.append("/");
|
|
}
|
|
}
|
|
if (!pathSet) {
|
|
cerr << endl << ">> msr2data: **WARNING** The MUSRFITPATH environment variable is not set!";
|
|
cerr << endl << ">> msr2data: **WARNING** Please set it or at least ensure that musrfit can be found on the PATH!" << endl;
|
|
}
|
|
ostringstream oss;
|
|
oss << path << "musrfit" << " " << strInfile.str() << " " << musrfitOptions;
|
|
cout << endl << ">> msr2data: **INFO** Calling " << oss.str() << endl;
|
|
system(oss.str().c_str());
|
|
}
|
|
}
|
|
|
|
// read msr-file
|
|
if (realOutput) {
|
|
status = msr2dataHandler->ReadMsrFile(strInfile.str());
|
|
if (status != PMUSR_SUCCESS) {
|
|
// if the msr-file cannot be read, write no output but proceed to the next run
|
|
status = msr2dataHandler->WriteOutput("none", db, writeHeader);
|
|
if (status == -1) {
|
|
msr2data_cleanup(msr2dataHandler, arg);
|
|
return status;
|
|
} else {
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
// read data files
|
|
if (writeSummary)
|
|
status = msr2dataHandler->ReadRunDataFile();
|
|
|
|
// write DB or dat file
|
|
status = msr2dataHandler->WriteOutput(outputFile, db, writeHeader);
|
|
if (status == -1) {
|
|
msr2data_cleanup(msr2dataHandler, arg);
|
|
return status;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Make sure that the empty line at the end of the output file gets written
|
|
// This is needed to create a "valid db-file", however, we do it for all output files
|
|
// Unfortunately, this can be done in a coherent way only on that level
|
|
// Unfortunately, there are also problems with boost::filesystem::exists(outputFile)
|
|
// Therefore, first try to open the file for reading and if this works, write to it - not clean but it works
|
|
if(realOutput) {
|
|
fileOutput = new fstream;
|
|
fileOutput->open(outputFile.c_str(), ios::in);
|
|
if (fileOutput->is_open()) {
|
|
fileOutput->close();
|
|
fileOutput->open(outputFile.c_str(), ios::out | ios::app);
|
|
if (fileOutput->is_open()) {
|
|
*fileOutput << endl << endl;
|
|
fileOutput->close();
|
|
} else {
|
|
cerr << endl << ">> msr2data: **ERROR** The output file " << outputFile << " cannot be opened! Please check!";
|
|
cerr << endl;
|
|
}
|
|
} else {
|
|
cerr << endl << ">> msr2data: **WARNING** No output has been written to the file " << outputFile << "!";
|
|
cerr << endl << ">> msr2data: **WARNING** Please check the range of runs and the specified options!" << endl;
|
|
}
|
|
delete fileOutput;
|
|
fileOutput = 0;
|
|
}
|
|
|
|
if (!arg.empty()) {
|
|
cout << endl << ">> msr2data: **INFO** The following command line arguments have been specified but not been used: " << endl;
|
|
cout << ">> msr2data: **INFO**";
|
|
for (unsigned int i(0); i<arg.size(); ++i)
|
|
cout << " " << arg[i];
|
|
cout << endl;
|
|
}
|
|
|
|
msr2data_cleanup(msr2dataHandler, arg);
|
|
|
|
cout << endl << ">> msr2data: done ..." << endl;
|
|
|
|
return 1;
|
|
}
|