musrfit/src/classes/PMsrHandler.cpp

5793 lines
202 KiB
C++

/***************************************************************************
PMsrHandler.cpp
Author: Andreas Suter
e-mail: andreas.suter@psi.ch
***************************************************************************/
/***************************************************************************
* Copyright (C) 2007-2014 by 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. *
***************************************************************************/
#include <math.h>
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
#include <TString.h>
#include <TObjArray.h>
#include <TObjString.h>
#include <TDatime.h>
#include "PMusr.h"
#include "PMsrHandler.h"
//--------------------------------------------------------------------------
// Constructor
//--------------------------------------------------------------------------
/**
* <p>Constructor
*
* \param fileName name of a msr-file.
*/
PMsrHandler::PMsrHandler(const Char_t *fileName, PStartupOptions *startupOptions, const Bool_t fourierOnly) :
fFourierOnly(fourierOnly), fStartupOptions(startupOptions), fFileName(fileName)
{
// init variables
fMsrBlockCounter = 0;
fTitle = "";
fCopyStatisticsBlock = false;
fStatistic.fValid = false;
fStatistic.fChisq = true;
fStatistic.fMin = -1.0;
fStatistic.fNdf = 0;
fStatistic.fMinExpected = 0.0;
fStatistic.fMinExpectedPerHisto.clear();
fStatistic.fNdfPerHisto.clear();
fFuncHandler = 0;
// check if the file name given is a path-file-name, and if yes, split it into path and file name.
if (fFileName.Contains("/")) {
Int_t idx = -1;
while (fFileName.Index("/", idx+1) != -1) {
idx = fFileName.Index("/", idx+1);
}
fMsrFileDirectoryPath = fFileName;
fMsrFileDirectoryPath.Remove(idx+1);
} else {
fMsrFileDirectoryPath = "./";
}
}
//--------------------------------------------------------------------------
// Destructor
//--------------------------------------------------------------------------
/**
* <p>Destructor
*/
PMsrHandler::~PMsrHandler()
{
fParam.clear();
fTheory.clear();
fFunctions.clear();
fRuns.clear();
fCommands.clear();
fPlots.clear();
fStatistic.fStatLines.clear();
fStatistic.fMinExpectedPerHisto.clear();
fStatistic.fNdfPerHisto.clear();
fParamInUse.clear();
if (fFuncHandler) {
delete fFuncHandler;
fFuncHandler = 0;
}
}
//--------------------------------------------------------------------------
// ReadMsrFile (public)
//--------------------------------------------------------------------------
/**
* <p>Reads and parses a msr-file.
*
* <p><b>return:</b>
* - PMUSR_SUCCESS if everything is OK
* - line number if an error in the MSR file was encountered which cannot be handled.
*/
Int_t PMsrHandler::ReadMsrFile()
{
ifstream f;
string str;
TString line;
Int_t line_no = 0;
Int_t result = PMUSR_SUCCESS;
PMsrLineStructure current;
PMsrLines fit_parameter;
PMsrLines theory;
PMsrLines functions;
PMsrLines global;
PMsrLines run;
PMsrLines commands;
PMsrLines fourier;
PMsrLines plot;
PMsrLines statistic;
// init stuff
InitFourierParameterStructure(fFourier);
// open msr-file
f.open(fFileName.Data(), iostream::in);
if (!f.is_open()) {
return PMUSR_MSR_FILE_NOT_FOUND;
}
fMsrBlockCounter = -1; // no msr block
// read msr-file
while (!f.eof()) {
// read a line
getline(f, str);
line = str.c_str();
line_no++;
current.fLineNo = line_no;
current.fLine = line;
if (line.BeginsWith("#") || line.IsWhitespace()) { // if the line is a comment/empty go to the next one
continue;
}
if (!line.IsWhitespace()) { // if not an empty line, handle it
// check for a msr block
if (line_no == 1) { // title
fTitle = line;
} else if (line.BeginsWith("FITPARAMETER")) { // FITPARAMETER block tag
fMsrBlockCounter = MSR_TAG_FITPARAMETER;
} else if (line.BeginsWith("THEORY")) { // THEORY block tag
fMsrBlockCounter = MSR_TAG_THEORY;
theory.push_back(current);
} else if (line.BeginsWith("FUNCTIONS")) { // FUNCTIONS block tag
fMsrBlockCounter = MSR_TAG_FUNCTIONS;
functions.push_back(current);
} else if (line.BeginsWith("GLOBAL")) { // GLOBAL block tag
fMsrBlockCounter = MSR_TAG_GLOBAL;
global.push_back(current);
} else if (line.BeginsWith("RUN")) { // RUN block tag
fMsrBlockCounter = MSR_TAG_RUN;
run.push_back(current);
} else if (line.BeginsWith("COMMANDS")) { // COMMANDS block tag
fMsrBlockCounter = MSR_TAG_COMMANDS;
commands.push_back(current);
} else if (line.BeginsWith("FOURIER")) { // FOURIER block tag
fMsrBlockCounter = MSR_TAG_FOURIER;
fourier.push_back(current);
} else if (line.BeginsWith("PLOT")) { // PLOT block tag
fMsrBlockCounter = MSR_TAG_PLOT;
plot.push_back(current);
} else if (line.BeginsWith("STATISTIC")) { // STATISTIC block tag
fMsrBlockCounter = MSR_TAG_STATISTIC;
statistic.push_back(current);
} else { // the read line is some real stuff
switch (fMsrBlockCounter) {
case MSR_TAG_FITPARAMETER: // FITPARAMETER block
fit_parameter.push_back(current);
break;
case MSR_TAG_THEORY: // THEORY block
theory.push_back(current);
break;
case MSR_TAG_FUNCTIONS: // FUNCTIONS block
functions.push_back(current);
break;
case MSR_TAG_GLOBAL: // GLOBAL block
global.push_back(current);
break;
case MSR_TAG_RUN: // RUN block
run.push_back(current);
break;
case MSR_TAG_COMMANDS: // COMMANDS block
commands.push_back(current);
break;
case MSR_TAG_FOURIER: // FOURIER block
fourier.push_back(current);
break;
case MSR_TAG_PLOT: // PLOT block
plot.push_back(current);
break;
case MSR_TAG_STATISTIC: // STATISTIC block
statistic.push_back(current);
break;
default:
break;
}
}
}
}
// close msr-file
f.close();
// execute handler of the various blocks
if (!HandleFitParameterEntry(fit_parameter))
result = PMUSR_MSR_SYNTAX_ERROR;
if (result == PMUSR_SUCCESS)
if (!HandleTheoryEntry(theory))
result = PMUSR_MSR_SYNTAX_ERROR;
if (result == PMUSR_SUCCESS)
if (!HandleFunctionsEntry(functions))
result = PMUSR_MSR_SYNTAX_ERROR;
if (result == PMUSR_SUCCESS)
if (!HandleGlobalEntry(global))
result = PMUSR_MSR_SYNTAX_ERROR;
if (result == PMUSR_SUCCESS)
if (!HandleRunEntry(run))
result = PMUSR_MSR_SYNTAX_ERROR;
if (result == PMUSR_SUCCESS)
if (!HandleCommandsEntry(commands))
result = PMUSR_MSR_SYNTAX_ERROR;
if (result == PMUSR_SUCCESS)
if (!HandleFourierEntry(fourier))
result = PMUSR_MSR_SYNTAX_ERROR;
if (result == PMUSR_SUCCESS)
if (!HandlePlotEntry(plot))
result = PMUSR_MSR_SYNTAX_ERROR;
if (result == PMUSR_SUCCESS)
if (!HandleStatisticEntry(statistic))
result = PMUSR_MSR_SYNTAX_ERROR;
// check if chisq or max.log likelihood
fStatistic.fChisq = true;
for (UInt_t i=0; i<fCommands.size(); i++) {
if (fCommands[i].fLine.Contains("MAX_LIKELIHOOD"))
fStatistic.fChisq = false; // max.log likelihood
}
// fill parameter-in-use vector
if ((result == PMUSR_SUCCESS) && !fFourierOnly)
FillParameterInUse(theory, functions, run);
// check that each run fulfills the minimum requirements
if (result == PMUSR_SUCCESS)
if (!CheckRunBlockIntegrity())
result = PMUSR_MSR_SYNTAX_ERROR;
// check that parameter names are unique
if ((result == PMUSR_SUCCESS) && !fFourierOnly) {
UInt_t parX, parY;
if (!CheckUniquenessOfParamNames(parX, parY)) {
cerr << endl << ">> PMsrHandler::ReadMsrFile: **SEVERE ERROR** parameter name " << fParam[parX].fName.Data() << " is identical for parameter no " << fParam[parX].fNo << " and " << fParam[parY].fNo << "!";
cerr << endl << ">> Needs to be fixed first!";
cerr << endl;
result = PMUSR_MSR_SYNTAX_ERROR;
}
}
// check that if maps are present in the theory- and/or function-block,
// that there are really present in the run block
if ((result == PMUSR_SUCCESS) && !fFourierOnly)
if (!CheckMaps())
result = PMUSR_MSR_SYNTAX_ERROR;
// check that if functions are present in the theory- and/or run-block, that they
// are really present in the function block
if (result == PMUSR_SUCCESS)
if (!CheckFuncs())
result = PMUSR_MSR_SYNTAX_ERROR;
// check that if histogram grouping is present that it makes any sense
if (result == PMUSR_SUCCESS)
if (!CheckHistoGrouping())
result = PMUSR_MSR_SYNTAX_ERROR;
// check that if addrun is present that the given parameter make any sense
if (result == PMUSR_SUCCESS)
if (!CheckAddRunParameters())
result = PMUSR_MSR_SYNTAX_ERROR;
if (result == PMUSR_SUCCESS) {
CheckMaxLikelihood(); // check if the user wants to use max likelihood with asymmetry/non-muSR fit (which is not implemented)
CheckLegacyLifetimecorrection(); // check if lifetimecorrection is found in RUN blocks, if yes transfer it to PLOT blocks
}
// clean up
fit_parameter.clear();
theory.clear();
functions.clear();
global.clear();
run.clear();
commands.clear();
fourier.clear();
plot.clear();
statistic.clear();
return result;
}
//--------------------------------------------------------------------------
// WriteMsrLogFile (public)
//--------------------------------------------------------------------------
/**
* <p>Writes a mlog-file.
*
* <p><b>return:</b>
* - PMUSR_SUCCESS everything is OK
* - PMUSR_MSR_LOG_FILE_WRITE_ERROR msr-/mlog-file couldn't be opened
* - PMUSR_MSR_SYNTAX_ERROR a syntax error has been encountered
*
* \param messages if true some additional messages concerning the statistic block are written.
* When using musrt0, messages will be set to false.
*/
Int_t PMsrHandler::WriteMsrLogFile(const Bool_t messages)
{
const UInt_t prec = 6; // default output precision for float/doubles
UInt_t neededPrec = 0;
UInt_t neededWidth = 9;
Int_t tag, lineNo = 0, number;
Int_t runNo = -1, addRunNo = 0;
Int_t plotNo = -1;
string line;
TString logFileName, str, sstr, *pstr;
TObjArray *tokens = 0;
TObjString *ostr = 0;
Bool_t found = false;
Bool_t statisticBlockFound = false;
Bool_t partialStatisticBlockFound = true;
PBoolVector t0TagMissing; // needed for proper musrt0 handling
for (UInt_t i=0; i<fRuns.size(); i++) {
t0TagMissing.push_back(true);
}
vector<PBoolVector> addt0TagMissing; // needed for proper musrt0 handling
PBoolVector bvec;
for (UInt_t i=0; i<fRuns.size(); i++) {
bvec.clear();
for (UInt_t j=0; j<fRuns[i].GetAddT0BinEntries(); j++)
bvec.push_back(true);
addt0TagMissing.push_back(bvec);
}
PBoolVector backgroundTagMissing; // needed for proper musrt0 handling
for (UInt_t i=0; i<fRuns.size(); i++) {
backgroundTagMissing.push_back(true);
}
PBoolVector dataTagMissing; // needed for proper musrt0 handling
for (UInt_t i=0; i<fRuns.size(); i++) {
dataTagMissing.push_back(true);
}
// add some counters needed in connection to addruns
Int_t addT0Counter = 0;
Int_t addT0GlobalCounter = 0;
ifstream fin;
ofstream fout;
// check msr-file for any missing tags first
// open msr-file for reading
fin.open(fFileName.Data(), iostream::in);
if (!fin.is_open()) {
return PMUSR_MSR_LOG_FILE_WRITE_ERROR;
}
while (!fin.eof()) {
// read a line
getline(fin, line);
str = line.c_str();
if (str.BeginsWith("RUN")) {
runNo++;
continue;
}
if (runNo == -1)
continue;
if (str.BeginsWith("t0"))
t0TagMissing[runNo] = false;
else if (str.BeginsWith("background"))
backgroundTagMissing[runNo] = false;
else if (str.BeginsWith("data"))
dataTagMissing[runNo] = false;
}
fin.close();
// construct log file name
// first find the last '.' in the filename
Int_t idx = -1;
while (fFileName.Index(".", idx+1) != -1) {
idx = fFileName.Index(".", idx+1);
}
if (idx == -1)
return PMUSR_MSR_SYNTAX_ERROR;
// remove extension
logFileName = fFileName;
logFileName.Remove(idx+1);
logFileName += "mlog";
// open msr-file for reading
fin.open(fFileName.Data(), iostream::in);
if (!fin.is_open()) {
return PMUSR_MSR_LOG_FILE_WRITE_ERROR;
}
// open mlog-file for writing
fout.open(logFileName.Data(), iostream::out);
if (!fout.is_open()) {
return PMUSR_MSR_LOG_FILE_WRITE_ERROR;
}
tag = MSR_TAG_TITLE;
lineNo = 0;
runNo = -1;
// read msr-file
while (!fin.eof()) {
// read a line
getline(fin, line);
str = line.c_str();
lineNo++;
// check for tag
if (str.BeginsWith("FITPARAMETER")) { // FITPARAMETER block tag
tag = MSR_TAG_FITPARAMETER;
} else if (str.BeginsWith("THEORY")) { // THEORY block tag
tag = MSR_TAG_THEORY;
fout << str.Data() << endl;
continue;
} else if (str.BeginsWith("FUNCTIONS")) { // FUNCTIONS block tag
tag = MSR_TAG_FUNCTIONS;
fout << str.Data() << endl;
continue;
} else if (str.BeginsWith("GLOBAL")) { // GLOBAL block tag
tag = MSR_TAG_GLOBAL;
fout << str.Data() << endl;
continue;
} else if (str.BeginsWith("RUN")) { // RUN block tag
tag = MSR_TAG_RUN;
runNo++;
addT0Counter = 0; // reset counter
} else if (str.BeginsWith("COMMANDS")) { // COMMANDS block tag
tag = MSR_TAG_COMMANDS;
fout << str.Data() << endl;
continue;
} else if (str.BeginsWith("FOURIER")) { // FOURIER block tag
tag = MSR_TAG_FOURIER;
fout << str.Data() << endl;
continue;
} else if (str.BeginsWith("PLOT")) { // PLOT block tag
tag = MSR_TAG_PLOT;
plotNo++;
} else if (str.BeginsWith("STATISTIC")) { // STATISTIC block tag
tag = MSR_TAG_STATISTIC;
}
// handle blocks
switch (tag) {
case MSR_TAG_TITLE:
if (lineNo == 1)
fout << fTitle.Data() << endl;
else
fout << str.Data() << endl;
break;
case MSR_TAG_FITPARAMETER:
tokens = str.Tokenize(" \t");
if (tokens->GetEntries() == 0) { // not a parameter line
fout << str.Data() << endl;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(0));
sstr = ostr->GetString();
if (sstr.IsDigit()) { // parameter
number = sstr.Atoi();
number--;
// make sure number makes sense
assert ((number >= 0) && (number < (Int_t)fParam.size()));
// parameter no
fout.width(9);
fout << right << fParam[number].fNo;
fout << " ";
// parameter name
fout.width(11);
fout << left << fParam[number].fName.Data();
fout << " ";
// value of the parameter
if (fParam[number].fStep == 0.0) // if fixed parameter take all significant digits
neededPrec = LastSignificant(fParam[number].fValue);
else // step/neg.error given hence they will limited the output precission of the value
neededPrec = NeededPrecision(fParam[number].fStep)+1;
if ((fParam[number].fStep != 0.0) && fParam[number].fPosErrorPresent && (NeededPrecision(fParam[number].fPosError)+1 > neededPrec))
neededPrec = NeededPrecision(fParam[number].fPosError)+1;
if (neededPrec < 6)
neededWidth = 9;
else
neededWidth = neededPrec + 3;
fout.width(neededWidth);
fout.setf(ios::fixed, ios::floatfield);
fout.precision(neededPrec);
fout << left << fParam[number].fValue;
fout << " ";
// value of step/error/neg.error
fout.width(11);
fout.setf(ios::fixed);
if (fParam[number].fStep == 0.0)
neededPrec = 0;
fout.precision(neededPrec);
fout << left << fParam[number].fStep;
fout << " ";
fout.width(11);
fout.setf(ios::fixed);
fout.precision(neededPrec);
if ((fParam[number].fNoOfParams == 5) || (fParam[number].fNoOfParams == 7)) // pos. error given
if (fParam[number].fPosErrorPresent && (fParam[number].fStep != 0)) // pos error is a number
fout << left << fParam[number].fPosError;
else // pos error is a none
fout << left << "none";
else // no pos. error
fout << left << "none";
fout << " ";
fout.unsetf(ios::floatfield);
// boundaries
if (fParam[number].fNoOfParams > 5) {
fout.width(7);
fout.precision(prec);
if (fParam[number].fLowerBoundaryPresent)
fout << left << fParam[number].fLowerBoundary;
else
fout << left << "none";
fout << " ";
fout.width(7);
fout.precision(prec);
if (fParam[number].fUpperBoundaryPresent)
fout << left << fParam[number].fUpperBoundary;
else
fout << left << "none";
fout << " ";
}
fout << endl;
} else { // not a parameter, hence just copy it
fout << str.Data() << endl;
}
// clean up tokens
delete tokens;
}
break;
case MSR_TAG_THEORY:
found = false;
for (UInt_t i=0; i<fTheory.size(); i++) {
if (fTheory[i].fLineNo == lineNo) {
fout << fTheory[i].fLine.Data() << endl;
found = true;
}
}
if (!found) {
fout << str.Data() << endl;
}
break;
case MSR_TAG_FUNCTIONS:
sstr = str;
sstr.Remove(TString::kLeading, ' ');
if (str.BeginsWith("fun")) {
if (FilterNumber(sstr, "fun", 0, number)) {
idx = GetFuncIndex(number); // get index of the function number
sstr = fFuncHandler->GetFuncString(idx);
sstr.ToLower();
fout << sstr.Data() << endl;
}
} else {
fout << str.Data() << endl;
}
break;
case MSR_TAG_GLOBAL:
sstr = str;
if (sstr.BeginsWith("fittype")) {
fout.width(16);
switch (fGlobal.GetFitType()) {
case MSR_FITTYPE_SINGLE_HISTO:
fout << left << "fittype" << MSR_FITTYPE_SINGLE_HISTO << " (single histogram fit)" << endl;
break;
case MSR_FITTYPE_ASYM:
fout << left << "fittype" << MSR_FITTYPE_ASYM << " (asymmetry fit)" << endl ;
break;
case MSR_FITTYPE_MU_MINUS:
fout << left << "fittype" << MSR_FITTYPE_MU_MINUS << " (mu minus fit)" << endl ;
break;
case MSR_FITTYPE_NON_MUSR:
fout << left << "fittype" << MSR_FITTYPE_NON_MUSR << " (non muSR fit)" << endl ;
break;
default:
break;
}
} else if (sstr.BeginsWith("data")) {
fout.width(16);
fout << left << "data";
for (UInt_t j=0; j<4; j++) {
if (fGlobal.GetDataRange(j) > 0) {
fout.width(8);
fout << left << fGlobal.GetDataRange(j);
}
}
fout << endl;
} else if (sstr.BeginsWith("t0")) {
fout.width(16);
fout << left << "t0";
for (UInt_t j=0; j<fGlobal.GetT0BinSize(); j++) {
fout.width(8);
fout.precision(1);
fout.setf(ios::fixed,ios::floatfield);
fout << left << fGlobal.GetT0Bin(j);
}
fout << endl;
} else if (sstr.BeginsWith("addt0")) {
fout.width(16);
fout << left << "addt0";
for (Int_t j=0; j<fGlobal.GetAddT0BinSize(addT0GlobalCounter); j++) {
fout.width(8);
fout.precision(1);
fout.setf(ios::fixed,ios::floatfield);
fout << left << fGlobal.GetAddT0Bin(addT0GlobalCounter, j);
}
fout << endl;
addT0GlobalCounter++;
} else if (sstr.BeginsWith("fit")) {
fout.width(16);
fout << left << "fit";
if (fGlobal.IsFitRangeInBin()) { // fit range given in bins
fout << "fgb";
if (fGlobal.GetFitRangeOffset(0) > 0)
fout << "+" << fGlobal.GetFitRangeOffset(0);
fout << " lgb";
if (fGlobal.GetFitRangeOffset(1) > 0)
fout << "-" << fGlobal.GetFitRangeOffset(1);
neededPrec = LastSignificant(fGlobal.GetFitRange(0));
if (LastSignificant(fGlobal.GetFitRange(1)) > neededPrec)
neededPrec = LastSignificant(fGlobal.GetFitRange(1));
fout.precision(neededPrec);
fout << " # in time: " << fGlobal.GetFitRange(0) << ".." << fGlobal.GetFitRange(1) << " (usec)";
} else { // fit range given in time
for (UInt_t j=0; j<2; j++) {
if (fGlobal.GetFitRange(j) == -1)
break;
neededWidth = 7;
neededPrec = LastSignificant(fGlobal.GetFitRange(j));
fout.width(neededWidth);
fout.precision(neededPrec);
fout << left << fixed << fGlobal.GetFitRange(j);
if (j==0)
fout << " ";
}
}
fout << endl;
} else if (sstr.BeginsWith("packing")) {
fout.width(16);
fout << left << "packing";
fout << fGlobal.GetPacking() << endl;
} else {
fout << str.Data() << endl;
}
break;
case MSR_TAG_RUN:
sstr = str;
sstr.Remove(TString::kLeading, ' ');
if (sstr.BeginsWith("RUN")) {
addRunNo = 0; // reset counter
fout << "RUN " << fRuns[runNo].GetRunName()->Data() << " ";
pstr = fRuns[runNo].GetBeamline();
if (pstr == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrLogFile: **ERROR** Couldn't obtain beamline data." << endl;
assert(0);
}
pstr->ToUpper();
fout << pstr->Data() << " ";
pstr = fRuns[runNo].GetInstitute();
if (pstr == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrLogFile: **ERROR** Couldn't obtain institute data." << endl;
assert(0);
}
pstr->ToUpper();
fout << pstr->Data() << " ";
pstr = fRuns[runNo].GetFileFormat();
if (pstr == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrLogFile: **ERROR** Couldn't obtain file format data." << endl;
assert(0);
}
pstr->ToUpper();
fout << pstr->Data() << " (name beamline institute data-file-format)" << endl;
} else if (sstr.BeginsWith("ADDRUN")) {
addRunNo++;
fout << "ADDRUN " << fRuns[runNo].GetRunName(addRunNo)->Data() << " ";
pstr = fRuns[runNo].GetBeamline(addRunNo);
if (pstr == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrLogFile: **ERROR** Couldn't obtain beamline data (addrun)." << endl;
assert(0);
}
pstr->ToUpper();
fout << pstr->Data() << " ";
pstr = fRuns[runNo].GetInstitute(addRunNo);
if (pstr == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrLogFile: **ERROR** Couldn't obtain institute data (addrun)." << endl;
assert(0);
}
pstr->ToUpper();
fout << pstr->Data() << " ";
pstr = fRuns[runNo].GetFileFormat(addRunNo);
if (pstr == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrLogFile: **ERROR** Couldn't obtain file format data (addrun)." << endl;
assert(0);
}
pstr->ToUpper();
fout << pstr->Data() << " (name beamline institute data-file-format)" << endl;
} else if (sstr.BeginsWith("fittype")) {
fout.width(16);
switch (fRuns[runNo].GetFitType()) {
case MSR_FITTYPE_SINGLE_HISTO:
fout << left << "fittype" << MSR_FITTYPE_SINGLE_HISTO << " (single histogram fit)" << endl;
break;
case MSR_FITTYPE_ASYM:
fout << left << "fittype" << MSR_FITTYPE_ASYM << " (asymmetry fit)" << endl ;
break;
case MSR_FITTYPE_MU_MINUS:
fout << left << "fittype" << MSR_FITTYPE_MU_MINUS << " (mu minus fit)" << endl ;
break;
case MSR_FITTYPE_NON_MUSR:
fout << left << "fittype" << MSR_FITTYPE_NON_MUSR << " (non muSR fit)" << endl ;
break;
default:
break;
}
} else if (sstr.BeginsWith("alpha ")) {
fout.width(16);
fout << left << "alpha";
fout << fRuns[runNo].GetAlphaParamNo() << endl;
} else if (sstr.BeginsWith("beta ")) {
fout.width(16);
fout << left << "beta";
fout << fRuns[runNo].GetBetaParamNo() << endl;
} else if (sstr.BeginsWith("norm")) {
fout.width(16);
fout << left << "norm";
// check if norm is give as a function
if (fRuns[runNo].GetNormParamNo() >= MSR_PARAM_FUN_OFFSET)
fout << "fun" << fRuns[runNo].GetNormParamNo()-MSR_PARAM_FUN_OFFSET;
else
fout << fRuns[runNo].GetNormParamNo();
fout << endl;
} else if (sstr.BeginsWith("backgr.fit")) {
fout.width(16);
fout << left << "backgr.fit";
fout << fRuns[runNo].GetBkgFitParamNo() << endl;
} else if (sstr.BeginsWith("lifetime ")) {
fout.width(16);
fout << left << "lifetime";
fout << fRuns[runNo].GetLifetimeParamNo() << endl;
} else if (sstr.BeginsWith("lifetimecorrection")) {
/* obsolate, hence do nothing here
if ((fRuns[runNo].IsLifetimeCorrected()) &&
((fRuns[runNo].GetFitType() == MSR_FITTYPE_SINGLE_HISTO) ||
(fGlobal.GetFitType() == MSR_FITTYPE_SINGLE_HISTO))) {
fout << "lifetimecorrection" << endl;
}
*/
} else if (sstr.BeginsWith("map")) {
fout << "map ";
for (UInt_t j=0; j<fRuns[runNo].GetMap()->size(); j++) {
fout.width(5);
fout << right << fRuns[runNo].GetMap(j);
}
// if there are less maps then 10 fill with zeros
if (fRuns[runNo].GetMap()->size() < 10) {
for (UInt_t j=fRuns[runNo].GetMap()->size(); j<10; j++)
fout << " 0";
}
fout << endl;
} else if (sstr.BeginsWith("forward")) {
if (fRuns[runNo].GetForwardHistoNoSize() == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrLogFile: **WARNING** 'forward' tag without any data found!";
cerr << endl << ">> Something is VERY fishy, please check your msr-file carfully." << endl;
} else {
TString result("");
PIntVector forward;
for (UInt_t i=0; i<fRuns[runNo].GetForwardHistoNoSize(); i++)
forward.push_back(fRuns[runNo].GetForwardHistoNo(i));
MakeDetectorGroupingString("forward", forward, result);
forward.clear();
fout << result.Data() << endl;
}
} else if (sstr.BeginsWith("backward")) {
if (fRuns[runNo].GetBackwardHistoNoSize() == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrLogFile: **WARNING** 'backward' tag without any data found!";
cerr << endl << ">> Something is VERY fishy, please check your msr-file carfully." << endl;
} else {
TString result("");
PIntVector backward;
for (UInt_t i=0; i<fRuns[runNo].GetBackwardHistoNoSize(); i++)
backward.push_back(fRuns[runNo].GetBackwardHistoNo(i));
MakeDetectorGroupingString("backward", backward, result);
backward.clear();
fout << result.Data() << endl;
}
} else if (sstr.BeginsWith("backgr.fix")) {
fout.width(16);
fout << left << "backgr.fix";
for (UInt_t j=0; j<2; j++) {
if (fRuns[runNo].GetBkgFix(j) != PMUSR_UNDEFINED) {
fout.precision(prec);
fout.width(12);
fout << left << fRuns[runNo].GetBkgFix(j);
}
}
fout << endl;
} else if (sstr.BeginsWith("background")) {
backgroundTagMissing[runNo] = false;
fout.width(16);
fout << left << "background";
for (UInt_t j=0; j<4; j++) {
if (fRuns[runNo].GetBkgRange(j) > 0) {
fout.width(8);
fout << left << fRuns[runNo].GetBkgRange(j);
}
}
if (fRuns[runNo].GetBkgEstimated(0) != PMUSR_UNDEFINED) {
Int_t precision=4;
if ((Int_t)log10(fRuns[runNo].GetBkgEstimated(0))+1 >= 4)
precision = 2;
fout << " # estimated bkg: ";
fout << fixed;
fout.precision(precision);
fout << fRuns[runNo].GetBkgEstimated(0);
if (fRuns[runNo].GetBkgEstimated(1) != PMUSR_UNDEFINED) {
fout << " / ";
fout << fixed;
fout.precision(precision);
fout << fRuns[runNo].GetBkgEstimated(1);
}
}
fout << endl;
} else if (sstr.BeginsWith("data")) {
dataTagMissing[runNo] = false;
fout.width(16);
fout << left << "data";
for (UInt_t j=0; j<4; j++) {
if (fRuns[runNo].GetDataRange(j) > 0) {
fout.width(8);
fout << left << fRuns[runNo].GetDataRange(j);
}
}
fout << endl;
} else if (sstr.BeginsWith("t0")) {
t0TagMissing[runNo] = false;
fout.width(16);
fout << left << "t0";
for (UInt_t j=0; j<fRuns[runNo].GetT0BinSize(); j++) {
fout.width(8);
fout.precision(1);
fout.setf(ios::fixed,ios::floatfield);
fout << left << fRuns[runNo].GetT0Bin(j);
}
fout << endl;
} else if (sstr.BeginsWith("addt0")) {
addt0TagMissing[runNo][addT0Counter] = false;
if (fRuns[runNo].GetAddT0BinSize(addT0Counter) <=0) {
cerr << endl << ">> PMsrHandler::WriteMsrLogFile: **WARNING** 'addt0' tag without any data found!";
cerr << endl << ">> Something is VERY fishy, please check your msr-file carfully." << endl;
} else {
fout.width(16);
fout << left << "addt0";
for (Int_t j=0; j<fRuns[runNo].GetAddT0BinSize(addT0Counter); j++) {
fout.width(8);
fout.precision(1);
fout.setf(ios::fixed,ios::floatfield);
fout << left << fRuns[runNo].GetAddT0Bin(addT0Counter, j);
}
fout << endl;
addT0Counter++;
}
} else if (sstr.BeginsWith("xy-data")) {
if (fRuns[runNo].GetXDataIndex() != -1) { // indices
fout.width(16);
fout << left << "xy-data";
fout.width(8);
fout.precision(2);
fout << left << fixed << fRuns[runNo].GetXDataIndex();
fout.width(8);
fout.precision(2);
fout << left << fixed << fRuns[runNo].GetYDataIndex();
fout << endl;
} else if (!fRuns[runNo].GetXDataLabel()->IsWhitespace()) { // labels
fout.width(16);
fout << left << "xy-data";
fout.width(8);
fout << left << fixed << fRuns[runNo].GetXDataLabel()->Data();
fout << " ";
fout.width(8);
fout << left << fixed << fRuns[runNo].GetYDataLabel()->Data();
fout << endl;
}
} else if (sstr.BeginsWith("fit")) {
// check if missing t0/addt0/background/data tag are present eventhough the values are present, if so write these data values
// if ISIS data, do not do anything
if (t0TagMissing[runNo] && fRuns[runNo].GetInstitute()->CompareTo("isis", TString::kIgnoreCase)) {
if (fRuns[runNo].GetT0BinSize() > 0) {
fout.width(16);
fout << left << "t0";
for (UInt_t j=0; j<fRuns[runNo].GetT0BinSize(); j++) {
fout.width(8);
fout.precision(1);
fout.setf(ios::fixed,ios::floatfield);
fout << left << fRuns[runNo].GetT0Bin(j);
}
fout << endl;
}
}
for (UInt_t i=0; i<fRuns[runNo].GetAddT0BinEntries(); i++) {
if (addt0TagMissing[runNo][i] && fRuns[runNo].GetInstitute()->CompareTo("isis", TString::kIgnoreCase)) {
if (fRuns[runNo].GetAddT0BinSize(i) > 0) {
fout.width(16);
fout << left << "addt0";
for (Int_t j=0; j<fRuns[runNo].GetAddT0BinSize(i); j++) {
fout.width(8);
fout.precision(1);
fout.setf(ios::fixed,ios::floatfield);
fout << left << fRuns[runNo].GetAddT0Bin(i, j);
}
fout << endl;
}
}
}
if (backgroundTagMissing[runNo]) {
if (fRuns[runNo].GetBkgRange(0) >= 0) {
fout.width(16);
fout << left << "background";
for (UInt_t j=0; j<4; j++) {
if (fRuns[runNo].GetBkgRange(j) > 0) {
fout.width(8);
fout << left << fRuns[runNo].GetBkgRange(j);
}
}
fout << endl;
}
}
if (dataTagMissing[runNo]) {
if (fRuns[runNo].GetDataRange(0) >= 0) {
fout.width(16);
fout << left << "data";
for (UInt_t j=0; j<4; j++) {
if (fRuns[runNo].GetDataRange(j) > 0) {
fout.width(8);
fout << left << fRuns[runNo].GetDataRange(j);
}
}
fout << endl;
}
}
// write fit range line
fout.width(16);
fout << left << "fit";
if (fRuns[runNo].IsFitRangeInBin()) { // fit range given in bins
fout << "fgb";
if (fRuns[runNo].GetFitRangeOffset(0) > 0)
fout << "+" << fRuns[runNo].GetFitRangeOffset(0);
fout << " lgb";
if (fRuns[runNo].GetFitRangeOffset(1) > 0)
fout << "-" << fRuns[runNo].GetFitRangeOffset(1);
neededPrec = LastSignificant(fRuns[runNo].GetFitRange(0));
if (LastSignificant(fRuns[runNo].GetFitRange(1)) > neededPrec)
neededPrec = LastSignificant(fRuns[runNo].GetFitRange(1));
fout.precision(neededPrec);
fout << " # in time: " << fRuns[runNo].GetFitRange(0) << ".." << fRuns[runNo].GetFitRange(1) << " (usec)";
} else { // fit range given in time
for (UInt_t j=0; j<2; j++) {
if (fRuns[runNo].GetFitRange(j) == -1)
break;
neededWidth = 7;
neededPrec = LastSignificant(fRuns[runNo].GetFitRange(j));
fout.width(neededWidth);
fout.precision(neededPrec);
fout << left << fixed << fRuns[runNo].GetFitRange(j);
if (j==0)
fout << " ";
}
}
fout << endl;
} else if (sstr.BeginsWith("packing")) {
fout.width(16);
fout << left << "packing";
fout << fRuns[runNo].GetPacking() << endl;
} else {
fout << str.Data() << endl;
}
break;
case MSR_TAG_COMMANDS:
fout << str.Data() << endl;
break;
case MSR_TAG_FOURIER:
sstr = str;
sstr.Remove(TString::kLeading, ' ');
if (sstr.BeginsWith("units")) {
fout << "units ";
if (fFourier.fUnits == FOURIER_UNIT_GAUSS) {
fout << "Gauss";
} else if (fFourier.fUnits == FOURIER_UNIT_TESLA) {
fout << "Tesla";
} else if (fFourier.fUnits == FOURIER_UNIT_FREQ) {
fout << "MHz ";
} else if (fFourier.fUnits == FOURIER_UNIT_CYCLES) {
fout << "Mc/s";
}
fout << " # units either 'Gauss', 'Tesla', 'MHz', or 'Mc/s'";
fout << endl;
} else if (sstr.BeginsWith("fourier_power")) {
fout << "fourier_power " << fFourier.fFourierPower << endl;
} else if (sstr.BeginsWith("dc-corrected")) {
fout << "dc-corrected ";
if (fFourier.fDCCorrected == true)
fout << "true" << endl;
else
fout << "false" << endl;
} else if (sstr.BeginsWith("apodization")) {
fout << "apodization ";
if (fFourier.fApodization == FOURIER_APOD_NONE) {
fout << "NONE ";
} else if (fFourier.fApodization == FOURIER_APOD_WEAK) {
fout << "WEAK ";
} else if (fFourier.fApodization == FOURIER_APOD_MEDIUM) {
fout << "MEDIUM";
} else if (fFourier.fApodization == FOURIER_APOD_STRONG) {
fout << "STRONG";
}
fout << " # NONE, WEAK, MEDIUM, STRONG";
fout << endl;
} else if (sstr.BeginsWith("plot")) {
fout << "plot ";
if (fFourier.fPlotTag == FOURIER_PLOT_REAL) {
fout << "REAL ";
} else if (fFourier.fPlotTag == FOURIER_PLOT_IMAG) {
fout << "IMAG ";
} else if (fFourier.fPlotTag == FOURIER_PLOT_REAL_AND_IMAG) {
fout << "REAL_AND_IMAG";
} else if (fFourier.fPlotTag == FOURIER_PLOT_POWER) {
fout << "POWER";
} else if (fFourier.fPlotTag == FOURIER_PLOT_PHASE) {
fout << "PHASE";
}
fout << " # REAL, IMAG, REAL_AND_IMAG, POWER, PHASE";
fout << endl;
} else if (sstr.BeginsWith("phase")) {
if (fFourier.fPhaseParamNo > 0) {
fout << "phase par" << fFourier.fPhaseParamNo << endl;
} else {
if (fFourier.fPhase != -999.0) {
fout << "phase " << fFourier.fPhase << endl;
}
}
} else if (sstr.BeginsWith("range_for_phase_correction")) {
fout << "range_for_phase_correction " << fFourier.fRangeForPhaseCorrection[0] << " " << fFourier.fRangeForPhaseCorrection[1] << endl;
} else if (sstr.BeginsWith("range ")) {
fout << "range " << fFourier.fPlotRange[0] << " " << fFourier.fPlotRange[1] << endl;
} else {
fout << str.Data() << endl;
}
break;
case MSR_TAG_PLOT:
sstr = str;
sstr.Remove(TString::kLeading, ' ');
if (sstr.BeginsWith("PLOT")) {
switch (fPlots[plotNo].fPlotType) {
case MSR_PLOT_SINGLE_HISTO:
fout << "PLOT " << fPlots[plotNo].fPlotType << " (single histo plot)" << endl;
break;
case MSR_PLOT_ASYM:
fout << "PLOT " << fPlots[plotNo].fPlotType << " (asymmetry plot)" << endl;
break;
case MSR_PLOT_MU_MINUS:
fout << "PLOT " << fPlots[plotNo].fPlotType << " (mu minus plot)" << endl;
break;
case MSR_PLOT_NON_MUSR:
fout << "PLOT " << fPlots[plotNo].fPlotType << " (non muSR plot)" << endl;
break;
default:
break;
}
if (fPlots[plotNo].fLifeTimeCorrection) {
fout << "lifetimecorrection" << endl;
}
} else if (sstr.BeginsWith("lifetimecorrection")) {
// do nothing, since it is already handled in the lines above.
// The reason why this handled that oddly is due to legacy issues
// of this flag, i.e. transfer from RUN -> PLOT
} else if (sstr.BeginsWith("runs")) {
fout << "runs ";
fout.precision(0);
for (UInt_t j=0; j<fPlots[plotNo].fRuns.size(); j++) {
fout.width(4);
fout << fPlots[plotNo].fRuns[j];
}
fout << endl;
} else if (sstr.BeginsWith("range")) {
fout << "range ";
neededPrec = LastSignificant(fPlots[plotNo].fTmin[0]);
fout.precision(neededPrec);
fout << fPlots[plotNo].fTmin[0];
fout << " ";
neededPrec = LastSignificant(fPlots[plotNo].fTmax[0]);
fout.precision(neededPrec);
fout << fPlots[plotNo].fTmax[0];
if (fPlots[plotNo].fYmin.size() > 0) {
fout << " ";
neededPrec = LastSignificant(fPlots[plotNo].fYmin[0]);
fout.precision(neededPrec);
fout << fPlots[plotNo].fYmin[0] << " ";
neededPrec = LastSignificant(fPlots[plotNo].fYmax[0]);
fout.precision(neededPrec);
fout << fPlots[plotNo].fYmax[0];
}
fout << endl;
} else {
fout << str.Data() << endl;
}
break;
case MSR_TAG_STATISTIC:
statisticBlockFound = true;
sstr = str;
sstr.Remove(TString::kLeading, ' ');
if (sstr.BeginsWith("STATISTIC")) {
TDatime dt;
fout << "STATISTIC --- " << dt.AsSQLString() << endl;
} else if (sstr.BeginsWith("chisq") || sstr.BeginsWith("maxLH")) {
partialStatisticBlockFound = false;
if (fStatistic.fValid) { // valid fit result
if (fStatistic.fChisq) {
str.Form(" chisq = %.1lf, NDF = %d, chisq/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
fout << str.Data() << endl;
if (messages)
cout << endl << str.Data() << endl;
// check if expected chisq needs to be written
if (fStatistic.fMinExpected != 0.0) {
str.Form(" expected chisq = %.1lf, NDF = %d, expected chisq/NDF = %lf",
fStatistic.fMinExpected, fStatistic.fNdf, fStatistic.fMinExpected/fStatistic.fNdf);
if (fStartupOptions) {
if (fStartupOptions->writeExpectedChisq)
fout << str.Data() << endl;
}
if (messages)
cout << endl << str.Data() << endl;
for (UInt_t i=0; i<fStatistic.fMinExpectedPerHisto.size(); i++) {
if (fStatistic.fNdfPerHisto[i] > 0) {
str.Form(" run block %d: (NDF/red.chisq/red.chisq_e) = (%d/%lf/%lf)",
i+1, fStatistic.fNdfPerHisto[i], fStatistic.fMinPerHisto[i]/fStatistic.fNdfPerHisto[i], fStatistic.fMinExpectedPerHisto[i]/fStatistic.fNdfPerHisto[i]);
if (fStartupOptions) {
if (fStartupOptions->writeExpectedChisq)
fout << str.Data() << endl;
}
if (messages)
cout << str.Data() << endl;
}
}
} else if (fStatistic.fNdfPerHisto.size() > 1) { // check if per run chisq needs to be written
for (UInt_t i=0; i<fStatistic.fNdfPerHisto.size(); i++) {
str.Form(" run block %d: (NDF/red.chisq) = (%d/%lf)",
i+1, fStatistic.fNdfPerHisto[i], fStatistic.fMinPerHisto[i]/fStatistic.fNdfPerHisto[i]);
if (fStartupOptions) {
if (fStartupOptions->writeExpectedChisq)
fout << str.Data() << endl;
}
if (messages)
cout << str.Data() << endl;
}
}
} else { // maxLH
str.Form(" maxLH = %.1lf, NDF = %d, maxLH/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
fout << str.Data() << endl;
if (messages)
cout << endl << str.Data() << endl;
}
} else {
fout << "*** FIT DID NOT CONVERGE ***" << endl;
if (messages)
cout << endl << "*** FIT DID NOT CONVERGE ***" << endl;
}
} else if (sstr.BeginsWith("*** FIT DID NOT CONVERGE ***")) {
partialStatisticBlockFound = false;
if (fStatistic.fValid) { // valid fit result
if (fStatistic.fChisq) { // chisq
str.Form(" chisq = %.1lf, NDF = %d, chisq/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
fout << str.Data() << endl;
if (messages)
cout << endl << str.Data() << endl;
// check if expected chisq needs to be written
if (fStatistic.fMinExpected != 0.0) {
str.Form(" expected chisq = %.1lf, NDF = %d, expected chisq/NDF = %lf",
fStatistic.fMinExpected, fStatistic.fNdf, fStatistic.fMinExpected/fStatistic.fNdf);
if (fStartupOptions) {
if (fStartupOptions->writeExpectedChisq)
fout << str.Data() << endl;
}
if (messages)
cout << str.Data() << endl;
for (UInt_t i=0; i<fStatistic.fMinExpectedPerHisto.size(); i++) {
if (fStatistic.fNdfPerHisto[i] > 0) {
str.Form(" run block %d: (NDF/red.chisq/red.chisq_e) = (%d/%lf/%lf)",
i+1, fStatistic.fNdfPerHisto[i], fStatistic.fMinPerHisto[i]/fStatistic.fNdfPerHisto[i], fStatistic.fMinExpectedPerHisto[i]/fStatistic.fNdfPerHisto[i]);
if (fStartupOptions) {
if (fStartupOptions->writeExpectedChisq)
fout << str.Data() << endl;
}
if (messages)
cout << str.Data() << endl;
}
}
} else if (fStatistic.fNdfPerHisto.size() > 1) { // check if per run chisq needs to be written
for (UInt_t i=0; i<fStatistic.fNdfPerHisto.size(); i++) {
str.Form(" run block %d: (NDF/red.chisq) = (%d/%lf)",
i+1, fStatistic.fNdfPerHisto[i], fStatistic.fMinPerHisto[i]/fStatistic.fNdfPerHisto[i]);
if (fStartupOptions) {
if (fStartupOptions->writeExpectedChisq)
fout << str.Data() << endl;
}
if (messages)
cout << str.Data() << endl;
}
}
} else { // max. log. liklihood
str.Form(" maxLH = %.1lf, NDF = %d, maxLH/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
fout << str.Data() << endl;
if (messages)
cout << endl << str.Data() << endl;
}
} else {
fout << "*** FIT DID NOT CONVERGE ***" << endl;
if (messages)
cout << endl << "*** FIT DID NOT CONVERGE ***" << endl;
}
} else {
if (str.Length() > 0) {
sstr = str;
sstr.Remove(TString::kLeading, ' ');
if (!sstr.BeginsWith("expected chisq") && !sstr.BeginsWith("run block"))
fout << str.Data() << endl;
} else { // only write endl if not eof is reached. This is preventing growing msr-files, i.e. more and more empty lines at the end of the file
if (!fin.eof())
fout << endl;
}
}
break;
default:
break;
}
}
// there was no statistic block present in the msr-input-file
if (!statisticBlockFound) {
partialStatisticBlockFound = false;
cerr << endl << ">> PMsrHandler::WriteMsrLogFile: **WARNING** no STATISTIC block present, will write a default one" << endl;
fout << "###############################################################" << endl;
TDatime dt;
fout << "STATISTIC --- " << dt.AsSQLString() << endl;
if (fStatistic.fValid) { // valid fit result
if (fStatistic.fChisq) {
str.Form(" chisq = %.1lf, NDF = %d, chisq/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
fout << str.Data() << endl;
if (messages)
cout << endl << str.Data() << endl;
// check if expected chisq needs to be written
if (fStatistic.fMinExpected != 0.0) {
str.Form(" expected chisq = %.1lf, NDF = %d, expected chisq/NDF = %lf",
fStatistic.fMinExpected, fStatistic.fNdf, fStatistic.fMinExpected/fStatistic.fNdf);
if (fStartupOptions) {
if (fStartupOptions->writeExpectedChisq)
fout << str.Data() << endl;
}
if (messages)
cout << str.Data() << endl;
for (UInt_t i=0; i<fStatistic.fMinExpectedPerHisto.size(); i++) {
if (fStatistic.fNdfPerHisto[i] > 0) {
str.Form(" run block %d: (NDF/red.chisq/red.chisq_e) = (%d/%lf/%lf)",
i+1, fStatistic.fNdfPerHisto[i], fStatistic.fMinPerHisto[i]/fStatistic.fNdfPerHisto[i], fStatistic.fMinExpectedPerHisto[i]/fStatistic.fNdfPerHisto[i]);
if (fStartupOptions) {
if (fStartupOptions->writeExpectedChisq)
fout << str.Data() << endl;
}
if (messages)
cout << str.Data() << endl;
}
}
} else if (fStatistic.fNdfPerHisto.size() > 1) { // check if per run chisq needs to be written
for (UInt_t i=0; i<fStatistic.fNdfPerHisto.size(); i++) {
str.Form(" run block %d: (NDF/red.chisq) = (%d/%lf)",
i+1, fStatistic.fNdfPerHisto[i], fStatistic.fMinPerHisto[i]/fStatistic.fNdfPerHisto[i]);
if (fStartupOptions) {
if (fStartupOptions->writeExpectedChisq)
fout << str.Data() << endl;
}
if (messages)
cout << str.Data() << endl;
}
}
} else { // maxLH
str.Form(" maxLH = %.1lf, NDF = %d, maxLH/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
fout << str.Data() << endl;
if (messages)
cout << endl << str.Data() << endl;
// check if per run block maxLH needs to be written
}
} else {
fout << "*** FIT DID NOT CONVERGE ***" << endl;
if (messages)
cout << endl << "*** FIT DID NOT CONVERGE ***" << endl;
}
}
// there was only a partial statistic block present in the msr-input-file
if (partialStatisticBlockFound) {
cerr << endl << ">> PMsrHandler::WriteMsrLogFile: **WARNING** garbage STATISTIC block present in the msr-input file.";
cerr << endl << ">> ** WILL ADD SOME SENSIBLE STUFF, BUT YOU HAVE TO CHECK IT SINCE I AM **NOT** REMOVING THE GARBAGE! **" << endl;
TDatime dt;
fout << "STATISTIC --- " << dt.AsSQLString() << endl;
if (fStatistic.fValid) { // valid fit result
if (fStatistic.fChisq) { // chisq
str.Form(" chisq = %.1lf, NDF = %d, chisq/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
fout << str.Data() << endl;
if (messages)
cout << endl << str.Data() << endl;
// check if expected chisq needs to be written
if (fStatistic.fMinExpected != 0.0) {
str.Form(" expected chisq = %.1lf, NDF = %d, expected chisq/NDF = %lf",
fStatistic.fMinExpected, fStatistic.fNdf, fStatistic.fMinExpected/fStatistic.fNdf);
if (fStartupOptions) {
if (fStartupOptions->writeExpectedChisq)
fout << str.Data() << endl;
}
if (messages)
cout << str.Data() << endl;
for (UInt_t i=0; i<fStatistic.fMinExpectedPerHisto.size(); i++) {
if (fStatistic.fNdfPerHisto[i] > 0) {
str.Form(" run block %d: (NDF/red.chisq/red.chisq_e) =(%d/%lf/%lf)",
i+1, fStatistic.fNdfPerHisto[i], fStatistic.fMinExpectedPerHisto[i]/fStatistic.fNdfPerHisto[i], fStatistic.fMinExpectedPerHisto[i]/fStatistic.fNdfPerHisto[i]);
if (fStartupOptions) {
if (fStartupOptions->writeExpectedChisq)
fout << str.Data() << endl;
}
if (messages)
cout << str.Data() << endl;
}
}
} else if (fStatistic.fNdfPerHisto.size() > 1) { // check if per run chisq needs to be written
for (UInt_t i=0; i<fStatistic.fNdfPerHisto.size(); i++) {
str.Form(" run block %d: (NDF/red.chisq) = (%d/%lf)",
i+1, fStatistic.fNdfPerHisto[i], fStatistic.fMinPerHisto[i]/fStatistic.fNdfPerHisto[i]);
if (fStartupOptions) {
if (fStartupOptions->writeExpectedChisq)
fout << str.Data() << endl;
}
if (messages)
cout << str.Data() << endl;
}
}
} else { // max. log. liklihood
str.Form(" maxLH = %.1lf, NDF = %d, maxLH/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
fout << str.Data() << endl;
if (messages)
cout << endl << str.Data() << endl;
}
} else {
fout << "*** FIT DID NOT CONVERGE (4) ***" << endl;
if (messages)
cout << endl << "*** FIT DID NOT CONVERGE ***" << endl;
}
}
// close files
fout.close();
fin.close();
// clean up
t0TagMissing.clear();
backgroundTagMissing.clear();
dataTagMissing.clear();
return PMUSR_SUCCESS;
}
//--------------------------------------------------------------------------
// WriteMsrFile (public)
//--------------------------------------------------------------------------
/**
* <p>Writes a msr-file from the internal data structures
*
* <p><b>return:</b>
* - PMUSR_SUCCESS everything is OK
* - PMUSR_MSR_FILE_WRITE_ERROR msr output file couldn't be opened
*
* \param filename The name of the output file.
*/
Int_t PMsrHandler::WriteMsrFile(const Char_t *filename, map<UInt_t, TString> *commentsPAR, \
map<UInt_t, TString> *commentsTHE, \
map<UInt_t, TString> *commentsFUN, \
map<UInt_t, TString> *commentsRUN)
{
const UInt_t prec = 6; // output precision for float/doubles
const TString hline = "###############################################################";
UInt_t i = 0;
map<UInt_t, TString>::iterator iter;
TString str, *pstr;
// open output file for writing
ofstream fout(filename);
if (!fout) {
return PMUSR_MSR_FILE_WRITE_ERROR;
}
// write TITLE
fout << fTitle.Data() << endl;
fout << hline.Data() << endl;
// write FITPARAMETER block
fout << "FITPARAMETER" << endl;
fout << "# No Name Value Step Pos_Error Boundaries" << endl;
for (i = 0; i < fParam.size(); ++i) {
if (commentsPAR) {
iter = commentsPAR->find(i+1);
if (iter != commentsPAR->end()) {
fout << endl;
fout << "# " << iter->second.Data() << endl;
fout << endl;
commentsPAR->erase(iter);
}
}
// parameter no
fout.width(9);
fout << right << fParam[i].fNo;
fout << " ";
// parameter name
fout.width(11);
fout << left << fParam[i].fName.Data();
fout << " ";
// value of the parameter
fout.width(9);
fout.precision(prec);
fout << left << fParam[i].fValue;
fout << " ";
// value of step/error/neg.error
fout.width(11);
fout.precision(prec);
fout << left << fParam[i].fStep;
fout << " ";
fout.width(11);
fout.precision(prec);
if ((fParam[i].fNoOfParams == 5) || (fParam[i].fNoOfParams == 7)) // pos. error given
if (fParam[i].fPosErrorPresent && (fParam[i].fStep != 0)) // pos error is a number
fout << left << fParam[i].fPosError;
else // pos error is a none
fout << left << "none";
else // no pos. error
fout << left << "none";
fout << " ";
// boundaries
if (fParam[i].fNoOfParams > 5) {
fout.width(7);
fout.precision(prec);
if (fParam[i].fLowerBoundaryPresent)
fout << left << fParam[i].fLowerBoundary;
else
fout << left << "none";
fout << " ";
fout.width(7);
fout.precision(prec);
if (fParam[i].fUpperBoundaryPresent)
fout << left << fParam[i].fUpperBoundary;
else
fout << left << "none";
fout << " ";
}
fout << endl;
}
if (commentsPAR && !commentsPAR->empty()) {
fout << endl;
for(iter = commentsPAR->begin(); iter != commentsPAR->end(); ++iter) {
fout << "# " << iter->second.Data() << endl;
}
commentsPAR->clear();
}
fout << endl;
fout << hline.Data() << endl;
// write THEORY block
fout << "THEORY" << endl;
for (i = 1; i < fTheory.size(); ++i) {
if (commentsTHE) {
iter = commentsTHE->find(i);
if (iter != commentsTHE->end()) {
fout << endl;
fout << "# " << iter->second.Data() << endl;
fout << endl;
commentsTHE->erase(iter);
}
}
fout << fTheory[i].fLine.Data() << endl;
}
if (commentsTHE && !commentsTHE->empty()) {
fout << endl;
for(iter = commentsTHE->begin(); iter != commentsTHE->end(); ++iter) {
fout << "# " << iter->second.Data() << endl;
}
commentsTHE->clear();
}
fout << endl;
fout << hline.Data() << endl;
// write FUNCTIONS block
// or comment it if there is none in the data structures
if (fFunctions.size() < 2)
fout << "# ";
fout << "FUNCTIONS" << endl;
for (i = 1; i < fFunctions.size(); ++i) {
if (commentsFUN) {
iter = commentsFUN->find(i);
if (iter != commentsFUN->end()) {
fout << endl;
fout << "# " << iter->second.Data() << endl;
fout << endl;
commentsFUN->erase(iter);
}
}
fout << fFunctions[i].fLine.Data() << endl;
}
if (commentsFUN && !commentsFUN->empty()) {
fout << endl;
for(iter = commentsFUN->begin(); iter != commentsFUN->end(); ++iter) {
fout << "# " << iter->second.Data() << endl;
}
commentsFUN->clear();
}
fout << endl;
fout << hline.Data() << endl;
// write GLOBAL block
if (fGlobal.IsPresent()) {
// not sure that anything needs to be done here ...
}
// write RUN blocks
for (i = 0; i < fRuns.size(); ++i) {
if (commentsRUN) {
iter = commentsRUN->find(i + 1);
if (iter != commentsRUN->end()) {
if (!i)
fout << endl;
fout << "# " << iter->second.Data() << endl;
fout << endl;
commentsRUN->erase(iter);
}
}
fout << "RUN " << fRuns[i].GetRunName()->Data() << " ";
pstr = fRuns[i].GetBeamline();
if (pstr == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrFile: **ERROR** Couldn't obtain beamline data." << endl;
assert(0);
}
pstr->ToUpper();
fout << pstr->Data() << " ";
pstr = fRuns[i].GetInstitute();
if (pstr == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrFile: **ERROR** Couldn't obtain institute data." << endl;
assert(0);
}
pstr->ToUpper();
fout << pstr->Data() << " ";
pstr = fRuns[i].GetFileFormat();
if (pstr == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrFile: **ERROR** Couldn't obtain file format data." << endl;
assert(0);
}
pstr->ToUpper();
fout << pstr->Data() << " (name beamline institute data-file-format)" << endl;
// ADDRUN
for (UInt_t j = 1; j < fRuns[i].GetRunNameSize(); ++j) {
fout << "ADDRUN " << fRuns[i].GetRunName(j)->Data() << " ";
pstr = fRuns[i].GetBeamline(j);
if (pstr == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrFile: **ERROR** Couldn't obtain beamline data (addrun)." << endl;
assert(0);
}
pstr->ToUpper();
fout << pstr->Data() << " ";
pstr = fRuns[i].GetInstitute(j);
if (pstr == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrFile: **ERROR** Couldn't obtain institute data (addrun)." << endl;
assert(0);
}
pstr->ToUpper();
fout << pstr->Data() << " ";
pstr = fRuns[i].GetFileFormat(j);
if (pstr == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrFile: **ERROR** Couldn't obtain file format data (addrun)." << endl;
assert(0);
}
pstr->ToUpper();
fout << pstr->Data() << " (name beamline institute data-file-format)" << endl;
}
// fittype
fout.width(16);
switch (fRuns[i].GetFitType()) {
case MSR_FITTYPE_SINGLE_HISTO:
fout << left << "fittype" << MSR_FITTYPE_SINGLE_HISTO << " (single histogram fit)" << endl;
break;
case MSR_FITTYPE_ASYM:
fout << left << "fittype" << MSR_FITTYPE_ASYM << " (asymmetry fit)" << endl ;
break;
case MSR_FITTYPE_MU_MINUS:
fout << left << "fittype" << MSR_FITTYPE_MU_MINUS << " (mu minus fit)" << endl ;
break;
case MSR_FITTYPE_NON_MUSR:
fout << left << "fittype" << MSR_FITTYPE_NON_MUSR << " (non muSR fit)" << endl ;
break;
default:
break;
}
// alpha
if (fRuns[i].GetAlphaParamNo() != -1) {
fout.width(16);
fout << left << "alpha";
fout << fRuns[i].GetAlphaParamNo() << endl;
}
// beta
if (fRuns[i].GetBetaParamNo() != -1) {
fout.width(16);
fout << left << "beta";
fout << fRuns[i].GetBetaParamNo() << endl;
}
// norm
if (fRuns[i].GetNormParamNo() != -1) {
fout.width(16);
fout << left << "norm";
// check if norm is give as a function
if (fRuns[i].GetNormParamNo() >= MSR_PARAM_FUN_OFFSET)
fout << "fun" << fRuns[i].GetNormParamNo()-MSR_PARAM_FUN_OFFSET;
else
fout << fRuns[i].GetNormParamNo();
fout << endl;
}
// backgr.fit
if (fRuns[i].GetBkgFitParamNo() != -1) {
fout.width(16);
fout << left << "backgr.fit";
fout << fRuns[i].GetBkgFitParamNo() << endl;
}
// lifetime
if (fRuns[i].GetLifetimeParamNo() != -1) {
fout.width(16);
fout << left << "lifetime";
fout << fRuns[i].GetLifetimeParamNo() << endl;
}
// lifetimecorrection
if ((fRuns[i].IsLifetimeCorrected()) && (fRuns[i].GetFitType() == MSR_FITTYPE_SINGLE_HISTO)) {
fout << "lifetimecorrection" << endl;
}
// map
fout << "map ";
for (UInt_t j=0; j<fRuns[i].GetMap()->size(); ++j) {
fout.width(5);
fout << right << fRuns[i].GetMap(j);
}
// if there are less maps then 10 fill with zeros
if (fRuns[i].GetMap()->size() < 10) {
for (UInt_t j=fRuns[i].GetMap()->size(); j<10; ++j)
fout << " 0";
}
fout << endl;
// forward
if (fRuns[i].GetForwardHistoNoSize() == 0) {
cerr << endl << ">> PMsrHandler::WriteMsrFile: **WARNING** No 'forward' data found!";
cerr << endl << ">> Something is VERY fishy, please check your msr-file carfully." << endl;
} else {
fout.width(16);
fout << left << "forward";
for (UInt_t j=0; j<fRuns[i].GetForwardHistoNoSize(); ++j) {
fout.width(8);
fout << fRuns[i].GetForwardHistoNo(j);
}
fout << endl;
}
// backward
if (fRuns[i].GetBackwardHistoNoSize() > 0) {
fout.width(16);
fout << left << "backward";
for (UInt_t j=0; j<fRuns[i].GetBackwardHistoNoSize(); ++j) {
fout.width(8);
fout << fRuns[i].GetBackwardHistoNo(j);
}
fout << endl;
}
// backgr.fix
if ((fRuns[i].GetBkgFix(0) != PMUSR_UNDEFINED) || (fRuns[i].GetBkgFix(1) != PMUSR_UNDEFINED)) {
fout.width(15);
fout << left << "backgr.fix";
for (UInt_t j=0; j<2; ++j) {
if (fRuns[i].GetBkgFix(j) != PMUSR_UNDEFINED) {
fout.precision(prec);
fout.width(12);
fout << left << fRuns[i].GetBkgFix(j);
}
}
fout << endl;
}
// background
if ((fRuns[i].GetBkgRange(0) != -1) || (fRuns[i].GetBkgRange(1) != -1) || (fRuns[i].GetBkgRange(2) != -1) || (fRuns[i].GetBkgRange(3) != -1)) {
fout.width(16);
fout << left << "background";
for (UInt_t j=0; j<4; ++j) {
if (fRuns[i].GetBkgRange(j) > 0) {
fout.width(8);
fout << left << fRuns[i].GetBkgRange(j);
}
}
fout << endl;
}
// data
if ((fRuns[i].GetDataRange(0) != -1) || (fRuns[i].GetDataRange(1) != -1) || (fRuns[i].GetDataRange(2) != -1) || (fRuns[i].GetDataRange(3) != -1)) {
fout.width(16);
fout << left << "data";
for (UInt_t j=0; j<4; ++j) {
if (fRuns[i].GetDataRange(j) > 0) {
fout.width(8);
fout << left << fRuns[i].GetDataRange(j);
}
}
fout << endl;
}
// t0
if (fRuns[i].GetT0BinSize() > 0) {
fout.width(16);
fout << left << "t0";
for (UInt_t j=0; j<fRuns[i].GetT0BinSize(); ++j) {
fout.width(8);
fout.precision(1);
fout.setf(ios::fixed,ios::floatfield);
fout << left << fRuns[i].GetT0Bin(j);
}
fout << endl;
}
// addt0
for (UInt_t j = 0; j < fRuns[i].GetRunNameSize() - 1; ++j) {
if (fRuns[i].GetAddT0BinSize(j) > 0) {
fout.width(16);
fout << left << "addt0";
for (Int_t k=0; k<fRuns[i].GetAddT0BinSize(j); ++k) {
fout.width(8);
fout.precision(1);
fout.setf(ios::fixed,ios::floatfield);
fout << left << fRuns[i].GetAddT0Bin(j, k);
}
fout << endl;
}
}
// xy-data
if (fRuns[i].GetXDataIndex() != -1) { // indices
fout.width(16);
fout << left << "xy-data";
fout.width(8);
fout.precision(2);
fout << left << fixed << fRuns[i].GetXDataIndex();
fout.width(8);
fout.precision(2);
fout << left << fixed << fRuns[i].GetYDataIndex();
fout << endl;
} else if (!fRuns[i].GetXDataLabel()->IsWhitespace()) { // labels
fout.width(16);
fout << left << "xy-data";
fout.width(8);
fout << left << fixed << fRuns[i].GetXDataLabel()->Data();
fout << " ";
fout.width(8);
fout << left << fixed << fRuns[i].GetYDataLabel()->Data();
fout << endl;
}
// fit
fout.width(16);
fout << left << "fit";
if (fRuns[i].IsFitRangeInBin()) { // fit range given in bins
fout << "fgb";
if (fRuns[i].GetFitRangeOffset(0) > 0)
fout << "+" << fRuns[i].GetFitRangeOffset(0);
fout << " lgb";
if (fRuns[i].GetFitRangeOffset(1) > 0)
fout << "-" << fRuns[i].GetFitRangeOffset(1);
} else { // fit range given in time
for (UInt_t j=0; j<2; j++) {
if (fRuns[i].GetFitRange(j) == -1)
break;
UInt_t neededWidth = 7;
UInt_t neededPrec = LastSignificant(fRuns[i].GetFitRange(j));
fout.width(neededWidth);
fout.precision(neededPrec);
fout << left << fixed << fRuns[i].GetFitRange(j);
if (j==0)
fout << " ";
}
}
fout << endl;
// packing
fout.width(16);
fout << left << "packing";
fout << fRuns[i].GetPacking() << endl;
fout << endl;
}
if (commentsRUN && !commentsRUN->empty()) {
for(iter = commentsRUN->begin(); iter != commentsRUN->end(); ++iter) {
fout << "# " << iter->second.Data() << endl;
}
fout << endl;
commentsRUN->clear();
}
fout << hline.Data() << endl;
// write COMMANDS block
fout << "COMMANDS" << endl;
for (i = 0; i < fCommands.size(); ++i) {
if (fCommands[i].fLine.BeginsWith("SET BATCH") || fCommands[i].fLine.BeginsWith("END RETURN"))
continue;
else
fout << fCommands[i].fLine.Data() << endl;
}
fout << endl;
fout << hline.Data() << endl;
// write FOURIER block
if (fFourier.fFourierBlockPresent) {
fout << "FOURIER" << endl;
// units
if (fFourier.fUnits) {
fout << "units ";
if (fFourier.fUnits == FOURIER_UNIT_GAUSS) {
fout << "Gauss";
} else if (fFourier.fUnits == FOURIER_UNIT_TESLA) {
fout << "Tesla";
} else if (fFourier.fUnits == FOURIER_UNIT_FREQ) {
fout << "MHz ";
} else if (fFourier.fUnits == FOURIER_UNIT_CYCLES) {
fout << "Mc/s";
}
fout << " # units either 'Gauss', 'Tesla', 'MHz', or 'Mc/s'";
fout << endl;
}
// fourier_power
if (fFourier.fFourierPower != -1) {
fout << "fourier_power " << fFourier.fFourierPower << endl;
}
// apodization
if (fFourier.fApodization) {
fout << "apodization ";
if (fFourier.fApodization == FOURIER_APOD_NONE) {
fout << "NONE ";
} else if (fFourier.fApodization == FOURIER_APOD_WEAK) {
fout << "WEAK ";
} else if (fFourier.fApodization == FOURIER_APOD_MEDIUM) {
fout << "MEDIUM";
} else if (fFourier.fApodization == FOURIER_APOD_STRONG) {
fout << "STRONG";
}
fout << " # NONE, WEAK, MEDIUM, STRONG";
fout << endl;
}
// plot
if (fFourier.fPlotTag) {
fout << "plot ";
if (fFourier.fPlotTag == FOURIER_PLOT_REAL) {
fout << "REAL ";
} else if (fFourier.fPlotTag == FOURIER_PLOT_IMAG) {
fout << "IMAG ";
} else if (fFourier.fPlotTag == FOURIER_PLOT_REAL_AND_IMAG) {
fout << "REAL_AND_IMAG";
} else if (fFourier.fPlotTag == FOURIER_PLOT_POWER) {
fout << "POWER";
} else if (fFourier.fPlotTag == FOURIER_PLOT_PHASE) {
fout << "PHASE";
}
fout << " # REAL, IMAG, REAL_AND_IMAG, POWER, PHASE";
fout << endl;
}
// phase
if (fFourier.fPhaseParamNo > 0) {
fout << "phase par" << fFourier.fPhaseParamNo << endl;
} else if (fFourier.fPhase != -999.0) {
fout << "phase " << fFourier.fPhase << endl;
}
// range_for_phase_correction
if ((fFourier.fRangeForPhaseCorrection[0] != -1.0) || (fFourier.fRangeForPhaseCorrection[1] != -1.0)) {
fout << "range_for_phase_correction " << fFourier.fRangeForPhaseCorrection[0] << " " << fFourier.fRangeForPhaseCorrection[1] << endl;
}
// range
if ((fFourier.fPlotRange[0] != -1.0) || (fFourier.fPlotRange[1] != -1.0)) {
fout << "range " << fFourier.fPlotRange[0] << " " << fFourier.fPlotRange[1] << endl;
}
// // phase_increment -- not used in msr-files at the moment (can only be set through the xml-file)
// if (fFourier.fPhaseIncrement) {
// fout << "phase_increment " << fFourier.fPhaseIncrement << endl;
// }
fout << endl;
fout << hline.Data() << endl;
}
// write PLOT blocks
for (i = 0; i < fPlots.size(); ++i) {
switch (fPlots[i].fPlotType) {
case MSR_PLOT_SINGLE_HISTO:
fout << "PLOT " << fPlots[i].fPlotType << " (single histo plot)" << endl;
break;
case MSR_PLOT_ASYM:
fout << "PLOT " << fPlots[i].fPlotType << " (asymmetry plot)" << endl;
break;
case MSR_PLOT_MU_MINUS:
fout << "PLOT " << fPlots[i].fPlotType << " (mu minus plot)" << endl;
break;
case MSR_PLOT_NON_MUSR:
fout << "PLOT " << fPlots[i].fPlotType << " (non muSR plot)" << endl;
break;
default:
break;
}
// runs
fout << "runs ";
fout.precision(0);
for (UInt_t j=0; j<fPlots[i].fRuns.size(); ++j) {
fout.width(4);
fout << fPlots[i].fRuns[j];
}
fout << endl;
// range and sub_ranges
if ((fPlots[i].fTmin.size() == 1) && (fPlots[i].fTmax.size() == 1)) {
fout << "range ";
fout.precision(2);
fout << fPlots[i].fTmin[0] << " " << fPlots[i].fTmax[0];
} else if ((fPlots[i].fTmin.size() > 1) && (fPlots[i].fTmax.size() > 1)) {
fout << "sub_ranges ";
fout.precision(2);
for (UInt_t j=0; j < fPlots[i].fTmin.size(); ++j) {
fout << " " << fPlots[i].fTmin[j] << " " << fPlots[i].fTmax[j];
}
}
if (!fPlots[i].fYmin.empty() && !fPlots[i].fYmax.empty()) {
fout << " " << fPlots[i].fYmin[0] << " " << fPlots[i].fYmax[0];
}
fout << endl;
// use_fit_ranges
if (fPlots[i].fUseFitRanges) {
if (!fPlots[i].fYmin.empty() && !fPlots[i].fYmax.empty())
fout << "use_fit_ranges " << fPlots[i].fYmin[0] << " " << fPlots[i].fYmax[0] << endl;
else
fout << "use_fit_ranges" << endl;
}
// view_packing
if (fPlots[i].fViewPacking != -1) {
fout << "view_packing " << fPlots[i].fViewPacking << endl;
}
// logx
if (fPlots[i].fLogX) {
fout << "logx" << endl;
}
// logy
if (fPlots[i].fLogY) {
fout << "logy" << endl;
}
// rrf_packing
if (fPlots[i].fRRFPacking) {
fout << "rrf_packing " << fPlots[i].fRRFPacking << endl;
}
// rrf_freq
if (fPlots[i].fRRFFreq) {
fout << "rrf_freq " << fPlots[i].fRRFFreq << " ";
switch (fPlots[i].fRRFUnit) {
case RRF_UNIT_kHz:
fout << "kHz";
break;
case RRF_UNIT_MHz:
fout << "MHz";
break;
case RRF_UNIT_Mcs:
fout << "Mc/s";
break;
case RRF_UNIT_G:
fout << "G";
break;
case RRF_UNIT_T:
fout << "T";
break;
default:
break;
}
fout << endl;
}
// rrf_phase
if (fPlots[i].fRRFPhaseParamNo > 0) {
fout << "rrf_phase par" << fPlots[i].fRRFPhaseParamNo << endl;
} else if (fPlots[i].fRRFPhase) {
fout << "rrf_phase " << fPlots[i].fRRFPhase << endl;
}
fout << endl;
}
if (!fPlots.empty()) {
fout << hline.Data() << endl;
}
// write STATISTIC block
TDatime dt;
fout << "STATISTIC --- " << dt.AsSQLString() << endl;
if (fStatistic.fValid) { // valid fit result
if (fStatistic.fChisq) { // chisq
str = " chisq = ";
str += fStatistic.fMin;
str += ", NDF = ";
str += fStatistic.fNdf;
str += ", chisq/NDF = ";
str += fStatistic.fMin / fStatistic.fNdf;
fout << str.Data() << endl;
} else { // max. log. liklihood
str = " maxLH = ";
str += fStatistic.fMin;
str += ", NDF = ";
str += fStatistic.fNdf;
str += ", maxLH/NDF = ";
str += fStatistic.fMin / fStatistic.fNdf;
fout << str.Data() << endl;
}
} else {
fout << "*** FIT DID NOT CONVERGE ***" << endl;
}
// close file
fout.close();
str.Clear();
pstr = 0;
return PMUSR_SUCCESS;
}
//--------------------------------------------------------------------------
// SetMsrParamValue (public)
//--------------------------------------------------------------------------
/**
* <p>Sets the fit parameter value at position idx.
*
* <p><b>return:</b>
* - true if idx is within range
* - false if idx is larger than the fit parameter vector.
*
* \param idx index of the fit parameter value.
* \param value fit parameter value to be set.
*/
Bool_t PMsrHandler::SetMsrParamValue(UInt_t idx, Double_t value)
{
if (idx >= fParam.size()) {
cerr << endl << ">> PMsrHandler::SetMsrParamValue(): **ERROR** idx = " << idx << " is >= than the number of fit parameters " << fParam.size();
cerr << endl;
return false;
}
fParam[idx].fValue = value;
return true;
}
//--------------------------------------------------------------------------
// SetMsrParamStep (public)
//--------------------------------------------------------------------------
/**
* <p>Sets the fit parameter step value (initial step size for minuit2) at positon idx.
* After a successful fit, the negative error will be writen.
*
* <p><b>return:</b>
* - true if idx is within range
* - false if idx is larger than the fit parameter vector.
*
* \param idx index fo the fit parameter step value
* \param value fit parameter step value to be set.
*/
Bool_t PMsrHandler::SetMsrParamStep(UInt_t idx, Double_t value)
{
if (idx >= fParam.size()) {
cerr << endl << ">> PMsrHandler::SetMsrParamValue(): **ERROR** idx = " << idx << " is larger than the number of parameters " << fParam.size();
cerr << endl;
return false;
}
fParam[idx].fStep = value;
return true;
}
//--------------------------------------------------------------------------
// SetMsrParamPosErrorPresent (public)
//--------------------------------------------------------------------------
/**
* <p>Sets the flag whether the fit parameter positive error value is persent. This at positon idx.
*
* <p><b>return:</b>
* - true if idx is within range
* - false if idx is larger than the fit parameter vector.
*
* \param idx index fo the fit parameter positive error value
* \param value fit parameter positive error value present.
*/
Bool_t PMsrHandler::SetMsrParamPosErrorPresent(UInt_t idx, Bool_t value)
{
if (idx >= fParam.size()) {
cerr << endl << ">> PMsrHandler::SetMsrParamPosErrorPresent(): **ERROR** idx = " << idx << " is larger than the number of parameters " << fParam.size();
cerr << endl;
return false;
}
fParam[idx].fPosErrorPresent = value;
return true;
}
//--------------------------------------------------------------------------
// SetMsrParamPosError (public)
//--------------------------------------------------------------------------
/**
* <p>Sets the fit parameter positive error value at positon idx.
*
* <p><b>return:</b>
* - true if idx is within range
* - false if idx is larger than the fit parameter vector.
*
* \param idx index fo the fit parameter positive error value
* \param value fit parameter positive error value to be set.
*/
Bool_t PMsrHandler::SetMsrParamPosError(UInt_t idx, Double_t value)
{
if (idx >= fParam.size()) {
cerr << endl << ">> PMsrHandler::SetMsrParamPosError(): **ERROR** idx = " << idx << " is larger than the number of parameters " << fParam.size();
cerr << endl;
return false;
}
fParam[idx].fPosErrorPresent = true;
fParam[idx].fPosError = value;
return true;
}
//--------------------------------------------------------------------------
// SetMsrT0Entry (public)
//--------------------------------------------------------------------------
/**
* <p>Sets the t0 entries for a given runNo and a given histogram index idx.
*
* \param runNo msr-file run number
* \param idx msr-file histogram index
* \param bin t0 bin value
*/
void PMsrHandler::SetMsrT0Entry(UInt_t runNo, UInt_t idx, Double_t bin)
{
if (runNo >= fRuns.size()) { // error
cerr << endl << ">> PMsrHandler::SetMsrT0Entry: **ERROR** runNo = " << runNo << ", is out of valid range 0.." << fRuns.size();
cerr << endl;
return;
}
if (idx >= fRuns[runNo].GetT0BinSize()) { // error
cerr << endl << ">> PMsrHandler::SetMsrT0Entry: **WARNING** idx = " << idx << ", is out of valid range 0.." << fRuns[runNo].GetT0BinSize();
cerr << endl << ">> Will add it anyway.";
cerr << endl;
}
fRuns[runNo].SetT0Bin(bin, idx);
}
//--------------------------------------------------------------------------
// SetMsrAddT0Entry (public)
//--------------------------------------------------------------------------
/**
* <p> Sets a t0 value for an addrun entry.
*
* \param runNo msr-file run number
* \param addRunIdx msr-file addrun index, e.g. if 2 addruns are present addRunIdx can take the values 0 or 1.
* \param histoIdx msr-file histogram index for an addrun.
* \param bin t0 bin value.
*/
void PMsrHandler::SetMsrAddT0Entry(UInt_t runNo, UInt_t addRunIdx, UInt_t histoIdx, Double_t bin)
{
if (runNo >= fRuns.size()) { // error
cerr << endl << ">> PMsrHandler::SetMsrAddT0Entry: **ERROR** runNo = " << runNo << ", is out of valid range 0.." << fRuns.size();
cerr << endl;
return;
}
if (addRunIdx >= fRuns[runNo].GetAddT0BinEntries()) { // error
cerr << endl << ">> PMsrHandler::SetMsrAddT0Entry: **WARNING** addRunIdx = " << addRunIdx << ", is out of valid range 0.." << fRuns[runNo].GetAddT0BinEntries();
cerr << endl << ">> Will add it anyway.";
cerr << endl;
}
if (static_cast<Int_t>(histoIdx) > fRuns[runNo].GetAddT0BinSize(addRunIdx)) { // error
cerr << endl << ">> PMsrHandler::SetMsrAddT0Entry: **WARNING** histoIdx = " << histoIdx << ", is out of valid range 0.." << fRuns[runNo].GetAddT0BinSize(addRunIdx);
cerr << endl << ">> Will add it anyway.";
cerr << endl;
}
fRuns[runNo].SetAddT0Bin(bin, addRunIdx, histoIdx);
}
//--------------------------------------------------------------------------
// SetMsrDataRangeEntry (public)
//--------------------------------------------------------------------------
/**
* <p>Sets the data range entries for a given runNo and a given histogram index idx.
*
* \param runNo msr-file run number
* \param idx 0=start bin index, 1=end bin index
* \param bin data range bin value
*/
void PMsrHandler::SetMsrDataRangeEntry(UInt_t runNo, UInt_t idx, Int_t bin)
{
if (runNo >= fRuns.size()) { // error
cerr << endl << ">> PMsrHandler::SetMsrDataRangeEntry: **ERROR** runNo = " << runNo << ", is out of valid range 0.." << fRuns.size();
cerr << endl;
return;
}
fRuns[runNo].SetDataRange(bin, idx);
}
//--------------------------------------------------------------------------
// SetMsrBkgRangeEntry (public)
//--------------------------------------------------------------------------
/**
* <p>Sets the background range entries for a given runNo and a given histogram index idx.
*
* \param runNo msr-file run number
* \param idx 0=start bin index, 1=end bin index
* \param bin background range bin value
*/
void PMsrHandler::SetMsrBkgRangeEntry(UInt_t runNo, UInt_t idx, Int_t bin)
{
if (runNo >= fRuns.size()) { // error
cerr << endl << ">> PMsrHandler::SetMsrBkgRangeEntry: **ERROR** runNo = " << runNo << ", is out of valid range 0.." << fRuns.size();
cerr << endl;
return;
}
fRuns[runNo].SetBkgRange(bin, idx);
}
//--------------------------------------------------------------------------
// ParameterInUse (public)
//--------------------------------------------------------------------------
/**
* <p>Needed for the following purpose: if minuit is minimizing, it varies
* all the parameters of the parameter list (if not fixed), even if a particular
* parameter is <b>NOT</b> used at all. This is stupid! Hence one has to check
* if the parameter is used at all and if not, it has to be fixed.
*
* <p><b>return:</b>
* - 0 if the parameter is <b>not</b> used.
* - a value > 0 if the parameter is used.
*
* \param paramNo parameter number
*/
Int_t PMsrHandler::ParameterInUse(UInt_t paramNo)
{
// check that paramNo is within acceptable range
if ((paramNo < 0) || (paramNo >= fParam.size()))
return -1;
return fParamInUse[paramNo];
}
//--------------------------------------------------------------------------
// HandleFitParameterEntry (private)
//--------------------------------------------------------------------------
/**
* <p>The routine analyze a parameter line and, if the possible parameter list
* is OK (what this means see below), it adds the parameter to the parameter list.
*
* <p>Possible cases:
* \code
* No Name Value Step/Neg_Error Pos_Error Boundary_Low Boundary_High
* x x x x x x x -> 7 Parameters, e.g. after a MINOS fit
* x x x x x -> 5 Parameters, e.g. after a MINOS fit
* without boundaries
* x x x x -> 4 Parameters, e.g. after MIGRAD fit
* without boundaries, or
* when starting
* \endcode
*
* <b>return:</b>
* - true is fit parameter lines are OK.
* - false otherwise
*
* \param lines is a list of lines containing the fitparameter block
*/
Bool_t PMsrHandler::HandleFitParameterEntry(PMsrLines &lines)
{
// If msr-file is used for musrFT only, nothing needs to be done here.
if (fFourierOnly)
return true;
PMsrParamStructure param;
Bool_t error = false;
PMsrLines::iterator iter;
TObjArray *tokens = 0;
TObjString *ostr = 0;
TString str;
// fill param structure
iter = lines.begin();
while ((iter != lines.end()) && !error) {
// init param structure
param.fNoOfParams = -1;
param.fNo = -1;
param.fName = TString("");
param.fValue = 0.0;
param.fStep = 0.0;
param.fPosErrorPresent = false;
param.fPosError = 0.0;
param.fLowerBoundaryPresent = false;
param.fLowerBoundary = 0.0;
param.fUpperBoundaryPresent = false;
param.fUpperBoundary = 0.0;
tokens = iter->fLine.Tokenize(" \t");
if (!tokens) {
cerr << endl << ">> PMsrHandler::HandleFitParameterEntry: **SEVERE ERROR** Couldn't tokenize Parameters in line " << iter->fLineNo;
cerr << endl << endl;
return false;
}
// handle various input possiblities
if ((tokens->GetEntries() < 4) || (tokens->GetEntries() > 7) || (tokens->GetEntries() == 6)) {
error = true;
} else { // handle the first 4 parameter since they are always the same
// parameter number
ostr = dynamic_cast<TObjString*>(tokens->At(0));
str = ostr->GetString();
if (str.IsDigit())
param.fNo = str.Atoi();
else
error = true;
// parameter name
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
param.fName = str;
// parameter value
ostr = dynamic_cast<TObjString*>(tokens->At(2));
str = ostr->GetString();
if (str.IsFloat())
param.fValue = (Double_t)str.Atof();
else
error = true;
// parameter value
ostr = dynamic_cast<TObjString*>(tokens->At(3));
str = ostr->GetString();
if (str.IsFloat())
param.fStep = (Double_t)str.Atof();
else
error = true;
// 4 values, i.e. No Name Value Step
if (tokens->GetEntries() == 4) {
param.fNoOfParams = 4;
}
// 5 values, i.e. No Name Value Neg_Error Pos_Error
if (tokens->GetEntries() == 5) {
param.fNoOfParams = 5;
// positive error
ostr = dynamic_cast<TObjString*>(tokens->At(4));
str = ostr->GetString();
if (str.IsFloat()) {
param.fPosErrorPresent = true;
param.fPosError = (Double_t)str.Atof();
} else {
str.ToLower();
if (!str.CompareTo("none", TString::kIgnoreCase))
param.fPosErrorPresent = false;
else
error = true;
}
}
// 7 values, i.e. No Name Value Neg_Error Pos_Error Lower_Boundary Upper_Boundary
if (tokens->GetEntries() == 7) {
param.fNoOfParams = 7;
// positive error
ostr = dynamic_cast<TObjString*>(tokens->At(4));
str = ostr->GetString();
if (str.IsFloat()) {
param.fPosErrorPresent = true;
param.fPosError = (Double_t)str.Atof();
} else {
str.ToLower();
if (!str.CompareTo("none", TString::kIgnoreCase))
param.fPosErrorPresent = false;
else
error = true;
}
// lower boundary
ostr = dynamic_cast<TObjString*>(tokens->At(5));
str = ostr->GetString();
// check if lower boundary is "none", i.e. upper boundary limited only
if (!str.CompareTo("none", TString::kIgnoreCase)) { // none
param.fLowerBoundaryPresent = false;
} else { // assuming that the lower boundary is a number
if (str.IsFloat()) {
param.fLowerBoundary = (Double_t)str.Atof();
param.fLowerBoundaryPresent = true;
} else {
error = true;
}
}
// upper boundary
ostr = dynamic_cast<TObjString*>(tokens->At(6));
str = ostr->GetString();
// check if upper boundary is "none", i.e. lower boundary limited only
if (!str.CompareTo("none", TString::kIgnoreCase)) { // none
param.fUpperBoundaryPresent = false;
} else { // assuming a number
if (str.IsFloat()) {
param.fUpperBoundary = (Double_t)str.Atof();
param.fUpperBoundaryPresent = true;
} else {
error = true;
}
}
// check for lower-/upper-boundaries = none/none
if (!param.fLowerBoundaryPresent && !param.fUpperBoundaryPresent)
param.fNoOfParams = 5; // since there are no real boundaries present
}
}
// check if enough elements found
if (error) {
cerr << endl;
cerr << endl << ">> PMsrHandler::HandleFitParameterEntry: **ERROR** in line " << iter->fLineNo << ":";
cerr << endl << ">> " << iter->fLine.Data();
cerr << endl << ">> A Fit Parameter line needs to have the following form: ";
cerr << endl;
cerr << endl << ">> No Name Value Step/Error [Lower_Boundary Upper_Boundary]";
cerr << endl;
cerr << endl << ">> or";
cerr << endl;
cerr << endl << ">> No Name Value Step/Neg_Error Pos_Error [Lower_Boundary Upper_Boundary]";
cerr << endl;
cerr << endl << ">> No: the parameter number (an Int_t)";
cerr << endl << ">> Name: the name of the parameter (less than 256 character)";
cerr << endl << ">> Value: the starting value of the parameter (a Double_t)";
cerr << endl << ">> Step/Error,";
cerr << endl << ">> Step/Neg_Error: the starting step value in a fit (a Double_t), or";
cerr << endl << ">> the symmetric error (MIGRAD, SIMPLEX), or";
cerr << endl << ">> the negative error (MINOS)";
cerr << endl << ">> Pos_Error: the positive error (MINOS), (a Double_t or \"none\")";
cerr << endl << ">> Lower_Boundary: the lower boundary allowed for the fit parameter (a Double_t or \"none\")";
cerr << endl << ">> Upper_Boundary: the upper boundary allowed for the fit parameter (a Double_t or \"none\")";
cerr << endl;
} else { // everything is OK, therefore add the parameter to the parameter list
fParam.push_back(param);
}
// clean up
if (tokens) {
delete tokens;
tokens = 0;
}
iter++;
}
// check if all parameters have subsequent numbers.
for (UInt_t i=0; i<fParam.size(); i++) {
if (fParam[i].fNo != (Int_t)i+1) {
error = true;
cerr << endl << ">> PMsrHandler::HandleFitParameterEntry: **ERROR**";
cerr << endl << ">> Sorry, you are assuming to much from this program, it cannot";
cerr << endl << ">> handle none subsequent numbered parameters yet or in the near future.";
cerr << endl << ">> Found parameter " << fParam[i].fName.Data() << ", with";
cerr << endl << ">> parameter number " << fParam[i].fNo << ", at paramter position " << i+1 << ".";
cerr << endl << ">> This needs to be fixed first.";
cerr << endl;
break;
}
}
return !error;
}
//--------------------------------------------------------------------------
// HandleTheoryEntry (private)
//--------------------------------------------------------------------------
/**
* <p>Just stores the THEORY block lines.
*
* <b>return:</b>
* - true always
*
* \param lines is a list of lines containing the theory block
*/
Bool_t PMsrHandler::HandleTheoryEntry(PMsrLines &lines)
{
// If msr-file is used for musrFT only, nothing needs to be done here.
if (fFourierOnly)
return true;
// store the theory lines
fTheory = lines;
return true;
}
//--------------------------------------------------------------------------
// HandleFunctionsEntry (private)
//--------------------------------------------------------------------------
/**
* <p>Parses the FUNCTIONS block of the msr-file.
*
* <b>return:</b>
* - true if the parsing was successful.
* - false otherwise
*
* \param lines is a list of lines containing the functions block
*/
Bool_t PMsrHandler::HandleFunctionsEntry(PMsrLines &lines)
{
// If msr-file is used for musrFT only, nothing needs to be done here.
if (fFourierOnly)
return true;
// store the functions lines
fFunctions = lines;
// create function handler
fFuncHandler = new PFunctionHandler(fFunctions);
if (fFuncHandler == 0) {
cerr << endl << ">> PMsrHandler::HandleFunctionsEntry: **ERROR** Couldn't invoke PFunctionHandler." << endl;
return false;
}
// do the parsing
if (!fFuncHandler->DoParse()) {
return false;
}
// check if an empty FUNCTIONS block is present
if ((fFuncHandler->GetNoOfFuncs() == 0) && !lines.empty()) {
cerr << endl << ">> PMsrHandler::HandleFunctionsEntry: **WARNING** empty FUNCTIONS block found!";
cerr << endl;
}
return true;
}
//--------------------------------------------------------------------------
// HandleGlobalEntry (private)
//--------------------------------------------------------------------------
/**
* <p>Parses the GLOBAL block of the msr-file.
*
* <b>return:</b>
* - true if successful
* - false otherwise
*
* \param lines is a list of lines containing the run blocks
*/
Bool_t PMsrHandler::HandleGlobalEntry(PMsrLines &lines)
{
PMsrLines::iterator iter;
PMsrGlobalBlock global;
Bool_t error = false;
TString str;
TObjArray *tokens = 0;
TObjString *ostr = 0;
Int_t ival;
Double_t dval;
UInt_t addT0Counter = 0;
// since this routine is called, a GLOBAL block is present
global.SetGlobalPresent(true);
iter = lines.begin();
while ((iter != lines.end()) && !error) {
// remove potential comment at the end of lines
str = iter->fLine;
Ssiz_t idx = str.Index("#");
if (idx != -1)
str.Remove(idx);
// tokenize line
tokens = str.Tokenize(" \t");
if (!tokens) {
cerr << endl << ">> PMsrHandler::HandleGlobalEntry: **SEVERE ERROR** Couldn't tokenize line " << iter->fLineNo;
cerr << endl << endl;
return false;
}
if (iter->fLine.BeginsWith("fittype", TString::kIgnoreCase)) { // fittype
if (tokens->GetEntries() < 2) {
error = true;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit()) {
Int_t fittype = str.Atoi();
if ((fittype == MSR_FITTYPE_SINGLE_HISTO) ||
(fittype == MSR_FITTYPE_ASYM) ||
(fittype == MSR_FITTYPE_MU_MINUS) ||
(fittype == MSR_FITTYPE_NON_MUSR)) {
global.SetFitType(fittype);
} else {
error = true;
}
} else {
error = true;
}
}
} else if (iter->fLine.BeginsWith("data", TString::kIgnoreCase)) { // data
if (tokens->GetEntries() < 3) {
error = true;
} else {
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if (ival >= 0) {
global.SetDataRange(ival, i-1);
} else {
error = true;
}
} else {
error = true;
}
}
}
} else if (iter->fLine.BeginsWith("t0", TString::kIgnoreCase)) { // t0
if (tokens->GetEntries() < 2) {
error = true;
} else {
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsFloat()) {
dval = str.Atof();
if (dval >= 0.0)
global.SetT0Bin(dval);
else
error = true;
} else {
error = true;
}
}
}
} else if (iter->fLine.BeginsWith("addt0", TString::kIgnoreCase)) { // addt0
if (tokens->GetEntries() < 2) {
error = true;
} else {
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsFloat()) {
dval = str.Atof();
if (dval >= 0.0)
global.SetAddT0Bin(dval, addT0Counter, i-1);
else
error = true;
} else {
error = true;
}
}
}
addT0Counter++;
} else if (iter->fLine.BeginsWith("fit", TString::kIgnoreCase)) { // fit range
if (tokens->GetEntries() < 3) {
error = true;
} else { // fit given in time, i.e. fit <start> <end>, where <start>, <end> are given as doubles
if (iter->fLine.Contains("fgb", TString::kIgnoreCase)) { // fit given in bins, i.e. fit fgb+n0 lgb-n1
// check 1st entry, i.e. fgb[+n0]
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
Ssiz_t idx = str.First("+");
TString numStr = str;
if (idx > -1) { // '+' present hence extract n0
numStr.Remove(0,idx+1);
if (numStr.IsFloat()) {
global.SetFitRangeOffset(numStr.Atoi(), 0);
} else {
error = true;
}
} else { // n0 == 0
global.SetFitRangeOffset(0, 0);
}
// check 2nd entry, i.e. lgb[-n1]
ostr = dynamic_cast<TObjString*>(tokens->At(2));
str = ostr->GetString();
idx = str.First("-");
numStr = str;
if (idx > -1) { // '-' present hence extract n1
numStr.Remove(0,idx+1);
if (numStr.IsFloat()) {
global.SetFitRangeOffset(numStr.Atoi(), 1);
} else {
error = true;
}
} else { // n0 == 0
global.SetFitRangeOffset(0, 0);
}
if (!error)
global.SetFitRangeInBins(true);
} else { // fit given in time, i.e. fit <start> <end>, where <start>, <end> are given as doubles
for (Int_t i=1; i<3; i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsFloat())
global.SetFitRange(str.Atof(), i-1);
else
error = true;
}
}
}
} else if (iter->fLine.BeginsWith("packing", TString::kIgnoreCase)) { // packing
if (tokens->GetEntries() < 2) {
error = true;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if (ival >= 0) {
global.SetPacking(ival);
} else {
error = true;
}
} else {
error = true;
}
}
}
// clean up
if (tokens) {
delete tokens;
tokens = 0;
}
++iter;
}
if (error) {
--iter;
cerr << endl << ">> PMsrHandler::HandleGlobalEntry: **ERROR** in line " << iter->fLineNo << ":";
cerr << endl << ">> '" << iter->fLine.Data() << "'";
cerr << endl << ">> GLOBAL block syntax is too complex to print it here. Please check the manual.";
} else { // save global
fGlobal = global;
}
return !error;
}
//--------------------------------------------------------------------------
// HandleRunEntry (private)
//--------------------------------------------------------------------------
/**
* <p>Parses the RUN blocks of the msr-file.
*
* <b>return:</b>
* - true if successful
* - false otherwise
*
* \param lines is a list of lines containing the run blocks
*/
Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines)
{
PMsrLines::iterator iter;
PMsrRunBlock param;
Bool_t first = true; // first run line tag
Bool_t error = false;
Bool_t runLinePresent = false;
TString str;
TObjArray *tokens = 0;
TObjString *ostr = 0;
UInt_t addT0Counter = 0;
Int_t ival;
Double_t dval;
iter = lines.begin();
while ((iter != lines.end()) && !error) {
// remove potential comment at the end of lines
str = iter->fLine;
Ssiz_t idx = str.Index("#");
if (idx != -1)
str.Remove(idx);
// tokenize line
tokens = str.Tokenize(" \t");
if (!tokens) {
cerr << endl << ">> PMsrHandler::HandleRunEntry: **SEVERE ERROR** Couldn't tokenize Parameters in line " << iter->fLineNo;
cerr << endl << endl;
return false;
}
// RUN line ----------------------------------------------
if (iter->fLine.BeginsWith("run", TString::kIgnoreCase)) {
runLinePresent = true; // this is needed to make sure that a run line is present before and ADDRUN is following
if (!first) { // not the first run in the list
fRuns.push_back(param);
param.CleanUp();
} else {
first = false;
}
// get run name, beamline, institute, and file-format
if (tokens->GetEntries() < 5) {
error = true;
} else {
// run name
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
param.SetRunName(str);
// beamline
ostr = dynamic_cast<TObjString*>(tokens->At(2));
str = ostr->GetString();
param.SetBeamline(str);
// institute
ostr = dynamic_cast<TObjString*>(tokens->At(3));
str = ostr->GetString();
param.SetInstitute(str);
// data file format
ostr = dynamic_cast<TObjString*>(tokens->At(4));
str = ostr->GetString();
param.SetFileFormat(str);
}
addT0Counter = 0; // reset counter
}
// ADDRUN line ---------------------------------------------
if (iter->fLine.BeginsWith("addrun", TString::kIgnoreCase)) {
if (!runLinePresent) {
cerr << endl << ">> PMsrHandler::HandleRunEntry: **ERROR** Found ADDRUN without prior RUN, or";
cerr << endl << ">> ADDRUN lines intercepted by other stuff. All this is not allowed!";
cerr << endl << ">> error in line " << iter->fLineNo;
cerr << endl;
error = true;
continue;
}
// get run name, beamline, institute, and file-format
if (tokens->GetEntries() < 5) {
error = true;
} else {
// run name
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
param.SetRunName(str);
// beamline
ostr = dynamic_cast<TObjString*>(tokens->At(2));
str = ostr->GetString();
param.SetBeamline(str);
// institute
ostr = dynamic_cast<TObjString*>(tokens->At(3));
str = ostr->GetString();
param.SetInstitute(str);
// data file format
ostr = dynamic_cast<TObjString*>(tokens->At(4));
str = ostr->GetString();
param.SetFileFormat(str);
}
}
// fittype -------------------------------------------------
if (iter->fLine.BeginsWith("fittype", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() < 2) {
error = true;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit()) {
Int_t fittype = str.Atoi();
if ((fittype == MSR_FITTYPE_SINGLE_HISTO) ||
(fittype == MSR_FITTYPE_ASYM) ||
(fittype == MSR_FITTYPE_MU_MINUS) ||
(fittype == MSR_FITTYPE_NON_MUSR)) {
param.SetFitType(fittype);
} else {
error = true;
}
} else {
error = true;
}
}
}
// alpha -------------------------------------------------
if (iter->fLine.BeginsWith("alpha", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() < 2) {
error = true;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if (ival > 0)
param.SetAlphaParamNo(ival);
else
error = true;
} else {
error = true;
}
}
}
// beta -------------------------------------------------
if (iter->fLine.BeginsWith("beta", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() < 2) {
error = true;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if (ival > 0)
param.SetBetaParamNo(ival);
else
error = true;
} else {
error = true;
}
}
}
// norm -------------------------------------------------
if (iter->fLine.BeginsWith("norm", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() < 2) {
error = true;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit()) {
param.SetNormParamNo(str.Atoi());
} else if (str.Contains("fun")) {
Int_t no;
if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, no))
param.SetNormParamNo(no);
else
error = true;
} else {
error = true;
}
}
}
// backgr.fit --------------------------------------------
if (iter->fLine.BeginsWith("backgr.fit", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() < 2) {
error = true;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if (ival > 0)
param.SetBkgFitParamNo(ival);
else
error = true;
} else {
error = true;
}
}
}
// lifetime ------------------------------------------------
if (iter->fLine.BeginsWith("lifetime ", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() < 2) {
error = true;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if (ival > 0)
param.SetLifetimeParamNo(ival);
else
error = true;
} else {
error = true;
}
}
}
// lifetimecorrection ---------------------------------------
if (iter->fLine.BeginsWith("lifetimecorrection", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
param.SetLifetimeCorrection(true);
}
// map ------------------------------------------------------
if (iter->fLine.BeginsWith("map", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if (ival >= 0)
param.SetMap(ival);
else
error = true;
} else {
error = true;
}
}
// check map entries, i.e. if the map values are within parameter bounds
if (!fFourierOnly) {
for (UInt_t i=0; i<param.GetMap()->size(); i++) {
if ((param.GetMap(i) < 0) || (param.GetMap(i) > (Int_t) fParam.size())) {
cerr << endl << ">> PMsrHandler::HandleRunEntry: **SEVERE ERROR** map value " << param.GetMap(i) << " in line " << iter->fLineNo << " is out of range!";
error = true;
break;
}
}
}
}
// forward ------------------------------------------------
if (iter->fLine.BeginsWith("forward", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() < 2) {
error = true;
} else {
PIntVector group;
str = iter->fLine;
if (ParseDetectorGrouping(str, group)) {
for (UInt_t i=0; i<group.size(); i++) {
param.SetForwardHistoNo(group[i]);
}
} else {
error = true;
}
group.clear();
}
}
// backward -----------------------------------------------
if (iter->fLine.BeginsWith("backward", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() < 2) {
error = true;
} else {
PIntVector group;
str = iter->fLine;
if (ParseDetectorGrouping(str, group)) {
for (UInt_t i=0; i<group.size(); i++) {
param.SetBackwardHistoNo(group[i]);
}
} else {
error = true;
}
group.clear();
}
}
// backgr.fix ----------------------------------------------
if (iter->fLine.BeginsWith("backgr.fix", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() < 2) {
error = true;
} else {
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsFloat())
param.SetBkgFix(str.Atof(), i-1);
else
error = true;
}
}
}
// background ---------------------------------------------
if (iter->fLine.BeginsWith("background", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if ((tokens->GetEntries() < 3) || (tokens->GetEntries() % 2 != 1)) { // odd number (>=3) of entries needed
error = true;
} else {
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if (ival > 0)
param.SetBkgRange(ival, i-1);
else
error = true;
} else {
error = true;
}
}
}
}
// data --------------------------------------------------
if (iter->fLine.BeginsWith("data", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if ((tokens->GetEntries() < 3) || (tokens->GetEntries() % 2 != 1)) { // odd number (>=3) of entries needed
error = true;
} else {
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if (ival > 0)
param.SetDataRange(ival, i-1);
else
error = true;
} else {
error = true;
}
}
}
}
// t0 -----------------------------------------------------
if (iter->fLine.BeginsWith("t0", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() < 2) {
error = true;
} else {
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsFloat()) {
dval = str.Atof();
if (dval >= 0.0)
param.SetT0Bin(dval);
else
error = true;
} else {
error = true;
}
}
}
}
// addt0 -----------------------------------------------------
if (iter->fLine.BeginsWith("addt0", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() < 2) {
error = true;
} else {
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsFloat()) {
dval = str.Atof();
if (dval >= 0.0)
param.SetAddT0Bin(dval, addT0Counter, i-1);
else
error = true;
} else {
error = true;
}
}
}
addT0Counter++;
}
// fit -----------------------------------------------------
if (iter->fLine.BeginsWith("fit ", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() < 3) {
error = true;
} else {
if (iter->fLine.Contains("fgb", TString::kIgnoreCase)) { // fit given in bins, i.e. fit fgb+n0 lgb-n1
// check 1st entry, i.e. fgb[+n0]
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
Ssiz_t idx = str.First("+");
TString numStr = str;
if (idx > -1) { // '+' present hence extract n0
numStr.Remove(0,idx+1);
if (numStr.IsFloat()) {
param.SetFitRangeOffset(numStr.Atoi(), 0);
} else {
error = true;
}
} else { // n0 == 0
param.SetFitRangeOffset(0, 0);
}
// check 2nd entry, i.e. lgb[-n1]
ostr = dynamic_cast<TObjString*>(tokens->At(2));
str = ostr->GetString();
idx = str.First("-");
numStr = str;
if (idx > -1) { // '-' present hence extract n1
numStr.Remove(0,idx+1);
if (numStr.IsFloat()) {
param.SetFitRangeOffset(numStr.Atoi(), 1);
} else {
error = true;
}
} else { // n0 == 0
param.SetFitRangeOffset(0, 0);
}
if (!error)
param.SetFitRangeInBins(true);
} else { // fit given in time, i.e. fit <start> <end>, where <start>, <end> are given as doubles
for (Int_t i=1; i<3; i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsFloat())
param.SetFitRange(str.Atof(), i-1);
else
error = true;
}
}
}
}
// packing --------------------------------------------------
if (iter->fLine.BeginsWith("packing", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() != 2) {
error = true;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if (ival > 0)
param.SetPacking(ival);
else
error = true;
} else {
error = true;
}
}
}
// xy-data -----------------------------------------------
if (iter->fLine.BeginsWith("xy-data", TString::kIgnoreCase)) {
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
if (tokens->GetEntries() != 3) { // xy-data x-label y-label
error = true;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit()) { // xy-data indices given
param.SetXDataIndex(str.Atoi()); // x-index
ostr = dynamic_cast<TObjString*>(tokens->At(2));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if (ival > 0)
param.SetYDataIndex(ival); // y-index
else
error = true;
} else {
error = true;
}
} else { // xy-data labels given
param.SetXDataLabel(str); // x-label
ostr = dynamic_cast<TObjString*>(tokens->At(2));
str = ostr->GetString();
param.SetYDataLabel(str); // y-label
}
}
}
// clean up
if (tokens) {
delete tokens;
tokens = 0;
}
++iter;
}
if (error) {
--iter;
cerr << endl << ">> PMsrHandler::HandleRunEntry: **ERROR** in line " << iter->fLineNo << ":";
cerr << endl << ">> " << iter->fLine.Data();
cerr << endl << ">> RUN block syntax is too complex to print it here. Please check the manual.";
} else { // save last run found
fRuns.push_back(param);
param.CleanUp();
}
return !error;
}
//--------------------------------------------------------------------------
// FilterNumber (private)
//--------------------------------------------------------------------------
/**
* <p>Used to filter numbers from a string of the structure strX, where
* X is a number. The filter string is used to define the offset to X.
* It is used to filter strings like: map1 or fun4. At the moment only
* the filter strings 'map', 'fun', and 'par' are supported.
*
* <b>return:</b>
* - true if successful
* - false otherwise
*
* \param str input string
* \param filter filter string
* \param offset it is used to offset to found number, e.g. strX -> no = X+offset
* \param no filtered number
*/
Bool_t PMsrHandler::FilterNumber(TString str, const Char_t *filter, Int_t offset, Int_t &no)
{
Int_t found, no_found=-1;
// copy str to an ordinary c-like string
Char_t *cstr, filterStr[32];
cstr = new Char_t[str.Sizeof()];
strncpy(cstr, str.Data(), str.Sizeof());
sprintf(filterStr, "%s%%d", filter);
// get number if present
found = sscanf(cstr, filterStr, &no_found);
if (found == 1)
if (no_found < 1000)
no = no_found + offset;
// clean up
if (cstr) {
delete [] cstr;
cstr = 0;
}
if ((no_found < 0) || (no_found > 1000))
return false;
else
return true;
}
//--------------------------------------------------------------------------
// HandleCommandsEntry (private)
//--------------------------------------------------------------------------
/**
* <p> Just copies the COMMAND block lines.
*
* <b>return:</b>
* - true
*
* \param lines is a list of lines containing the command block
*/
Bool_t PMsrHandler::HandleCommandsEntry(PMsrLines &lines)
{
// If msr-file is used for musrFT only, nothing needs to be done here.
if (fFourierOnly)
return true;
PMsrLines::iterator iter;
if (lines.empty()) {
cerr << endl << ">> PMsrHandler::HandleCommandsEntry(): **WARNING**: There is no COMMAND block! Do you really want this?";
cerr << endl;
}
for (iter = lines.begin(); iter != lines.end(); ++iter) {
if (!iter->fLine.BeginsWith("COMMANDS"))
fCommands.push_back(*iter);
}
return true;
}
//--------------------------------------------------------------------------
// InitFourierParameterStructure (private)
//--------------------------------------------------------------------------
/**
* <p>Initializes the Fourier parameter structure.
*
* \param fourier fourier parameters
*/
void PMsrHandler::InitFourierParameterStructure(PMsrFourierStructure &fourier)
{
fourier.fFourierBlockPresent = false; // fourier block present
fourier.fUnits = FOURIER_UNIT_NOT_GIVEN; // fourier untis, default: NOT GIVEN
fourier.fFourierPower = -1; // zero padding, default: -1 = NOT GIVEN
fourier.fDCCorrected = false; // dc-corrected FFT, default: false
fourier.fApodization = FOURIER_APOD_NOT_GIVEN; // apodization, default: NOT GIVEN
fourier.fPlotTag = FOURIER_PLOT_NOT_GIVEN; // initial plot tag, default: NOT GIVEN
fourier.fPhaseParamNo = 0; // initial parameter no = 0 means not a parameter
fourier.fPhase = -999.0; // fourier phase: -999 = NOT GIVEN
for (UInt_t i=0; i<2; i++) {
fourier.fRangeForPhaseCorrection[i] = -1.0; // frequency range for phase correction, default: {-1, -1} = NOT GIVEN
fourier.fPlotRange[i] = -1.0; // fourier plot range, default: {-1, -1} = NOT GIVEN
}
}
//--------------------------------------------------------------------------
// HandleFourierEntry (private)
//--------------------------------------------------------------------------
/**
* <p>Parses the Fourier block of a msr-file.
*
* <b>return:</b>
* - true if successful
* - false otherwise
*
* \param lines is a list of lines containing the fourier parameter block
*/
Bool_t PMsrHandler::HandleFourierEntry(PMsrLines &lines)
{
Bool_t error = false;
if (lines.empty()) // no fourier block present
return true;
PMsrFourierStructure fourier;
InitFourierParameterStructure(fourier);
fourier.fFourierBlockPresent = true;
PMsrLines::iterator iter;
TObjArray *tokens = 0;
TObjString *ostr = 0;
TString str;
Int_t ival;
iter = lines.begin();
while ((iter != lines.end()) && !error) {
// tokenize line
tokens = iter->fLine.Tokenize(" \t");
if (!tokens) {
cerr << endl << ">> PMsrHandler::HandleFourierEntry: **SEVERE ERROR** Couldn't tokenize Parameters in line " << iter->fLineNo;
cerr << endl << endl;
return false;
}
if (iter->fLine.BeginsWith("units", TString::kIgnoreCase)) { // units
if (tokens->GetEntries() < 2) { // units are missing
error = true;
continue;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (!str.CompareTo("gauss", TString::kIgnoreCase)) {
fourier.fUnits = FOURIER_UNIT_GAUSS;
} else if (!str.CompareTo("tesla", TString::kIgnoreCase)) {
fourier.fUnits = FOURIER_UNIT_TESLA;
} else if (!str.CompareTo("mhz", TString::kIgnoreCase)) {
fourier.fUnits = FOURIER_UNIT_FREQ;
} else if (!str.CompareTo("mc/s", TString::kIgnoreCase)) {
fourier.fUnits = FOURIER_UNIT_CYCLES;
} else {
error = true;
continue;
}
}
} else if (iter->fLine.BeginsWith("fourier_power", TString::kIgnoreCase)) { // fourier power (zero padding)
if (tokens->GetEntries() < 2) { // fourier power exponent is missing
error = true;
continue;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if ((ival >= 0) && (ival <= 20)) {
fourier.fFourierPower = ival;
} else { // fourier power out of range
error = true;
continue;
}
} else { // fourier power not a number
error = true;
continue;
}
}
} else if (iter->fLine.BeginsWith("dc-corrected", TString::kIgnoreCase)) { // dc-corrected
if (tokens->GetEntries() < 2) { // dc-corrected tag is missing
error = true;
continue;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (!str.CompareTo("true", TString::kIgnoreCase) || !str.CompareTo("1")) {
fourier.fDCCorrected = true;
} else if (!str.CompareTo("false", TString::kIgnoreCase) || !str.CompareTo("0")) {
fourier.fDCCorrected = false;
} else { // unrecognized dc-corrected tag
error = true;
continue;
}
}
} else if (iter->fLine.BeginsWith("apodization", TString::kIgnoreCase)) { // apodization
if (tokens->GetEntries() < 2) { // apodization tag is missing
error = true;
continue;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (!str.CompareTo("none", TString::kIgnoreCase)) {
fourier.fApodization = FOURIER_APOD_NONE;
} else if (!str.CompareTo("weak", TString::kIgnoreCase)) {
fourier.fApodization = FOURIER_APOD_WEAK;
} else if (!str.CompareTo("medium", TString::kIgnoreCase)) {
fourier.fApodization = FOURIER_APOD_MEDIUM;
} else if (!str.CompareTo("strong", TString::kIgnoreCase)) {
fourier.fApodization = FOURIER_APOD_STRONG;
} else { // unrecognized apodization tag
error = true;
continue;
}
}
} else if (iter->fLine.BeginsWith("plot", TString::kIgnoreCase)) { // plot tag
if (tokens->GetEntries() < 2) { // plot tag is missing
error = true;
continue;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (!str.CompareTo("real", TString::kIgnoreCase)) {
fourier.fPlotTag = FOURIER_PLOT_REAL;
} else if (!str.CompareTo("imag", TString::kIgnoreCase)) {
fourier.fPlotTag = FOURIER_PLOT_IMAG;
} else if (!str.CompareTo("real_and_imag", TString::kIgnoreCase)) {
fourier.fPlotTag = FOURIER_PLOT_REAL_AND_IMAG;
} else if (!str.CompareTo("power", TString::kIgnoreCase)) {
fourier.fPlotTag = FOURIER_PLOT_POWER;
} else if (!str.CompareTo("phase", TString::kIgnoreCase)) {
fourier.fPlotTag = FOURIER_PLOT_PHASE;
} else { // unrecognized plot tag
error = true;
continue;
}
}
} else if (iter->fLine.BeginsWith("phase", TString::kIgnoreCase)) { // phase
if (tokens->GetEntries() < 2) { // phase value is missing
error = true;
continue;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.BeginsWith("par", TString::kIgnoreCase)) { // parameter value
if (fFourierOnly) {
cerr << endl << ">> PMsrHandler::HandleFourierEntry: **WARNING** Found phase parameter for Fourier only.";
cerr << endl << ">> This is currently not supported. Will set the phase to 0." << endl;
fourier.fPhase = 0.0;
} else {
Int_t no = 0;
if (FilterNumber(str, "par", 0, no)) {
// check that the parameter is in range
if ((Int_t)fParam.size() < no) {
error = true;
continue;
}
// keep the parameter number
fourier.fPhaseParamNo = no;
// get parameter value
fourier.fPhase = fParam[no-1].fValue;
} else {
error = true;
continue;
}
}
} else if (str.IsFloat()) { // phase value
fourier.fPhase = str.Atof();
} else {
error = true;
continue;
}
}
} else if (iter->fLine.BeginsWith("range_for_phase_correction", TString::kIgnoreCase)) {
if (tokens->GetEntries() < 3) { // range values are missing
error = true;
continue;
} else {
for (UInt_t i=0; i<2; i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i+1));
str = ostr->GetString();
if (str.IsFloat()) {
fourier.fRangeForPhaseCorrection[i] = str.Atof();
} else {
error = true;
continue;
}
}
}
} else if (iter->fLine.BeginsWith("range", TString::kIgnoreCase)) { // fourier plot range
if (tokens->GetEntries() < 3) { // plot range values are missing
error = true;
continue;
} else {
for (UInt_t i=0; i<2; i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i+1));
str = ostr->GetString();
if (str.IsFloat()) {
fourier.fPlotRange[i] = str.Atof();
} else {
error = true;
continue;
}
}
}
} else if (!iter->fLine.BeginsWith("fourier", TString::kIgnoreCase) && !iter->fLine.BeginsWith("#") &&
!iter->fLine.IsWhitespace() && (iter->fLine.Length() != 0)) { // make
error = true;
continue;
}
// clean up
if (tokens) {
delete tokens;
tokens = 0;
}
++iter;
}
// clean up after error
if (tokens) {
delete tokens;
tokens = 0;
}
if (error) {
cerr << endl << ">> PMsrHandler::HandleFourierEntry: **ERROR** in line " << iter->fLineNo << ":";
cerr << endl;
cerr << endl << ">> " << iter->fLine.Data();
cerr << endl;
cerr << endl << ">> FOURIER block syntax, parameters in [] are optinal:";
cerr << endl;
cerr << endl << ">> FOURIER";
cerr << endl << ">> [units Gauss | MHz | Mc/s]";
cerr << endl << ">> [fourier_power n # n is a number such that zero padding up to 2^n will be used]";
cerr << endl << ">> n=0 means no zero padding";
cerr << endl << ">> 0 <= n <= 20 are allowed values";
cerr << endl << ">> [dc-corrected true | false]";
cerr << endl << ">> [apodization none | weak | medium | strong]";
cerr << endl << ">> [plot real | imag | real_and_imag | power | phase]";
cerr << endl << ">> [phase value]";
cerr << endl << ">> [range_for_phase_correction min max]";
cerr << endl << ">> [range min max]";
cerr << endl;
} else { // save last run found
fFourier = fourier;
}
return !error;
}
//--------------------------------------------------------------------------
// HandlePlotEntry (private)
//--------------------------------------------------------------------------
/**
* <p>Parses the PLOT block of a msr-file.
*
* <b>return:</b>
* - true if successful
* - false otherwise
*
* \param lines is a list of lines containing the plot block
*/
Bool_t PMsrHandler::HandlePlotEntry(PMsrLines &lines)
{
Bool_t error = false;
PMsrPlotStructure param;
PMsrLines::iterator iter1;
PMsrLines::iterator iter2;
TObjArray *tokens = 0;
TObjString *ostr = 0;
TString str;
if (lines.empty()) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry(): **WARNING**: There is no PLOT block! Do you really want this?";
cerr << endl;
}
iter1 = lines.begin();
while ((iter1 != lines.end()) && !error) {
// initialize param structure
param.fPlotType = -1;
param.fLifeTimeCorrection = false;
param.fUseFitRanges = false; // i.e. if not overwritten use the range info of the plot block
param.fLogX = false; // i.e. if not overwritten use linear x-axis
param.fLogY = false; // i.e. if not overwritten use linear y-axis
param.fViewPacking = -1; // i.e. if not overwritten use the packing of the run blocks
param.fRuns.clear();
param.fTmin.clear();
param.fTmax.clear();
param.fYmin.clear();
param.fYmax.clear();
param.fRRFPacking = 0; // i.e. if not overwritten it will not be a valid RRF
param.fRRFFreq = 0.0; // i.e. no RRF whished
param.fRRFUnit = RRF_UNIT_MHz;
param.fRRFPhaseParamNo = 0; // initial parameter no = 0 means not a parameter
param.fRRFPhase = 0.0;
// find next plot if any is present
iter2 = iter1;
++iter2;
for ( ; iter2 != lines.end(); ++iter2) {
if (iter2->fLine.Contains("PLOT"))
break;
}
// handle a single PLOT block
while ((iter1 != iter2) && !error) {
if (iter1->fLine.Contains("PLOT")) { // handle plot header
tokens = iter1->fLine.Tokenize(" \t");
if (!tokens) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo;
cerr << endl << endl;
return false;
}
if (tokens->GetEntries() < 2) { // plot type missing
error = true;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit())
param.fPlotType = str.Atoi();
else
error = true;
}
// clean up
if (tokens) {
delete tokens;
tokens = 0;
}
} else if (iter1->fLine.Contains("lifetimecorrection", TString::kIgnoreCase)) {
param.fLifeTimeCorrection = true;
} else if (iter1->fLine.Contains("runs", TString::kIgnoreCase)) { // handle plot runs
TComplex run;
switch (param.fPlotType) {
case -1:
error = true;
break;
case MSR_PLOT_SINGLE_HISTO: // like: runs 1 5 13
case MSR_PLOT_ASYM:
case MSR_PLOT_NON_MUSR:
case MSR_PLOT_MU_MINUS:
tokens = iter1->fLine.Tokenize(" \t");
if (!tokens) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo;
cerr << endl << endl;
return false;
}
if (tokens->GetEntries() < 2) { // runs missing
error = true;
} else {
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsDigit()) {
run = TComplex(str.Atoi(),-1.0);
param.fRuns.push_back(run);
} else {
error = true;
}
}
}
// clean up
if (tokens) {
delete tokens;
tokens = 0;
}
break;
default:
error = true;
break;
}
} else if (iter1->fLine.Contains("range ", TString::kIgnoreCase)) { // handle plot range
// remove previous entries
param.fTmin.clear();
param.fTmax.clear();
param.fYmin.clear();
param.fYmax.clear();
tokens = iter1->fLine.Tokenize(" \t");
if (!tokens) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo;
cerr << endl << endl;
return false;
}
if ((tokens->GetEntries() != 3) && (tokens->GetEntries() != 5)) {
error = true;
} else {
// handle t_min
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsFloat())
param.fTmin.push_back((Double_t)str.Atof());
else
error = true;
// handle t_max
ostr = dynamic_cast<TObjString*>(tokens->At(2));
str = ostr->GetString();
if (str.IsFloat())
param.fTmax.push_back((Double_t)str.Atof());
else
error = true;
if (tokens->GetEntries() == 5) { // y-axis interval given as well
// handle y_min
ostr = dynamic_cast<TObjString*>(tokens->At(3));
str = ostr->GetString();
if (str.IsFloat())
param.fYmin.push_back((Double_t)str.Atof());
else
error = true;
// handle y_max
ostr = dynamic_cast<TObjString*>(tokens->At(4));
str = ostr->GetString();
if (str.IsFloat())
param.fYmax.push_back((Double_t)str.Atof());
else
error = true;
}
}
// clean up
if (tokens) {
delete tokens;
tokens = 0;
}
} else if (iter1->fLine.Contains("sub_ranges", TString::kIgnoreCase)) {
// remove previous entries
param.fTmin.clear();
param.fTmax.clear();
param.fYmin.clear();
param.fYmax.clear();
tokens = iter1->fLine.Tokenize(" \t");
if (!tokens) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo;
cerr << endl << endl;
return false;
}
if ((tokens->GetEntries() != (Int_t)(2*param.fRuns.size() + 1)) && (tokens->GetEntries() != (Int_t)(2*param.fRuns.size() + 3))) {
error = true;
} else {
// get all the times
for (UInt_t i=0; i<param.fRuns.size(); i++) {
// handle t_min
ostr = dynamic_cast<TObjString*>(tokens->At(2*i+1));
str = ostr->GetString();
if (str.IsFloat())
param.fTmin.push_back((Double_t)str.Atof());
else
error = true;
// handle t_max
ostr = dynamic_cast<TObjString*>(tokens->At(2*i+2));
str = ostr->GetString();
if (str.IsFloat())
param.fTmax.push_back((Double_t)str.Atof());
else
error = true;
}
// get y-range if present
if (tokens->GetEntries() == (Int_t)(2*param.fRuns.size() + 3)) {
// handle y_min
ostr = dynamic_cast<TObjString*>(tokens->At(2*param.fRuns.size()+1));
str = ostr->GetString();
if (str.IsFloat())
param.fYmin.push_back((Double_t)str.Atof());
else
error = true;
// handle y_max
ostr = dynamic_cast<TObjString*>(tokens->At(2*param.fRuns.size()+2));
str = ostr->GetString();
if (str.IsFloat())
param.fYmax.push_back((Double_t)str.Atof());
else
error = true;
}
}
// clean up
if (tokens) {
delete tokens;
tokens = 0;
}
} else if (iter1->fLine.Contains("use_fit_ranges", TString::kIgnoreCase)) {
param.fUseFitRanges = true;
// check if y-ranges are given
tokens = iter1->fLine.Tokenize(" \t");
if (!tokens) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo;
cerr << endl << endl;
return false;
}
if (tokens->GetEntries() == 3) { // i.e. use_fit_ranges ymin ymax
// handle y_min
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsFloat())
param.fYmin.push_back((Double_t)str.Atof());
else
error = true;
// handle y_max
ostr = dynamic_cast<TObjString*>(tokens->At(2));
str = ostr->GetString();
if (str.IsFloat())
param.fYmax.push_back((Double_t)str.Atof());
else
error = true;
}
if ((tokens->GetEntries() != 1) && (tokens->GetEntries() != 3)) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry: **WARNING** use_fit_ranges with undefined additional parameters in line " << iter1->fLineNo;
cerr << endl << ">> Will ignore this PLOT block command line, sorry.";
cerr << endl << ">> Proper syntax: use_fit_ranges [ymin ymax]";
cerr << endl << ">> Found: '" << iter1->fLine.Data() << "'" << endl;
}
// clean up
if (tokens) {
delete tokens;
tokens = 0;
}
} else if (iter1->fLine.Contains("logx", TString::kIgnoreCase)) {
param.fLogX = true;
} else if (iter1->fLine.Contains("logy", TString::kIgnoreCase)) {
param.fLogY = true;
} else if (iter1->fLine.Contains("view_packing", TString::kIgnoreCase)) {
tokens = iter1->fLine.Tokenize(" \t");
if (!tokens) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize view_packing in line " << iter1->fLineNo;
cerr << endl << endl;
return false;
}
if (tokens->GetEntries() != 2) {
error = true;
} else {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit()) {
Int_t val = str.Atoi();
if (val > 0)
param.fViewPacking = val;
else
error = true;
} else {
error = true;
}
}
// clean up
if (tokens) {
delete tokens;
tokens = 0;
}
} else if (iter1->fLine.Contains("rrf_freq", TString::kIgnoreCase)) {
// expected entry: rrf_freq value unit
// allowed units: kHz, MHz, Mc/s, G, T
tokens = iter1->fLine.Tokenize(" \t");
if (!tokens) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize rrf_freq in line " << iter1->fLineNo;
cerr << endl << endl;
return false;
}
if (tokens->GetEntries() != 3) {
error = true;
} else {
// get rrf frequency
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsFloat()) {
param.fRRFFreq = str.Atof();
} else {
error = true;
}
// get unit
ostr = dynamic_cast<TObjString*>(tokens->At(2));
str = ostr->GetString();
if (str.Contains("kHz", TString::kIgnoreCase))
param.fRRFUnit = RRF_UNIT_kHz;
else if (str.Contains("MHz", TString::kIgnoreCase))
param.fRRFUnit = RRF_UNIT_MHz;
else if (str.Contains("Mc/s", TString::kIgnoreCase))
param.fRRFUnit = RRF_UNIT_Mcs;
else if (str.Contains("G", TString::kIgnoreCase))
param.fRRFUnit = RRF_UNIT_G;
else if (str.Contains("T", TString::kIgnoreCase))
param.fRRFUnit = RRF_UNIT_T;
else
error = true;
}
// clean up
if (tokens) {
delete tokens;
tokens = 0;
}
} else if (iter1->fLine.Contains("rrf_phase", TString::kIgnoreCase)) {
// expected entry: rrf_phase value. value given in units of degree. or
// rrf_phase parX. where X is the parameter number, e.g. par3
tokens = iter1->fLine.Tokenize(" \t");
if (!tokens) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize rrf_phase in line " << iter1->fLineNo;
cerr << endl << endl;
return false;
}
if (tokens->GetEntries() != 2) {
error = true;
} else {
// get rrf phase
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsFloat()) {
param.fRRFPhase = str.Atof();
} else {
if (str.BeginsWith("par", TString::kIgnoreCase)) { // parameter value
Int_t no = 0;
if (FilterNumber(str, "par", 0, no)) {
// check that the parameter is in range
if ((Int_t)fParam.size() < no) {
error = true;
} else {
// keep the parameter number in case parX was used
param.fRRFPhaseParamNo = no;
// get parameter value
param.fRRFPhase = fParam[no-1].fValue;
}
}
} else {
error = true;
}
}
}
// clean up
if (tokens) {
delete tokens;
tokens = 0;
}
} else if (iter1->fLine.Contains("rrf_packing", TString::kIgnoreCase)) {
// expected entry: rrf_phase value. value given in units of degree
tokens = iter1->fLine.Tokenize(" \t");
if (!tokens) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize rrf_packing in line " << iter1->fLineNo;
cerr << endl << endl;
return false;
}
if (tokens->GetEntries() != 2) {
error = true;
} else {
// get rrf packing
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.IsDigit()) {
param.fRRFPacking = str.Atoi();
} else {
error = true;
}
}
// clean up
if (tokens) {
delete tokens;
tokens = 0;
}
} else {
error = true;
}
++iter1;
}
// analyze if the plot block is valid
Double_t keep;
if (!error) {
if (param.fRuns.empty()) { // there was no run tag
error = true;
} else { // everything ok
if ((param.fTmin.size() > 0) || (param.fTmax.size() > 0)) { // if range is given, check that it is ordered properly
for (UInt_t i=0; i<param.fTmin.size(); i++) {
if (param.fTmin[i] > param.fTmax[i]) {
keep = param.fTmin[i];
param.fTmin[i] = param.fTmax[i];
param.fTmax[i] = keep;
}
}
}
if ((param.fYmin.size() > 0) || (param.fYmax.size() > 0)) { // if range is given, check that it is ordered properly
for (UInt_t i=0; i<param.fYmin.size(); i++) {
if (param.fYmin[i] > param.fYmax[i]) {
keep = param.fYmin[i];
param.fYmin[i] = param.fYmax[i];
param.fYmax[i] = keep;
}
}
}
// check RRF entries
if (param.fRRFFreq != 0.0) {
if (param.fRRFPacking == 0) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry(): **ERROR** found RRF frequency but no required RRF packing.";
cerr << endl << ">> Will ignore the RRF option.";
cerr << endl;
param.fRRFFreq = 0.0;
}
}
// check if runs listed in the plot block indeed to exist
for (UInt_t i=0; i<param.fRuns.size(); i++) {
if (param.fRuns[i] > static_cast<Int_t>(fRuns.size())) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry(): **WARNING** found plot run number " << param.fRuns[i] << ".";
cerr << endl << ">> There are only " << fRuns.size() << " runs present, will ignore this run.";
cerr << endl;
param.fRuns.erase(param.fRuns.begin()+i);
i--;
}
if (param.fRuns[i] == 0) {
cerr << endl << ">> PMsrHandler::HandlePlotEntry(): **WARNING** found plot run number 0.";
cerr << endl << ">> Pot number needs to be > 0. Will ignore this entry.";
cerr << endl;
param.fRuns.erase(param.fRuns.begin()+i);
i--;
}
}
if (param.fRuns.size() > 0) {
fPlots.push_back(param);
} else {
cerr << endl << ">> PMsrHandler::HandlePlotEntry: **ERROR** no valid PLOT block entries, will ignore the entire PLOT block.";
cerr << endl;
}
}
}
if (fPlots.size() == 0) {
error = true;
cerr << endl << ">> PMsrHandler::HandlePlotEntry: **ERROR** no valid PLOT block at all present. Fix this first!";
cerr << endl;
}
if (error) { // print error message
--iter1;
cerr << endl << ">> PMsrHandler::HandlePlotEntry: **ERROR** in line " << iter1->fLineNo << ": " << iter1->fLine.Data();
cerr << endl << ">> A PLOT block needs to have the following structure:";
cerr << endl;
cerr << endl << ">> PLOT <plot_type>";
cerr << endl << ">> runs <run_list>";
cerr << endl << ">> [range tmin tmax [ymin ymax]]";
cerr << endl << ">> [sub_ranges tmin1 tmax1 tmin2 tmax2 ... tminN tmaxN [ymin ymax]";
cerr << endl << ">> [logx | logy]";
cerr << endl << ">> [use_fit_ranges [ymin ymax]]";
cerr << endl << ">> [view_packing n]";
cerr << endl;
cerr << endl << ">> where <plot_type> is: 0=single histo asym,";
cerr << endl << ">> 2=forward-backward asym,";
cerr << endl << ">> 4=mu minus single histo,";
cerr << endl << ">> 8=non muSR.";
cerr << endl << ">> <run_list> is the list of runs, e.g. runs 1 3";
cerr << endl << ">> range is optional";
cerr << endl << ">> sub_ranges (if present) will plot the N given runs each on its own sub-range";
cerr << endl << ">> logx, logy (if present) will present the x-, y-axis in log-scale";
cerr << endl << ">> use_fit_ranges (if present) will plot each run on its fit-range";
cerr << endl << ">> view_packing n (if present) will bin all data by n (> 0) rather than the binning of the fit";
cerr << endl;
}
param.fRuns.clear();
}
return !error;
}
//--------------------------------------------------------------------------
// HandleStatisticEntry (private)
//--------------------------------------------------------------------------
/**
* <p>Handles the STATISTIC block of a msr-file.
*
* <b>return:</b>
* - true if successful
* - false otherwise
*
* \param lines is a list of lines containing the statistic block
*/
Bool_t PMsrHandler::HandleStatisticEntry(PMsrLines &lines)
{
// If msr-file is used for musrFT only, nothing needs to be done here.
if (fFourierOnly)
return true;
if (lines.empty()) {
cerr << endl << ">> PMsrHandler::HandleStatisticEntry: **WARNING** There is no STATISTIC block! Do you really want this?";
cerr << endl;
fStatistic.fValid = false;
return true;
}
Char_t str[128];
Char_t date[128];
Char_t time[128];
Int_t status;
Double_t dval;
UInt_t ival;
TString tstr;
for (UInt_t i=0; i<lines.size(); i++) {
// check if the statistic block line is illegal
tstr = lines[i].fLine;
tstr.Remove(TString::kLeading, ' ');
if (tstr.Length() > 0) {
if (!tstr.BeginsWith("#") && !tstr.BeginsWith("STATISTIC") && !tstr.BeginsWith("chisq") &&
!tstr.BeginsWith("maxLH") && !tstr.BeginsWith("*** FIT DID NOT CONVERGE ***") &&
!tstr.BeginsWith("expected chisq") && !tstr.BeginsWith("run block")) {
cerr << endl << ">> PMsrHandler::HandleStatisticEntry: **SYNTAX ERROR** in line " << lines[i].fLineNo;
cerr << endl << ">> '" << lines[i].fLine.Data() << "'";
cerr << endl << ">> not a valid STATISTIC block line";
cerr << endl << ">> If you do not understand this, just remove the STATISTIC block, musrfit will recreate after fitting";
cerr << endl << endl;
return false;
}
}
// filter date and chisq etc from strings
// extract date and time
if (lines[i].fLine.Contains("STATISTIC")) {
status = sscanf(lines[i].fLine.Data(), "STATISTIC --- %s%s", date, time);
if (status == 2) {
fStatistic.fDate = TString(date)+TString(", ")+TString(time);
} else {
fStatistic.fDate = TString("????-??-??, ??:??:??");
}
}
// extract chisq
if (lines[i].fLine.Contains("chisq =")) {
if (lines[i].fLine.Contains("expected")) { // expected chisq
strncpy(str, lines[i].fLine.Data(), sizeof(str));
status = sscanf(str+lines[i].fLine.Index("chisq = ")+8, "%lf", &dval);
if (status == 1) {
fStatistic.fMinExpected = dval;
} else {
fStatistic.fMinExpected = -1.0;
}
} else { // chisq
fStatistic.fValid = true;
strncpy(str, lines[i].fLine.Data(), sizeof(str));
status = sscanf(str+lines[i].fLine.Index("chisq = ")+8, "%lf", &dval);
if (status == 1) {
fStatistic.fMin = dval;
} else {
fStatistic.fMin = -1.0;
}
}
}
// extract maxLH
if (lines[i].fLine.Contains("maxLH =")) {
fStatistic.fValid = true;
strncpy(str, lines[i].fLine.Data(), sizeof(str));
status = sscanf(str+lines[i].fLine.Index("maxLH = ")+8, "%lf", &dval);
if (status == 1) {
fStatistic.fMin = dval;
} else {
fStatistic.fMin = -1.0;
}
}
// extract NDF
if (lines[i].fLine.Contains(", NDF =")) {
strncpy(str, lines[i].fLine.Data(), sizeof(str));
status = sscanf(str+lines[i].fLine.Index(", NDF = ")+8, "%u", &ival);
if (status == 1) {
fStatistic.fNdf = ival;
} else {
fStatistic.fNdf = 0;
}
}
// keep string
fStatistic.fStatLines.push_back(lines[i]);
}
return true;
}
//--------------------------------------------------------------------------
// GetNoOfFitParameters (public)
//--------------------------------------------------------------------------
/**
* <p>Calculate the number of fit parameters.
*
* \param idx run block index
*/
UInt_t PMsrHandler::GetNoOfFitParameters(UInt_t idx)
{
UInt_t noOfFitParameters = 0;
PUIntVector paramVector;
PUIntVector funVector;
PUIntVector mapVector;
TObjArray *tokens = 0;
TObjString *ostr = 0;
TString str;
UInt_t k, dval;
Int_t status, pos;
// check that idx is valid
if (idx >= fRuns.size()) {
cerr << endl << ">> PMsrHandler::GetNoOfFitParameters() **ERROR** idx=" << idx << ", out of range fRuns.size()=" << fRuns.size();
cerr << endl;
return 0;
}
// get N0 parameter, possible parameter number or function (single histo fit)
if (fRuns[idx].GetNormParamNo() != -1) {
if (fRuns[idx].GetNormParamNo() < MSR_PARAM_FUN_OFFSET) // parameter
paramVector.push_back(fRuns[idx].GetNormParamNo());
else // function
funVector.push_back(fRuns[idx].GetNormParamNo() - MSR_PARAM_FUN_OFFSET);
}
// get background parameter, for the case the background is fitted (single histo fit)
if (fRuns[idx].GetBkgFitParamNo() != -1)
paramVector.push_back(fRuns[idx].GetBkgFitParamNo());
// get alpha parameter if present (asymmetry fit)
if (fRuns[idx].GetAlphaParamNo() != -1)
paramVector.push_back(fRuns[idx].GetAlphaParamNo());
// get beta parameter if present (asymmetry fit)
if (fRuns[idx].GetBetaParamNo() != -1)
paramVector.push_back(fRuns[idx].GetBetaParamNo());
// go through the theory block and collect parameters
// possible entries: number -> parameter, fun<number> -> function, map<number> -> maps
for (UInt_t i=0; i<fTheory.size(); i++) {
// remove potential comments
str = fTheory[i].fLine;
pos = str.Index('#');
if (pos >= 0)
str.Resize(pos);
// tokenize
tokens = str.Tokenize(" \t");
if (!tokens) {
mapVector.clear();
funVector.clear();
paramVector.clear();
return 0;
}
for (Int_t j=0; j<tokens->GetEntries(); j++) {
ostr = dynamic_cast<TObjString*>(tokens->At(j));
str = ostr->GetString();
// check for parameter number
if (str.IsDigit()) {
dval = str.Atoi();
paramVector.push_back(dval);
}
// check for map
if (str.Contains("map")) {
status = sscanf(str.Data(), "map%d", &dval);
if (status == 1) {
mapVector.push_back(dval);
}
}
// check for function
if (str.Contains("fun")) {
status = sscanf(str.Data(), "fun%d", &dval);
if (status == 1) {
funVector.push_back(dval);
}
}
}
delete tokens;
tokens = 0;
}
// go through the function block and collect parameters
for (UInt_t i=0; i<funVector.size(); i++) {
// find the proper function in the function block
for (k=0; k<fFunctions.size(); k++) {
status = sscanf(fFunctions[k].fLine.Data(), "fun%d", &dval);
if (status == 1) {
if (dval == funVector[i])
break;
}
}
// check if everything has been found at all
if (k == fFunctions.size()) {
cerr << endl << ">> PMsrHandler::GetNoOfFitParameters() **ERROR** couldn't find fun" << funVector[i];
cerr << endl << endl;
// clean up
mapVector.clear();
funVector.clear();
paramVector.clear();
return 0;
}
// remove potential comments
str = fFunctions[k].fLine;
pos = str.Index('#');
if (pos >= 0)
str.Resize(pos);
// tokenize
tokens = str.Tokenize(" \t");
if (!tokens) {
mapVector.clear();
funVector.clear();
paramVector.clear();
return 0;
}
// filter out parameters and maps
for (Int_t j=0; j<tokens->GetEntries(); j++) {
ostr = dynamic_cast<TObjString*>(tokens->At(j));
str = ostr->GetString();
// check for parameter
if (str.BeginsWith("par")) {
status = sscanf(str.Data(), "par%d", &dval);
if (status == 1)
paramVector.push_back(dval);
}
// check for map
if (str.BeginsWith("map")) {
status = sscanf(str.Data(), "map%d", &dval);
if (status == 1)
mapVector.push_back(dval);
}
}
}
// go through the map and collect parameters
for (UInt_t i=0; i<mapVector.size(); i++) {
paramVector.push_back(fRuns[idx].GetMap(mapVector[i]-1));
}
// eliminated multiple identical entries in paramVector
PUIntVector param;
param.push_back(paramVector[0]);
for (UInt_t i=0; i<paramVector.size(); i++) {
for (k=0; k<param.size(); k++) {
if (param[k] == paramVector[i])
break;
}
if (k == param.size())
param.push_back(paramVector[i]);
}
// calculate the number of fit parameters with step != 0
for (UInt_t i=0; i<param.size(); i++) {
if (fParam[param[i]-1].fStep != 0.0)
noOfFitParameters++;
}
// cleanup
param.clear();
mapVector.clear();
funVector.clear();
paramVector.clear();
return noOfFitParameters;
}
//--------------------------------------------------------------------------
// FillParameterInUse (private)
//--------------------------------------------------------------------------
/**
* <p>Fills the fParamInUse vector. An element of the vector will be 0 if the fit parameter
* is <b>not</b> used at all, otherwise it will be > 0.
*
* \param theory msr-file THEROY block lines
* \param funcs msr-file FUNCTIONS block lines
* \param run msr-file RUN blocks lines
*/
void PMsrHandler::FillParameterInUse(PMsrLines &theory, PMsrLines &funcs, PMsrLines &run)
{
PIntVector map;
PIntVector fun;
PMsrLines::iterator iter;
TObjArray *tokens = 0;
TObjString *ostr = 0;
TString str;
Int_t ival, funNo;
// create and initialize fParamInUse vector
for (UInt_t i=0; i<fParam.size(); i++)
fParamInUse.push_back(0);
// go through all the theory lines ------------------------------------
for (iter = theory.begin(); iter != theory.end(); ++iter) {
// remove potential comments
str = iter->fLine;
if (str.First('#') != -1)
str.Resize(str.First('#'));
// everything to lower case
str.ToLower();
// tokenize string
tokens = str.Tokenize(" \t");
if (!tokens)
continue;
// filter param no, map no, and fun no
for (Int_t i=0; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsDigit()) { // parameter number
ival = str.Atoi();
if ((ival > 0) && (ival < (Int_t)fParam.size()+1)) {
fParamInUse[ival-1]++;
}
} else if (str.Contains("map")) { // map
if (FilterNumber(str, "map", MSR_PARAM_MAP_OFFSET, ival))
map.push_back(ival-MSR_PARAM_MAP_OFFSET);
} else if (str.Contains("fun")) { // fun
if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, ival))
fun.push_back(ival-MSR_PARAM_FUN_OFFSET);
}
}
// delete tokens
if (tokens) {
delete tokens;
tokens = 0;
}
}
// go through all the function lines: 1st time -----------------------------
for (iter = funcs.begin(); iter != funcs.end(); ++iter) {
// remove potential comments
str = iter->fLine;
if (str.First('#') != -1)
str.Resize(str.First('#'));
// everything to lower case
str.ToLower();
tokens = str.Tokenize(" /t");
if (!tokens)
continue;
// filter fun number
ostr = dynamic_cast<TObjString*>(tokens->At(0));
str = ostr->GetString();
if (!FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, funNo))
continue;
funNo -= MSR_PARAM_FUN_OFFSET;
// check if fun number is used, and if yes, filter parameter numbers and maps
TString sstr;
for (UInt_t i=0; i<fun.size(); i++) {
if (fun[i] == funNo) { // function number found
// filter for parX
sstr = iter->fLine;
Char_t sval[128];
while (sstr.Index("par") != -1) {
memset(sval, 0, sizeof(sval));
sstr = &sstr[sstr.Index("par")+3]; // trunc sstr
for (Int_t j=0; j<sstr.Sizeof(); j++) {
if (!isdigit(sstr[j]))
break;
sval[j] = sstr[j];
}
sscanf(sval, "%d", &ival);
fParamInUse[ival-1]++;
}
// filter for mapX
sstr = iter->fLine;
while (sstr.Index("map") != -1) {
memset(sval, 0, sizeof(sval));
sstr = &sstr[sstr.Index("map")+3]; // trunc sstr
for (Int_t j=0; j<sstr.Sizeof(); j++) {
if (!isdigit(sstr[j]))
break;
sval[j] = sstr[j];
}
sscanf(sval, "%d", &ival);
// check if map value already in map, otherwise add it
if (ival > 0) {
UInt_t pos;
for (pos=0; pos<map.size(); pos++) {
if (ival == map[pos])
break;
}
if (pos == map.size()) { // new map value
map.push_back(ival);
}
}
}
break; // since function was found, break the loop
}
}
// delete tokens
if (tokens) {
delete tokens;
tokens = 0;
}
}
// go through all the run block lines -------------------------------------
for (iter = run.begin(); iter != run.end(); ++iter) {
// remove potential comments
str = iter->fLine;
if (str.First('#') != -1)
str.Resize(str.First('#'));
// everything to lower case
str.ToLower();
// handle everything but the maps
if (str.Contains("alpha") || str.Contains("beta") ||
str.Contains("alpha2") || str.Contains("beta2") ||
str.Contains("norm") || str.Contains("backgr.fit") ||
str.Contains("lifetime ")) {
// tokenize string
tokens = str.Tokenize(" \t");
if (!tokens)
continue;
if (tokens->GetEntries()<2)
continue;
ostr = dynamic_cast<TObjString*>(tokens->At(1)); // parameter number or function
str = ostr->GetString();
// check if parameter number
if (str.IsDigit()) {
ival = str.Atoi();
fParamInUse[ival-1]++;
}
// check if fun
if (str.Contains("fun")) {
if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, ival)) {
fun.push_back(ival-MSR_PARAM_FUN_OFFSET);
}
}
// delete tokens
if (tokens) {
delete tokens;
tokens = 0;
}
}
// handle the maps
if (str.Contains("map")) {
// tokenize string
tokens = str.Tokenize(" \t");
if (!tokens)
continue;
// get the parameter number via map
for (UInt_t i=0; i<map.size(); i++) {
if (map[i] == 0)
continue;
if (map[i] < tokens->GetEntries()) {
ostr = dynamic_cast<TObjString*>(tokens->At(map[i]));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if (ival > 0) {
fParamInUse[ival-1]++; // this is OK since map is ranging from 1 ..
}
}
}
}
// delete tokens
if (tokens) {
delete tokens;
tokens = 0;
}
}
}
// go through all the function lines: 2nd time -----------------------------
for (iter = funcs.begin(); iter != funcs.end(); ++iter) {
// remove potential comments
str = iter->fLine;
if (str.First('#') != -1)
str.Resize(str.First('#'));
// everything to lower case
str.ToLower();
tokens = str.Tokenize(" /t");
if (!tokens)
continue;
// filter fun number
ostr = dynamic_cast<TObjString*>(tokens->At(0));
str = ostr->GetString();
if (!FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, funNo))
continue;
funNo -= MSR_PARAM_FUN_OFFSET;
// check if fun number is used, and if yes, filter parameter numbers and maps
TString sstr;
for (UInt_t i=0; i<fun.size(); i++) {
if (fun[i] == funNo) { // function number found
// filter for parX
sstr = iter->fLine;
Char_t sval[128];
while (sstr.Index("par") != -1) {
memset(sval, 0, sizeof(sval));
sstr = &sstr[sstr.Index("par")+3]; // trunc sstr
for (Int_t j=0; j<sstr.Sizeof(); j++) {
if (!isdigit(sstr[j]))
break;
sval[j] = sstr[j];
}
sscanf(sval, "%d", &ival);
fParamInUse[ival-1]++;
}
// filter for mapX
sstr = iter->fLine;
while (sstr.Index("map") != -1) {
memset(sval, 0, sizeof(sval));
sstr = &sstr[sstr.Index("map")+3]; // trunc sstr
for (Int_t j=0; j<sstr.Sizeof(); j++) {
if (!isdigit(sstr[j]))
break;
sval[j] = sstr[j];
}
sscanf(sval, "%d", &ival);
// check if map value already in map, otherwise add it
if (ival > 0) {
UInt_t pos;
for (pos=0; pos<map.size(); pos++) {
if (ival == map[pos])
break;
}
if ((UInt_t)pos == map.size()) { // new map value
map.push_back(ival);
}
}
}
}
}
// delete tokens
if (tokens) {
delete tokens;
tokens = 0;
}
}
// go through all the run block lines 2nd time to filter remaining maps
for (iter = run.begin(); iter != run.end(); ++iter) {
// remove potential comments
str = iter->fLine;
if (str.First('#') != -1)
str.Resize(str.First('#'));
// everything to lower case
str.ToLower();
// handle the maps
if (str.Contains("map")) {
// tokenize string
tokens = str.Tokenize(" \t");
if (!tokens)
continue;
// get the parameter number via map
for (UInt_t i=0; i<map.size(); i++) {
if (map[i] == 0)
continue;
if (map[i] < tokens->GetEntries()) {
ostr = dynamic_cast<TObjString*>(tokens->At(map[i]));
str = ostr->GetString();
if (str.IsDigit()) {
ival = str.Atoi();
if (ival > 0) {
fParamInUse[ival-1]++; // this is OK since map is ranging from 1 ..
}
}
}
}
// delete tokens
if (tokens) {
delete tokens;
tokens = 0;
}
}
}
// if unused parameters are present, set the step value to 0.0
for (UInt_t i=0; i<fParam.size(); i++) {
if (!ParameterInUse(i)) {
if (fParam[i].fStep != 0.0) {
cerr << endl << ">> **WARNING** : Parameter No " << i+1 << " is not used at all, will fix it" << endl;
fParam[i].fStep = 0.0;
}
}
}
// clean up
map.clear();
fun.clear();
}
//--------------------------------------------------------------------------
// CheckRunBlockIntegrity (public)
//--------------------------------------------------------------------------
/**
* <p>Checks the consistency of each RUN block, i.e. are the necessary parameters
* set and present, etc.
*
* <b>return:</b>
* - true if the RUN blocks fulfill the minimal requirements.
* - false otherwise
*/
Bool_t PMsrHandler::CheckRunBlockIntegrity()
{
// go through all the present RUN blocks
Int_t fitType = 0;
for (UInt_t i=0; i<fRuns.size(); i++) {
// check if fittype is defined
fitType = fRuns[i].GetFitType();
if (fitType == -1) { // fittype not given in the run block
fitType = fGlobal.GetFitType();
if (fitType == -1) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** fittype is neither defined in RUN block number " << i+1 << ", nor in the GLOBAL block." << endl;
return false;
}
}
// check for the different fittypes differently
switch (fitType) {
case PRUN_SINGLE_HISTO:
// check of norm is present
if ((fRuns[i].GetNormParamNo() == -1) && !fFourierOnly) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> Norm parameter number not defined. Necessary for single histogram fits." << endl;
return false;
}
if (!fFourierOnly) { // next check NOT needed for Fourier only
// check if norm parameter is given that it is either a valid function of a fit parameter present
if (fRuns[i].GetNormParamNo() < MSR_PARAM_FUN_OFFSET) { // parameter number
// check that norm parameter number is not larger than the number of parameters
if (fRuns[i].GetNormParamNo() > static_cast<Int_t>(fParam.size())) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> Norm parameter number " << fRuns[i].GetNormParamNo() << " is larger than the number of fit parameters (" << fParam.size() << ").";
cerr << endl << ">> Consider to check the manual ;-)" << endl;
return false;
}
} else { // function norm
if (fRuns[i].GetNormParamNo()-MSR_PARAM_FUN_OFFSET > GetNoOfFuncs()) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> Norm parameter function number " << fRuns[i].GetNormParamNo()-MSR_PARAM_FUN_OFFSET << " is larger than the number of functions (" << GetNoOfFuncs() << ").";
cerr << endl << ">> Consider to check the manual ;-)" << endl;
return false;
}
}
}
// check that there is a forward parameter number
if (fRuns[i].GetForwardHistoNo() == -1) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> forward parameter number not defined. Necessary for single histogram fits." << endl;
return false;
}
if ((fRuns[i].GetNormParamNo() > static_cast<Int_t>(fParam.size())) && !fFourierOnly) {
// check if forward histogram number is a function
if (fRuns[i].GetNormParamNo() - MSR_PARAM_FUN_OFFSET > static_cast<Int_t>(fParam.size())) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> forward histogram number " << fRuns[i].GetNormParamNo() << " is larger than the number of fit parameters (" << fParam.size() << ").";
cerr << endl << ">> Consider to check the manual ;-)" << endl;
return false;
}
}
// check fit range
if (!fRuns[i].IsFitRangeInBin() && !fFourierOnly) { // fit range given as times in usec (RUN block)
if ((fRuns[i].GetFitRange(0) == PMUSR_UNDEFINED) || (fRuns[i].GetFitRange(1) == PMUSR_UNDEFINED)) { // check fit range in RUN block
if (!fGlobal.IsFitRangeInBin()) { // fit range given as times in usec (GLOBAL block)
if ((fGlobal.GetFitRange(0) == PMUSR_UNDEFINED) || (fGlobal.GetFitRange(1) == PMUSR_UNDEFINED)) { // check fit range in GLOBAL block
cerr << endl << "PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << " Fit range is not defined. Necessary for single histogram fits." << endl;
return false;
}
}
}
}
// check number of T0's provided
if ((fRuns[i].GetT0BinSize() > fRuns[i].GetForwardHistoNoSize()) &&
(fGlobal.GetT0BinSize() > fRuns[i].GetForwardHistoNoSize())) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> Found " << fRuns[i].GetT0BinSize() << " T0 entries. Expecting only " << fRuns[i].GetForwardHistoNoSize() << ". Needs to be fixed." << endl;
cerr << endl << ">> In GLOBAL block: " << fGlobal.GetT0BinSize() << " T0 entries. Expecting only " << fRuns[i].GetForwardHistoNoSize() << ". Needs to be fixed." << endl;
return false;
}
// check packing
if ((fRuns[i].GetPacking() == -1) && (fGlobal.GetPacking() == -1)) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **WARNING** in RUN block number " << i+1;
cerr << endl << ">> Packing is neither defined here, nor in the GLOBAL block, will set it to 1." << endl;
fRuns[i].SetPacking(1);
}
break;
case PRUN_ASYMMETRY:
// check alpha
if ((fRuns[i].GetAlphaParamNo() == -1) && !fFourierOnly) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> alpha parameter number missing which is needed for an asymmetry fit.";
cerr << endl << ">> Consider to check the manual ;-)" << endl;
return false;
}
// check that there is a forward parameter number
if (fRuns[i].GetForwardHistoNo() == -1) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> forward histogram number not defined. Necessary for asymmetry fits." << endl;
return false;
}
// check that there is a backward parameter number
if (fRuns[i].GetBackwardHistoNo() == -1) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> backward histogram number not defined. Necessary for asymmetry fits." << endl;
return false;
}
// check fit range
if (!fRuns[i].IsFitRangeInBin()) { // fit range given as times in usec
if ((fRuns[i].GetFitRange(0) == PMUSR_UNDEFINED) || (fRuns[i].GetFitRange(1) == PMUSR_UNDEFINED)) {
if ((fGlobal.GetFitRange(0) == PMUSR_UNDEFINED) || (fGlobal.GetFitRange(1) == PMUSR_UNDEFINED)) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> Fit range is not defined, also NOT present in the GLOBAL block. Necessary for asymmetry fits." << endl;
return false;
}
}
}
// check number of T0's provided
if ((fRuns[i].GetT0BinSize() > 2*fRuns[i].GetForwardHistoNoSize()) &&
(fGlobal.GetT0BinSize() > 2*fRuns[i].GetForwardHistoNoSize())) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> Found " << fRuns[i].GetT0BinSize() << " T0 entries. Expecting only " << 2*fRuns[i].GetForwardHistoNoSize() << " in forward. Needs to be fixed." << endl;
cerr << endl << ">> In GLOBAL block: " << fGlobal.GetT0BinSize() << " T0 entries. Expecting only " << 2*fRuns[i].GetForwardHistoNoSize() << ". Needs to be fixed." << endl;
return false;
}
if ((fRuns[i].GetT0BinSize() > 2*fRuns[i].GetBackwardHistoNoSize()) &&
(fGlobal.GetT0BinSize() > 2*fRuns[i].GetBackwardHistoNoSize())) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> Found " << fRuns[i].GetT0BinSize() << " T0 entries. Expecting only " << 2*fRuns[i].GetBackwardHistoNoSize() << " in backward. Needs to be fixed." << endl;
cerr << endl << ">> In GLOBAL block: " << fGlobal.GetT0BinSize() << " T0 entries. Expecting only " << 2*fRuns[i].GetBackwardHistoNoSize() << ". Needs to be fixed." << endl;
return false;
}
// check packing
if ((fRuns[i].GetPacking() == -1) && (fGlobal.GetPacking() == -1)) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **WARNING** in RUN block number " << i+1;
cerr << endl << ">> Packing is neither defined here, nor in the GLOBAL block, will set it to 1." << endl;
fRuns[i].SetPacking(1);
}
break;
case PRUN_MU_MINUS:
// needs eventually to be implemented
break;
case PRUN_NON_MUSR:
// check xy-data
if ((fRuns[i].GetXDataIndex() == -1) && (fRuns[i].GetXDataLabel()->Length() == 0)) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> xy-data is missing. Necessary for non muSR fits." << endl;
return false;
}
// check fit range
if ((fRuns[i].GetFitRange(0) == PMUSR_UNDEFINED) || (fRuns[i].GetFitRange(1) == PMUSR_UNDEFINED)) {
if ((fGlobal.GetFitRange(0) == PMUSR_UNDEFINED) || (fGlobal.GetFitRange(1) == PMUSR_UNDEFINED)) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
cerr << endl << ">> Fit range is not defined, neither in the RUN block, nor in the GLOBAL block.";
cerr << endl << ">> Necessary for non muSR fits." << endl;
return false;
}
}
// check packing
if (fRuns[i].GetPacking() == -1) {
if (fGlobal.GetPacking() == -1) {
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **WARNING** in RUN block number " << i+1;
cerr << endl << ">> Packing is not defined, will set it to 1." << endl;
fRuns[i].SetPacking(1);
}
}
break;
default:
cerr << endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** fittype " << fitType << " undefined." << endl;
return false;
break;
}
}
return true;
}
//--------------------------------------------------------------------------
// CheckUniquenessOfParamNames (public)
//--------------------------------------------------------------------------
/**
* <p>Checks if all the fit parameters are unique. If not parX, parY will show
* the first occurence of equal fit parameter names.
*
* <b>return:</b>
* - true if the fit parameter names are unique.
* - false otherwise
*
* \param parX index of the 1st fit parameter name for which there is a counter part.
* \param parY index of the counter part fit parameter name.
*/
Bool_t PMsrHandler::CheckUniquenessOfParamNames(UInt_t &parX, UInt_t &parY)
{
Bool_t unique = true;
for (UInt_t i=0; i<fParam.size()-1; i++) {
for (UInt_t j=i+1; j<fParam.size(); j++) {
if (fParam[i].fName.CompareTo(fParam[j].fName) == 0) { // equal
unique = false;
parX = i;
parY = j;
break;
}
}
}
return unique;
}
//--------------------------------------------------------------------------
// CheckMaps (public)
//--------------------------------------------------------------------------
/**
* <p>Checks if map entries found in the theory- or function-block are also
* present in the run-block.
*
* <b>return:</b>
* - true if maps or OK
* - false otherwise
*/
Bool_t PMsrHandler::CheckMaps()
{
Bool_t result = true;
PIntVector mapVec;
PIntVector mapBlock;
PIntVector mapLineNo;
TObjArray *tokens = 0;
TObjString *ostr = 0;
TString str;
Int_t no;
// check if map is present in the theory-block
for (UInt_t i=0; i<fTheory.size(); i++) {
if (fTheory[i].fLine.Contains("map", TString::kIgnoreCase)) {
// map found hence filter out map number
tokens = fTheory[i].fLine.Tokenize(" \t");
for (Int_t j=0; j<tokens->GetEntries(); j++) {
ostr = dynamic_cast<TObjString*>(tokens->At(j));
str = ostr->GetString();
if (str.Contains("map", TString::kIgnoreCase)) {
if (FilterNumber(str, "map", MSR_PARAM_MAP_OFFSET, no)) {
mapVec.push_back(no);
mapBlock.push_back(0); // 0 = theory-block
mapLineNo.push_back(fTheory[i].fLineNo);
}
}
}
// clean up tokens
if (tokens) {
delete tokens;
tokens = 0;
}
}
}
// check if map is present in the function-block
for (UInt_t i=0; i<fFunctions.size(); i++) {
if (fFunctions[i].fLine.Contains("map", TString::kIgnoreCase)) {
// map found hence filter out map number
tokens = fFunctions[i].fLine.Tokenize(" \t");
for (Int_t j=0; j<tokens->GetEntries(); j++) {
ostr = dynamic_cast<TObjString*>(tokens->At(j));
str = ostr->GetString();
if (str.Contains("map", TString::kIgnoreCase)) {
if (FilterNumber(str, "map", MSR_PARAM_MAP_OFFSET, no)) {
mapVec.push_back(no);
mapBlock.push_back(1); // 1 = theory-block
mapLineNo.push_back(fTheory[i].fLineNo);
}
}
}
// clean up tokens
if (tokens) {
delete tokens;
tokens = 0;
}
}
}
// check if present maps are found in the run-block
Bool_t found;
for (UInt_t i=0; i<mapVec.size(); i++) { // loop over found maps in theory- and function-block
found = false;
for (UInt_t j=0; j<fRuns.size(); j++) { // loop over all run-blocks
if ((mapVec[i]-MSR_PARAM_MAP_OFFSET-1 < (Int_t)fRuns[j].GetMap()->size()) &&
(mapVec[i]-MSR_PARAM_MAP_OFFSET-1 >= 0)) { // map value smaller than run-block map length
if (fRuns[j].GetMap(mapVec[i]-MSR_PARAM_MAP_OFFSET-1) != 0) { // map value in the run-block != 0
found = true;
break;
}
}
}
if (!found) { // map not found
result = false;
cerr << endl << ">> PMsrHandler::CheckMaps: **ERROR** map" << mapVec[i]-MSR_PARAM_MAP_OFFSET << " found in the ";
if (mapBlock[i] == 0)
cerr << "theory-block ";
else
cerr << "functions-block ";
cerr << "in line " << mapLineNo[i] << " is not present in the run-block!";
cerr << endl;
if (mapVec[i]-MSR_PARAM_MAP_OFFSET == 0) {
cerr << endl << ">> by the way: map must be > 0 ...";
cerr << endl;
}
}
}
// clean up
mapVec.clear();
mapBlock.clear();
mapLineNo.clear();
return result;
}
//--------------------------------------------------------------------------
// CheckFuncs (public)
//--------------------------------------------------------------------------
/**
* <p>Checks if fun entries found in the theory- and run-block are also
* present in the functions-block.
*
* <b>return:</b>
* - true if fun entries or present in the FUNCTIONS block
* - false otherwise
*/
Bool_t PMsrHandler::CheckFuncs()
{
Bool_t result = true;
if (fFourierOnly)
return result;
PIntVector funVec;
PIntVector funBlock;
PIntVector funLineBlockNo;
TObjArray *tokens = 0;
TObjString *ostr = 0;
TString str;
Int_t no;
// check if func is present in the theory-block
for (UInt_t i=0; i<fTheory.size(); i++) {
if (fTheory[i].fLine.Contains("fun", TString::kIgnoreCase)) {
// func found hence filter out func number
tokens = fTheory[i].fLine.Tokenize(" \t");
for (Int_t j=0; j<tokens->GetEntries(); j++) {
ostr = dynamic_cast<TObjString*>(tokens->At(j));
str = ostr->GetString();
if (str.Contains("fun", TString::kIgnoreCase)) {
if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, no)) {
funVec.push_back(no);
funBlock.push_back(0); // 0 = theory-block
funLineBlockNo.push_back(fTheory[i].fLineNo);
}
}
}
// clean up tokens
if (tokens) {
delete tokens;
tokens = 0;
}
}
}
// check if func is present in the run-block
for (UInt_t i=0; i<fRuns.size(); i++) {
if (fRuns[i].GetNormParamNo() >= MSR_PARAM_FUN_OFFSET) { // function found
funVec.push_back(fRuns[i].GetNormParamNo());
funBlock.push_back(1); // 1 = run-block
funLineBlockNo.push_back(i+1);
}
}
// check if present funcs are found in the functions-block
Bool_t found;
for (UInt_t i=0; i<funVec.size(); i++) { // loop over found funcs in theory- and run-block
found = false;
// check if function is present in the functions-block
for (UInt_t j=0; j<fFunctions.size(); j++) {
if (fFunctions[j].fLine.BeginsWith("#") || fFunctions[j].fLine.IsWhitespace())
continue;
str = TString("fun");
str += funVec[i] - MSR_PARAM_FUN_OFFSET;
if (fFunctions[j].fLine.Contains(str, TString::kIgnoreCase)) {
found = true;
break;
}
}
if (!found) { // func not found
result = false;
cerr << endl << ">> PMsrHandler::CheckFuncs: **ERROR** fun" << funVec[i]-MSR_PARAM_FUN_OFFSET << " found in the ";
if (funBlock[i] == 0)
cerr << "theory-block in line " << funLineBlockNo[i] << " is not present in the functions-block!";
else
cerr << "run-block No " << funLineBlockNo[i] << " (norm) is not present in the functions-block!";
cerr << endl;
}
}
// clean up
funVec.clear();
funBlock.clear();
funLineBlockNo.clear();
return result;
}
//--------------------------------------------------------------------------
// CheckHistoGrouping (public)
//--------------------------------------------------------------------------
/**
* <p>Checks if histogram grouping makes any sense.
*
* <b>return:</b>
* - true if histogram grouping seems OK
* - false otherwise
*/
Bool_t PMsrHandler::CheckHistoGrouping()
{
Bool_t result = true;
for (UInt_t i=0; i<fRuns.size(); i++) {
if (fRuns[i].GetFitType() == MSR_FITTYPE_ASYM) {
if (fRuns[i].GetForwardHistoNoSize() != fRuns[i].GetBackwardHistoNoSize()) {
cerr << endl << ">> PMsrHandler::CheckHistoGrouping: **ERROR** # of forward histos != # of backward histos.";
cerr << endl << ">> Run #" << i+1;
cerr << endl;
result = false;
break;
}
}
// check grouping entries are not identical, e.g. forward 1 1 2
if (fRuns[i].GetForwardHistoNoSize() > 1) {
for (UInt_t j=0; j<fRuns[i].GetForwardHistoNoSize(); j++) {
for (UInt_t k=j+1; k<fRuns[i].GetForwardHistoNoSize(); k++) {
if (fRuns[i].GetForwardHistoNo(j) == fRuns[i].GetForwardHistoNo(k)) {
cerr << endl << ">> PMsrHandler::CheckHistoGrouping: **WARNING** grouping identical histograms!!";
cerr << endl << ">> run no " << i+1 << ", forward histo " << j+1 << " == forward histo " << k+1 << ".";
cerr << endl << ">> this really doesn't make any sense, but you are the boss.";
cerr << endl;
}
}
}
}
if (fRuns[i].GetBackwardHistoNoSize() > 1) {
for (UInt_t j=0; j<fRuns[i].GetBackwardHistoNoSize(); j++) {
for (UInt_t k=j+1; k<fRuns[i].GetBackwardHistoNoSize(); k++) {
if (fRuns[i].GetBackwardHistoNo(j) == fRuns[i].GetBackwardHistoNo(k)) {
cerr << endl << ">> PMsrHandler::CheckHistoGrouping: **WARNING** grouping identical histograms!!";
cerr << endl << ">> run no " << i+1 << ", backward histo " << j+1 << " == backward histo " << k+1 << ".";
cerr << endl << ">> this really doesn't make any sense, but you are the boss.";
cerr << endl;
}
}
}
}
}
return result;
}
//--------------------------------------------------------------------------
// CheckAddRunParameters (public)
//--------------------------------------------------------------------------
/**
* <p>In case addrun is present check that if addt0's are given there are as many addt0's than addrun's.
*
* <b>return:</b>
* - true if either no addt0 present, or # of addrun's == # of addt0's.
* - false otherwise
*/
Bool_t PMsrHandler::CheckAddRunParameters()
{
Bool_t result = true;
for (UInt_t i=0; i<fRuns.size(); i++) {
if (fRuns[i].GetRunNameSize() > 1) {
// check concerning the addt0 tags
if (fRuns[i].GetAddT0BinEntries() != 0) {
if (fRuns[i].GetAddT0BinEntries() != fRuns[i].GetRunNameSize()-1) {
cerr << endl << ">> PMsrHandler::CheckAddRunParameters: **ERROR** # of addt0 != # of addruns.";
cerr << endl << ">> Run #" << i+1;
cerr << endl;
result = false;
break;
}
}
}
}
return result;
}
//--------------------------------------------------------------------------
// CheckMaxLikelihood (public)
//--------------------------------------------------------------------------
/**
* <p>If log max likelihood is requested, make sure that all run blocks are of single histogram type.
* If this is not the case, fall back to chisq, since for asymmetry/non-muSR fit, log max likelihood
* is not defined.
*/
void PMsrHandler::CheckMaxLikelihood()
{
if (!fStatistic.fChisq) {
for (UInt_t i=0; i<fRuns.size(); i++) {
if ((fRuns[i].GetFitType() != MSR_FITTYPE_SINGLE_HISTO) && (fGlobal.GetFitType() != MSR_FITTYPE_SINGLE_HISTO)) {
cerr << endl << ">> PMsrHandler::CheckMaxLikelihood: **WARNING**: Maximum Log Likelihood Fit is only implemented";
cerr << endl << ">> for Single Histogram Fit. Will fall back to Chi Square Fit.";
cerr << endl << endl;
fStatistic.fChisq = true;
break;
}
}
}
}
//--------------------------------------------------------------------------
// GetGroupingString (public)
//--------------------------------------------------------------------------
/**
* <p>returns the forward/backward grouping string.
*
* \param runNo msr-file run block number
* \param detector tag telling which set to be used. Possible are: 'forward' and 'backward'
* \param groupingStr compressed grouping information.
*/
void PMsrHandler::GetGroupingString(Int_t runNo, TString detector, TString &groupingStr)
{
PIntVector grouping;
if (!detector.CompareTo("forward", TString::kIgnoreCase)) {
for (UInt_t i=0; i<fRuns[runNo].GetForwardHistoNoSize(); i++)
grouping.push_back(fRuns[runNo].GetForwardHistoNo(i));
MakeDetectorGroupingString("forward", grouping, groupingStr, false);
} else if (!detector.CompareTo("backward", TString::kIgnoreCase)) {
for (UInt_t i=0; i<fRuns[runNo].GetBackwardHistoNoSize(); i++)
grouping.push_back(fRuns[runNo].GetBackwardHistoNo(i));
MakeDetectorGroupingString("backward", grouping, groupingStr, false);
} else {
groupingStr = "**ERROR** unkown detector. Allow forward/backward.";
}
// clean up
grouping.clear();
}
//--------------------------------------------------------------------------
// EstimateN0 (public)
//--------------------------------------------------------------------------
/**
* <p>returns if N0 shall be estimated
*/
Bool_t PMsrHandler::EstimateN0()
{
if (fStartupOptions == 0)
return true;
return fStartupOptions->estimateN0;
}
//--------------------------------------------------------------------------
// GetAlphaEstimateN0 (public)
//--------------------------------------------------------------------------
/**
* <p>returns alpha to estimate N0
*/
Double_t PMsrHandler::GetAlphaEstimateN0()
{
if (fStartupOptions == 0)
return 0.0;
return fStartupOptions->alphaEstimateN0;
}
//--------------------------------------------------------------------------
// NeededPrecision (private)
//--------------------------------------------------------------------------
/**
* <p>Calculates the needed precision of Double_t values for WriteMsrLogFile and WriteMsrFile of the fit range.
* If a precision of > precLimit decimal places is needed, a warning is placed and a value of precLimit is returned.
*
* \param dval value for which the precision has to be estimated
* \param precLimit precision limit
*
* <b>return:</b> needed precision
*/
UInt_t PMsrHandler::NeededPrecision(Double_t dval, UInt_t precLimit)
{
UInt_t prec=0;
if (dval == 0.0)
return prec;
for (UInt_t i=0; i<precLimit; i++) {
if ((Int_t)(dval*pow(10.0,(Double_t)i)) != 0) {
prec = i;
break;
}
}
if (prec == precLimit) {
cerr << endl << ">> PMsrHandler::NeededPrecision(): **WARNING** precision limit of " << precLimit << ", requested.";
}
return prec;
}
//--------------------------------------------------------------------------
// LastSignifiant (private)
//--------------------------------------------------------------------------
/**
* <p>Gets the last significant digit down to precLimit.
*
* \param dval value for which the last signigicant digit shall be found
* \param precLimit precision limit
*
* <b>return:</b> last significant digit down to precLimit
*/
UInt_t PMsrHandler::LastSignificant(Double_t dval, UInt_t precLimit)
{
UInt_t lastSignificant = 2;
UInt_t decimalPoint = 0;
char str[128];
sprintf(str, "%lf", dval);
// find decimal point
for (UInt_t i=0; i<strlen(str); i++) {
if (str[i] == '.') {
decimalPoint = i;
break;
}
}
// find last significant digit
for (UInt_t i=strlen(str)-1; i>=0; i--) {
if (str[i] != '0') {
if ((i-decimalPoint) < precLimit)
lastSignificant = i-decimalPoint;
else
lastSignificant = precLimit;
break;
}
}
return lastSignificant;
}
//--------------------------------------------------------------------------
// ParseDetectorGrouping (private)
//--------------------------------------------------------------------------
/**
* <p>
*
* \param str forward/backward string to be decoded
* \param group decoded detector grouping vector
*
* <b>return:</b> true if parsing was successful, false otherwise.
*/
Bool_t PMsrHandler::ParseDetectorGrouping(TString str, PIntVector &group)
{
TObjArray *tok=0, *tok1=0;
TObjString *ostr=0;
Int_t first=0, last=0;
// change cn - cm to cn-cm. Will *NOT* handle cn - cm etc
str = str.ReplaceAll(" - ", "-");
group.clear();
tok = str.Tokenize(" \t");
// check that there are indeed enough tokens
if (tok->GetEntries() < 2) {
delete tok;
return false;
}
for (Int_t i=1; i<tok->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tok->At(i));
if (ostr->GetString().Contains("-")) { // hopefully a cn-cm token
tok1 = ostr->GetString().Tokenize("-");
if (tok1->GetEntries() == 2) {
ostr = dynamic_cast<TObjString*>(tok1->At(0));
if (ostr->GetString().IsDigit()) {
first = ostr->GetString().Atoi();
} else {
if (tok) delete tok;
if (tok1) delete tok1;
return false;
}
ostr = dynamic_cast<TObjString*>(tok1->At(1));
if (ostr->GetString().IsDigit()) {
last = ostr->GetString().Atoi();
} else {
if (tok) delete tok;
if (tok1) delete tok1;
return false;
}
if (last < first) {
if (tok) delete tok;
return false;
}
for (Int_t i=first; i<=last; i++)
group.push_back(i);
} else {
if (tok) delete tok;
if (tok1) delete tok1;
return false;
}
} else { // hopefully a number
if (ostr->GetString().IsDigit()) {
group.push_back(ostr->GetString().Atoi());
} else {
if (tok) delete tok;
return false;
}
}
}
// clean up
if (tok) delete tok;
if (tok1) delete tok1;
return true;
}
//--------------------------------------------------------------------------
// MakeDetectorGroupingString (private)
//--------------------------------------------------------------------------
/**
* <p>encodes the detector grouping vector.
*
* \param str 'forward' or 'backward'
* \param group detector grouping vector to be encoded
* \param result encoded detector grouping string
* \param includeDetector if true, the detector information is included
*/
void PMsrHandler::MakeDetectorGroupingString(TString str, PIntVector &group, TString &result, Bool_t includeDetector)
{
if (includeDetector) {
result = str + TString(" ");
if (str == TString("forward"))
result += " ";
} else {
str = "";
}
UInt_t i=0, j=0;
do {
j = i;
while (group[j]+1 == group[j+1]) {
j++;
if (j == group.size()-1)
break;
}
if (j >= i+2) {
result += group[i];
result += "-";
result += group[j];
i = j+1;
} else {
result += group[i];
i++;
}
result += " ";
} while (i<group.size());
}
//--------------------------------------------------------------------------
// CheckLegacyLifetimecorrection (private)
//--------------------------------------------------------------------------
/**
* <p>Checks for lifetimecorrection flags in the RUN-blocks and if present,
* transfer it to the PLOT-blocks. This is needed since originally the lifetimecorrection
* was (miss)placed in the RUN-blocks rather than in the PLOT-blocks where it
* most naturally would have been expected.
*/
void PMsrHandler::CheckLegacyLifetimecorrection()
{
UInt_t idx=0;
for (UInt_t i=0; i<fPlots.size(); i++) {
for (UInt_t j=0; j<fPlots[i].fRuns.size(); j++) {
idx = fPlots[i].fRuns[j]-1;
if (fRuns[idx].IsLifetimeCorrected()) {
fPlots[i].fLifeTimeCorrection = true;
}
}
}
}
// end ---------------------------------------------------------------------