Compare commits

..

1 Commits

Author SHA1 Message Date
suter_a e90590b908 allow to set the number of threads for fitting directly via the preferences of musredit. Qt5 ui not yet adopted.
Build and Deploy Documentation / build-and-deploy (push) Successful in 31s
2026-06-07 11:03:02 +02:00
37 changed files with 2179 additions and 1694 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ if (CMAKE_VERSION GREATER_EQUAL "3.3")
cmake_policy(SET CMP0167 NEW)
endif ()
project(musrfit VERSION 1.11.0 LANGUAGES C CXX)
project(musrfit VERSION 1.11.1 LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
+6
View File
@@ -12,6 +12,12 @@ or
https://bitbucket.org/muonspin/musrfit
Release of V1.11.1, 2026/06/07
==============================
allow from musredit (via preferences) to select the number of threads to be used
for fitting.
Release of V1.11.0, 2026/05/28
==============================
+1 -5
View File
@@ -75,11 +75,7 @@ target_include_directories(msr2data
)
target_link_libraries(msr2data ${ROOT_LIBRARIES} ${MUSRFIT_LIBS})
add_executable(msr2msr msr2msr.cpp classes/PStringUtils.cpp)
target_include_directories(msr2msr
BEFORE PRIVATE
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/include>
)
add_executable(msr2msr msr2msr.cpp)
target_link_libraries(msr2msr ${ROOT_LIBRARIES})
add_executable(musrfit musrfit.cpp)
-2
View File
@@ -106,7 +106,6 @@ add_library(PMusr SHARED
PMsgBoxDict.cxx
PMsr2Data.cpp
PMsrHandler.cpp
PStringUtils.cpp
PMusrCanvas.cpp
PMusrCanvasDict.cxx
PMusr.cpp
@@ -271,7 +270,6 @@ install(
${MUSRFIT_INC}/PRunSingleHisto.h
${MUSRFIT_INC}/PRunSingleHistoRRF.h
${MUSRFIT_INC}/PStartupHandler.h
${MUSRFIT_INC}/PStringUtils.h
${MUSRFIT_INC}/PTheory.h
${MUSRFIT_INC}/PUserFcnBase.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+239 -61
View File
@@ -64,9 +64,10 @@
#include <TFile.h>
#include <TDatime.h>
#include <TString.h>
#include <TObjArray.h>
#include <TObjString.h>
#include "PFitter.h"
#include "PStringUtils.h"
//+++ PSectorChisq class +++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -396,6 +397,8 @@ void PFitter::GetPhaseParams()
// default functions:
// user functions cannot be checked!
PMsrLines *theo = fRunInfo->GetMsrTheory();
TObjArray *tok = nullptr;
TObjString *ostr = nullptr;
TString str;
int pos = -1;
for (unsigned int i=0; i<theo->size(); i++) {
@@ -420,10 +423,18 @@ void PFitter::GetPhaseParams()
continue;
// extract phase token
std::vector<std::string> tok = PStringUtils::Split(line.Data(), " \t");
if (static_cast<int>(tok.size()) > pos) {
str = tok[pos].c_str();
tok = line.Tokenize(" \t");
if (tok == nullptr) {
std::cerr << "PFitter::GetPhaseParams(): **ERROR** couldn't tokenize theory line string." << std::endl;
return;
}
if (tok->GetEntries() > pos) {
ostr = dynamic_cast<TObjString*>(tok->At(pos));
str = ostr->GetString();
}
// clean up
delete tok;
tok = nullptr;
// decode phase token. It can be funX, mapX, or a number
if (str.Contains("fun")) { // function
@@ -480,15 +491,22 @@ PIntVector PFitter::GetParFromFun(const TString funStr)
PIntVector parVec;
PMsrLines *funList = fRunInfo->GetMsrFunctions();
TObjArray *tok = nullptr;
TObjString *ostr = nullptr;
TString str;
for (int i=0; i<funList->size(); i++) {
if (funList->at(i).fLine.Contains(funStr)) {
// tokenize function string
std::vector<std::string> tok = PStringUtils::Split(funList->at(i).fLine.Data(), " =+-*/");
tok = funList->at(i).fLine.Tokenize(" =+-*/");
if (tok == nullptr) {
std::cerr << "PFitter::GetParFromFun(): **ERROR** couldn't tokenize function string." << std::endl;
return parVec;
}
for (int j=1; j<static_cast<int>(tok.size()); j++) {
str = tok[j].c_str();
for (int j=1; j<tok->GetEntries(); j++) {
ostr = dynamic_cast<TObjString*>(tok->At(j));
str = ostr->GetString();
// parse tok for parX
if (str.Contains("par")) {
// find start idx of par in token
@@ -515,6 +533,10 @@ PIntVector PFitter::GetParFromFun(const TString funStr)
}
}
}
// clean up
delete tok;
tok = nullptr;
}
}
@@ -974,14 +996,16 @@ Bool_t PFitter::CheckCommands()
cmd.second = cmdLineNo;
fCmdList.push_back(cmd);
// filter out possible parameters for scan
std::vector<std::string> tokens;
TObjArray *tokens = nullptr;
TObjString *ostr;
TString str;
UInt_t ival;
tokens = PStringUtils::Split(line.Data(), ", \t");
tokens = line.Tokenize(", \t");
for (Int_t i=0; i<static_cast<int>(tokens.size()); i++) {
str = tokens[i].c_str();
for (Int_t i=0; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if ((i==1) || (i==2)) { // parX / parY
// check that token is a UInt_t
@@ -992,6 +1016,10 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
ival = str.Atoi();
@@ -1003,6 +1031,10 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
// keep parameter
@@ -1019,6 +1051,10 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
ival = str.Atoi();
@@ -1029,12 +1065,20 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
fScanNoPoints = ival;
}
}
if (tokens) {
delete tokens;
tokens = nullptr;
}
} else if (line.Contains("EIGEN", TString::kIgnoreCase)) {
cmd.first = PMN_EIGEN;
cmd.second = cmdLineNo;
@@ -1046,13 +1090,15 @@ Bool_t PFitter::CheckCommands()
// (iii) FIT_RANGE start1 end1 start2 end2 ... startN endN
// (iv) FIT_RANGE fgb+n0 lgb-n1
// (v) FIT_RANGE fgb+n00 lgb-n01 fgb+n10 lgb-n11 ... fgb+nN0 lgb-nN1
std::vector<std::string> tokens;
TObjArray *tokens = nullptr;
TObjString *ostr;
TString str;
tokens = PStringUtils::Split(line.Data(), ", \t");
tokens = line.Tokenize(", \t");
if (static_cast<int>(tokens.size()) == 2) { // should only be RESET
str = tokens[1].c_str();
if (tokens->GetEntries() == 2) { // should only be RESET
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.Contains("RESET", TString::kIgnoreCase)) {
cmd.first = PMN_FIT_RANGE;
cmd.second = cmdLineNo;
@@ -1064,23 +1110,32 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> with N the number of runs in the msr-file." << std::endl;
std::cerr << std::endl << ">> Found " << str.Data() << ", instead of RESET" << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
} else if ((static_cast<int>(tokens.size()) > 1) && (static_cast<UInt_t>(static_cast<int>(tokens.size())) % 2) == 1) {
if ((static_cast<int>(tokens.size()) > 3) && ((static_cast<UInt_t>(static_cast<int>(tokens.size()))-1)) != 2*fRunInfo->GetMsrRunList()->size()) {
} else if ((tokens->GetEntries() > 1) && (static_cast<UInt_t>(tokens->GetEntries()) % 2) == 1) {
if ((tokens->GetEntries() > 3) && ((static_cast<UInt_t>(tokens->GetEntries())-1)) != 2*fRunInfo->GetMsrRunList()->size()) {
std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
std::cerr << std::endl << ">> " << line.Data();
std::cerr << std::endl << ">> Syntax: FIT_RANGE RESET | FIT_RANGE <start> <end> | FIT_RANGE <s1> <e1> <s2> <e2> .. <sN> <eN> |";
std::cerr << std::endl << ">> FIT_RANGE fgb+<n0> lgb-<n1> | FIT_RANGE fgb+<n00> lgb-<n01> fgb+<n10> lgb-<n11> ... fgb+<nN0> lgb-<nN1>,";
std::cerr << std::endl << ">> with N the number of runs in the msr-file.";
std::cerr << std::endl << ">> Found N=" << (static_cast<int>(tokens.size())-1)/2 << ", # runs in msr-file=" << fRunInfo->GetMsrRunList()->size() << std::endl;
std::cerr << std::endl << ">> Found N=" << (tokens->GetEntries()-1)/2 << ", # runs in msr-file=" << fRunInfo->GetMsrRunList()->size() << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
} else {
// check that all range entries are numbers or fgb+n0 / lgb-n1
Bool_t ok = true;
for (Int_t n=1; n<static_cast<int>(tokens.size()); n++) {
str = tokens[n].c_str();
for (Int_t n=1; n<tokens->GetEntries(); n++) {
ostr = dynamic_cast<TObjString*>(tokens->At(n));
str = ostr->GetString();
if (!str.IsFloat()) {
if ((n%2 == 1) && (!str.Contains("fgb", TString::kIgnoreCase)))
ok = false;
@@ -1103,6 +1158,10 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> with N the number of runs in the msr-file.";
std::cerr << std::endl << ">> Found token '" << str.Data() << "', which is not a floating point number." << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
}
@@ -1113,19 +1172,29 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> FIT_RANGE fgb+<n0> lgb-<n1> | FIT_RANGE fgb+<n00> lgb-<n01> fgb+<n10> lgb-<n11> ... fgb+<nN0> lgb-<nN1>,";
std::cerr << std::endl << ">> with N the number of runs in the msr-file.";
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
if (tokens) {
delete tokens;
tokens = nullptr;
}
} else if (line.Contains("FIX", TString::kIgnoreCase)) {
// check if the given set of parameters (number or names) is present
std::vector<std::string> tokens;
TObjArray *tokens = nullptr;
TObjString *ostr;
TString str;
UInt_t ival;
tokens = PStringUtils::Split(line.Data(), ", \t");
tokens = line.Tokenize(", \t");
for (Int_t i=1; i<static_cast<int>(tokens.size()); i++) {
str = tokens[i].c_str();
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsDigit()) { // token might be a parameter number
ival = str.Atoi();
@@ -1136,6 +1205,10 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> Parameter " << ival << " is out of the Parameter Range [1," << fParams.size() << "]";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
} else { // token might be a parameter name
@@ -1153,11 +1226,19 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> Parameter '" << str.Data() << "' is NOT present as a parameter name";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
}
}
if (tokens) {
delete tokens;
tokens = nullptr;
}
// everything looks fine, feed the command list
cmd.first = PMN_FIX;
@@ -1197,14 +1278,16 @@ Bool_t PFitter::CheckCommands()
fCmdList.push_back(cmd);
} else if (line.Contains("RELEASE", TString::kIgnoreCase)) {
// check if the given set of parameters (number or names) is present
std::vector<std::string> tokens;
TObjArray *tokens = nullptr;
TObjString *ostr;
TString str;
UInt_t ival;
tokens = PStringUtils::Split(line.Data(), ", \t");
tokens = line.Tokenize(", \t");
for (Int_t i=1; i<static_cast<int>(tokens.size()); i++) {
str = tokens[i].c_str();
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsDigit()) { // token might be a parameter number
ival = str.Atoi();
@@ -1215,6 +1298,10 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> Parameter " << ival << " is out of the Parameter Range [1," << fParams.size() << "]";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
} else { // token might be a parameter name
@@ -1232,11 +1319,19 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> Parameter '" << str.Data() << "' is NOT present as a parameter name";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
}
}
if (tokens) {
delete tokens;
tokens = nullptr;
}
cmd.first = PMN_RELEASE;
cmd.second = cmdLineNo;
fCmdList.push_back(cmd);
@@ -1253,14 +1348,16 @@ Bool_t PFitter::CheckCommands()
cmd.second = cmdLineNo;
fCmdList.push_back(cmd);
// filter out possible parameters for scan
std::vector<std::string> tokens;
TObjArray *tokens = nullptr;
TObjString *ostr;
TString str;
UInt_t ival;
tokens = PStringUtils::Split(line.Data(), ", \t");
tokens = line.Tokenize(", \t");
for (Int_t i=0; i<static_cast<int>(tokens.size()); i++) {
str = tokens[i].c_str();
for (Int_t i=0; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (i==1) { // get parameter number
// check that token is a UInt_t
if (!str.IsDigit()) {
@@ -1270,6 +1367,10 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
ival = str.Atoi();
@@ -1281,6 +1382,10 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
// keep parameter
@@ -1297,6 +1402,10 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
ival = str.Atoi();
@@ -1307,6 +1416,10 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
fScanNoPoints = ival;
@@ -1321,6 +1434,10 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
fScanLow = str.Atof();
@@ -1335,23 +1452,33 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
std::cerr << std::endl;
fIsValid = false;
if (tokens) {
delete tokens;
tokens = nullptr;
}
break;
}
fScanHigh = str.Atof();
}
}
if (tokens) {
delete tokens;
tokens = nullptr;
}
} else if (line.Contains("SIMPLEX", TString::kIgnoreCase)) {
cmd.first = PMN_SIMPLEX;
cmd.second = cmdLineNo;
fCmdList.push_back(cmd);
} else if (line.Contains("STRATEGY", TString::kIgnoreCase)) {
std::vector<std::string> tokens;
TObjArray *tokens = nullptr;
TObjString *ostr;
TString str;
tokens = PStringUtils::Split(line.Data(), " \t");
if (static_cast<int>(tokens.size()) == 2) {
str = tokens[1].c_str();
tokens = line.Tokenize(" \t");
if (tokens->GetEntries() == 2) {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (str.CompareTo("0") == 0) { // low
fStrategy = 0;
} else if (str.CompareTo("1") == 0) { // default
@@ -1367,6 +1494,10 @@ Bool_t PFitter::CheckCommands()
}
}
if (tokens) {
delete tokens;
tokens = nullptr;
}
} else if (line.Contains("USER_COVARIANCE", TString::kIgnoreCase)) {
cmd.first = PMN_USER_COVARIANCE;
cmd.second = cmdLineNo;
@@ -1382,28 +1513,35 @@ Bool_t PFitter::CheckCommands()
fCmdList.push_back(cmd);
// check if the given sector arguments are valid time stamps, i.e. doubles and value < lgb time stamp
std::vector<std::string> tokens;
TObjArray *tokens = nullptr;
TObjString *ostr;
TString str;
tokens = PStringUtils::Split(line.Data(), " ,\t");
tokens = line.Tokenize(" ,\t");
if (static_cast<int>(tokens.size()) == 1) { // no sector time stamps given -> issue an error
if (tokens->GetEntries() == 1) { // no sector time stamps given -> issue an error
std::cerr << std::endl << ">> PFitter::CheckCommands(): **FATAL ERROR** in line " << it->fLineNo;
std::cerr << std::endl << ">> " << line.Data();
std::cerr << std::endl << ">> At least one sector time stamp is expected.";
std::cerr << std::endl << ">> Will stop ...";
std::cerr << std::endl;
// cleanup
if (tokens) {
delete tokens;
tokens = nullptr;
}
fIsValid = false;
fSectorFlag = false;
break;
}
Double_t dval;
for (Int_t i=1; i<static_cast<int>(tokens.size()); i++) {
for (Int_t i=1; i<tokens->GetEntries(); i++) {
// keep time range of sector
PSectorChisq sec(fRunInfo->GetNoOfRuns());
// get parse tokens
str = tokens[i].c_str();
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsFloat()) {
dval = str.Atof();
// check that the sector time stamp is smaller than all lgb time stamps
@@ -1414,6 +1552,11 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> The sector time stamp " << dval << " is > as the lgb time stamp (" << fOriginalFitRange[j].second << ") of run " << j << ".";
std::cerr << std::endl << ">> Will stop ...";
std::cerr << std::endl;
// cleanup
if (tokens) {
delete tokens;
tokens = nullptr;
}
fIsValid = false;
fSectorFlag = false;
return fIsValid;
@@ -1428,12 +1571,21 @@ Bool_t PFitter::CheckCommands()
std::cerr << std::endl << ">> The sector time stamp '" << str << "' is not a number.";
std::cerr << std::endl << ">> Will stop ...";
std::cerr << std::endl;
// cleanup
if (tokens) {
delete tokens;
tokens = nullptr;
}
fIsValid = false;
fSectorFlag = false;
break;
}
}
if (tokens) {
delete tokens;
tokens = nullptr;
}
} else { // unkown command
std::cerr << std::endl << ">> PFitter::CheckCommands(): **FATAL ERROR** in line " << it->fLineNo << " an unkown command is found:";
std::cerr << std::endl << ">> " << line.Data();
@@ -1577,24 +1729,27 @@ Bool_t PFitter::ExecuteFitRange(UInt_t lineNo)
return true;
}
std::vector<std::string> tokens;
TObjArray *tokens = nullptr;
TObjString *ostr;
TString str;
tokens = PStringUtils::Split(fCmdLines[lineNo].fLine.Data(), ", \t");
tokens = fCmdLines[lineNo].fLine.Tokenize(", \t");
PMsrRunList *runList = fRunInfo->GetMsrRunList();
// execute command, no error checking needed since this has been already carried out in CheckCommands()
if (static_cast<int>(tokens.size()) == 2) { // reset command
if (tokens->GetEntries() == 2) { // reset command
fRunListCollection->SetFitRange(fOriginalFitRange);
} else if (static_cast<int>(tokens.size()) == 3) { // single fit range for all runs
} else if (tokens->GetEntries() == 3) { // single fit range for all runs
Double_t start = 0.0, end = 0.0;
PDoublePair fitRange;
PDoublePairVector fitRangeVector;
str = tokens[1].c_str();
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
start = str.Atof();
str = tokens[2].c_str();
ostr = dynamic_cast<TObjString*>(tokens->At(2));
str = ostr->GetString();
end = str.Atof();
fitRange.first = start;
@@ -1608,9 +1763,11 @@ Bool_t PFitter::ExecuteFitRange(UInt_t lineNo)
PDoublePairVector fitRangeVector;
for (UInt_t i=0; i<runList->size(); i++) {
str = tokens[2*i+1].c_str();
ostr = dynamic_cast<TObjString*>(tokens->At(2*i+1));
str = ostr->GetString();
start = str.Atof();
str = tokens[2*i+2].c_str();
ostr = dynamic_cast<TObjString*>(tokens->At(2*i+2));
str = ostr->GetString();
end = str.Atof();
fitRange.first = start;
@@ -1638,13 +1795,15 @@ Bool_t PFitter::ExecuteFix(UInt_t lineNo)
{
std::cout << ">> PFitter::ExecuteFix(): " << fCmdLines[lineNo].fLine.Data() << std::endl;
std::vector<std::string> tokens;
TObjArray *tokens = nullptr;
TObjString *ostr;
TString str;
tokens = PStringUtils::Split(fCmdLines[lineNo].fLine.Data(), ", \t");
tokens = fCmdLines[lineNo].fLine.Tokenize(", \t");
for (Int_t i=1; i<static_cast<int>(tokens.size()); i++) {
str = tokens[i].c_str();
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsDigit()) { // token is a parameter number
fMnUserParams.Fix(static_cast<UInt_t>(str.Atoi())-1);
@@ -1653,6 +1812,11 @@ Bool_t PFitter::ExecuteFix(UInt_t lineNo)
}
}
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
return true;
}
@@ -1960,17 +2124,19 @@ Bool_t PFitter::ExecutePrintLevel(UInt_t lineNo)
{
std::cout << ">> PFitter::ExecutePrintLevel(): " << fCmdLines[lineNo].fLine.Data() << std::endl;
std::vector<std::string> tokens;
TObjArray *tokens = nullptr;
TObjString *ostr;
TString str;
tokens = PStringUtils::Split(fCmdLines[lineNo].fLine.Data(), ", \t");
tokens = fCmdLines[lineNo].fLine.Tokenize(", \t");
if (static_cast<int>(tokens.size()) < 2) {
if (tokens->GetEntries() < 2) {
std::cerr << std::endl << "**ERROR** from PFitter::ExecutePrintLevel(): SYNTAX: PRINT_LEVEL <N>, where <N>=0-3" << std::endl << std::endl;
return false;
}
str = tokens[1].c_str();
ostr = (TObjString*)tokens->At(1);
str = ostr->GetString();
Int_t ival;
if (str.IsDigit()) {
@@ -1993,6 +2159,11 @@ Bool_t PFitter::ExecutePrintLevel(UInt_t lineNo)
ROOT::Minuit2::MnPrint::SetLevel(fPrintLevel);
#endif
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
return true;
}
@@ -2009,15 +2180,17 @@ Bool_t PFitter::ExecutePrintLevel(UInt_t lineNo)
*/
Bool_t PFitter::ExecuteRelease(UInt_t lineNo)
{
std::vector<std::string> tokens;
TObjArray *tokens = nullptr;
TObjString *ostr;
TString str;
tokens = PStringUtils::Split(fCmdLines[lineNo].fLine.Data(), ", \t");
tokens = fCmdLines[lineNo].fLine.Tokenize(", \t");
std::cout << ">> PFitter::ExecuteRelease(): " << fCmdLines[lineNo].fLine.Data() << std::endl;
for (Int_t i=1; i<static_cast<int>(tokens.size()); i++) {
str = tokens[i].c_str();
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
if (str.IsDigit()) { // token is a parameter number
fMnUserParams.Release(static_cast<UInt_t>(str.Atoi())-1);
@@ -2030,6 +2203,11 @@ Bool_t PFitter::ExecuteRelease(UInt_t lineNo)
}
}
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
return true;
}
File diff suppressed because it is too large Load Diff
+12 -4
View File
@@ -34,11 +34,11 @@
#include <TColor.h>
#include <TRandom.h>
#include <TROOT.h>
#include <TObjString.h>
#include <TGFileDialog.h>
#include "PMusrCanvas.h"
#include "PFourier.h"
#include "PStringUtils.h"
static const char *gFiletypes[] = { "Data files", "*.dat",
"All files", "*",
@@ -6408,15 +6408,23 @@ Bool_t PMusrCanvas::IsScaleN0AndBkg()
PMsrLines *cmd = fMsrHandler->GetMsrCommands();
for (UInt_t i=0; i<cmd->size(); i++) {
if (cmd->at(i).fLine.Contains("SCALE_N0_BKG", TString::kIgnoreCase)) {
std::vector<std::string> tokens = PStringUtils::Split(cmd->at(i).fLine.Data(), " \t");
if (tokens.size() != 2) {
TObjArray *tokens = nullptr;
TObjString *ostr = nullptr;
TString str;
tokens = cmd->at(i).fLine.Tokenize(" \t");
if (tokens->GetEntries() != 2) {
std::cerr << std::endl << ">> PRunSingleHisto::IsScaleN0AndBkg(): **WARNING** Found uncorrect 'SCALE_N0_BKG' command, will ignore it.";
std::cerr << std::endl << ">> Allowed commands: SCALE_N0_BKG TRUE | FALSE" << std::endl;
return willScale;
}
if (PStringUtils::IsEqualNoCase(tokens[1], "FALSE")) {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (!str.CompareTo("FALSE", TString::kIgnoreCase)) {
willScale = false;
}
// clean up
if (tokens)
delete tokens;
}
}
+22 -12
View File
@@ -38,13 +38,12 @@
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
#include <TString.h>
#include <TObjArray.h>
#include <TObjString.h>
#include "PMusr.h"
#include "PStringUtils.h"
#include "PRunAsymmetry.h"
//--------------------------------------------------------------------------
@@ -405,15 +404,18 @@ UInt_t PRunAsymmetry::GetNoOfFitBins()
*/
void PRunAsymmetry::SetFitRangeBin(const TString fitRange)
{
TObjArray *tok = nullptr;
TObjString *ostr = nullptr;
TString str;
Ssiz_t idx = -1;
Int_t offset = 0;
std::vector<std::string> tok = PStringUtils::Split(fitRange.Data(), " \t");
tok = fitRange.Tokenize(" \t");
if (tok.size() == 3) { // structure FIT_RANGE fgb+n0 lgb-n1
if (tok->GetEntries() == 3) { // structure FIT_RANGE fgb+n0 lgb-n1
// handle fgb+n0 entry
str = tok[1];
ostr = dynamic_cast<TObjString*>(tok->At(1));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("+");
if (idx != -1) { // offset present
@@ -424,7 +426,8 @@ void PRunAsymmetry::SetFitRangeBin(const TString fitRange)
fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
// handle lgb-n1 entry
str = tok[2];
ostr = dynamic_cast<TObjString*>(tok->At(2));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("-");
if (idx != -1) { // offset present
@@ -433,15 +436,16 @@ void PRunAsymmetry::SetFitRangeBin(const TString fitRange)
offset = str.Atoi();
}
fFitEndTime = (fGoodBins[1] - offset - fT0s[0]) * fTimeResolution;
} else if ((tok.size() > 3) && (tok.size() % 2 == 1)) { // structure FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
UInt_t pos = 2*(fRunNo+1)-1;
} else if ((tok->GetEntries() > 3) && (tok->GetEntries() % 2 == 1)) { // structure FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
Int_t pos = 2*(fRunNo+1)-1;
if (pos + 1 >= tok.size()) {
if (pos + 1 >= tok->GetEntries()) {
std::cerr << std::endl << ">> PRunAsymmetry::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
} else {
// handle fgb+n0 entry
str = tok[pos];
ostr = static_cast<TObjString*>(tok->At(pos));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("+");
if (idx != -1) { // offset present
@@ -452,7 +456,8 @@ void PRunAsymmetry::SetFitRangeBin(const TString fitRange)
fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
// handle lgb-n1 entry
str = tok[pos+1];
ostr = static_cast<TObjString*>(tok->At(pos+1));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("-");
if (idx != -1) { // offset present
@@ -466,6 +471,11 @@ void PRunAsymmetry::SetFitRangeBin(const TString fitRange)
std::cerr << std::endl << ">> PRunAsymmetry::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
}
// clean up
if (tok) {
delete tok;
}
}
//--------------------------------------------------------------------------
+22 -12
View File
@@ -39,13 +39,12 @@
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
#include <TString.h>
#include <TObjArray.h>
#include <TObjString.h>
#include "PMusr.h"
#include "PStringUtils.h"
#include "PRunAsymmetryBNMR.h"
//--------------------------------------------------------------------------
@@ -407,15 +406,18 @@ UInt_t PRunAsymmetryBNMR::GetNoOfFitBins()
*/
void PRunAsymmetryBNMR::SetFitRangeBin(const TString fitRange)
{
TObjArray *tok = nullptr;
TObjString *ostr = nullptr;
TString str;
Ssiz_t idx = -1;
Int_t offset = 0;
std::vector<std::string> tok = PStringUtils::Split(fitRange.Data(), " \t");
tok = fitRange.Tokenize(" \t");
if (tok.size() == 3) { // structure FIT_RANGE fgb+n0 lgb-n1
if (tok->GetEntries() == 3) { // structure FIT_RANGE fgb+n0 lgb-n1
// handle fgb+n0 entry
str = tok[1];
ostr = dynamic_cast<TObjString*>(tok->At(1));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("+");
if (idx != -1) { // offset present
@@ -426,7 +428,8 @@ void PRunAsymmetryBNMR::SetFitRangeBin(const TString fitRange)
fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
// handle lgb-n1 entry
str = tok[2];
ostr = dynamic_cast<TObjString*>(tok->At(2));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("-");
if (idx != -1) { // offset present
@@ -435,15 +438,16 @@ void PRunAsymmetryBNMR::SetFitRangeBin(const TString fitRange)
offset = str.Atoi();
}
fFitEndTime = (fGoodBins[1] - offset - fT0s[0]) * fTimeResolution;
} else if ((tok.size() > 3) && (tok.size() % 2 == 1)) { // structure FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
UInt_t pos = 2*(fRunNo+1)-1;
} else if ((tok->GetEntries() > 3) && (tok->GetEntries() % 2 == 1)) { // structure FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
Int_t pos = 2*(fRunNo+1)-1;
if (pos + 1 >= tok.size()) {
if (pos + 1 >= tok->GetEntries()) {
std::cerr << std::endl << ">> PRunAsymmetryBNMR::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
} else {
// handle fgb+n0 entry
str = tok[pos];
ostr = static_cast<TObjString*>(tok->At(pos));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("+");
if (idx != -1) { // offset present
@@ -454,7 +458,8 @@ void PRunAsymmetryBNMR::SetFitRangeBin(const TString fitRange)
fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
// handle lgb-n1 entry
str = tok[pos+1];
ostr = static_cast<TObjString*>(tok->At(pos+1));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("-");
if (idx != -1) { // offset present
@@ -468,6 +473,11 @@ void PRunAsymmetryBNMR::SetFitRangeBin(const TString fitRange)
std::cerr << std::endl << ">> PRunAsymmetryBNMR::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
}
// clean up
if (tok) {
delete tok;
}
}
//--------------------------------------------------------------------------
+22 -12
View File
@@ -39,13 +39,12 @@
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <TString.h>
#include <TObjArray.h>
#include <TObjString.h>
#include "PMusr.h"
#include "PStringUtils.h"
#include "PRunAsymmetryRRF.h"
//--------------------------------------------------------------------------
@@ -394,15 +393,18 @@ UInt_t PRunAsymmetryRRF::GetNoOfFitBins()
*/
void PRunAsymmetryRRF::SetFitRangeBin(const TString fitRange)
{
TObjArray *tok = nullptr;
TObjString *ostr = nullptr;
TString str;
Ssiz_t idx = -1;
Int_t offset = 0;
std::vector<std::string> tok = PStringUtils::Split(fitRange.Data(), " \t");
tok = fitRange.Tokenize(" \t");
if (tok.size() == 3) { // structure FIT_RANGE fgb+n0 lgb-n1
if (tok->GetEntries() == 3) { // structure FIT_RANGE fgb+n0 lgb-n1
// handle fgb+n0 entry
str = tok[1];
ostr = static_cast<TObjString*>(tok->At(1));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("+");
if (idx != -1) { // offset present
@@ -413,7 +415,8 @@ void PRunAsymmetryRRF::SetFitRangeBin(const TString fitRange)
fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
// handle lgb-n1 entry
str = tok[2];
ostr = static_cast<TObjString*>(tok->At(2));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("-");
if (idx != -1) { // offset present
@@ -422,15 +425,16 @@ void PRunAsymmetryRRF::SetFitRangeBin(const TString fitRange)
offset = str.Atoi();
}
fFitEndTime = (fGoodBins[1] - offset - fT0s[0]) * fTimeResolution;
} else if ((tok.size() > 3) && (tok.size() % 2 == 1)) { // structure FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
UInt_t pos = 2*(fRunNo+1)-1;
} else if ((tok->GetEntries() > 3) && (tok->GetEntries() % 2 == 1)) { // structure FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
Int_t pos = 2*(fRunNo+1)-1;
if (pos + 1 >= tok.size()) {
if (pos + 1 >= tok->GetEntries()) {
std::cerr << std::endl << ">> PRunSingleHisto::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
} else {
// handle fgb+n0 entry
str = tok[pos];
ostr = static_cast<TObjString*>(tok->At(pos));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("+");
if (idx != -1) { // offset present
@@ -441,7 +445,8 @@ void PRunAsymmetryRRF::SetFitRangeBin(const TString fitRange)
fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
// handle lgb-n1 entry
str = tok[pos+1];
ostr = static_cast<TObjString*>(tok->At(pos+1));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("-");
if (idx != -1) { // offset present
@@ -455,6 +460,11 @@ void PRunAsymmetryRRF::SetFitRangeBin(const TString fitRange)
std::cerr << std::endl << ">> PRunSingleHisto::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
}
// clean up
if (tok) {
delete tok;
}
}
//--------------------------------------------------------------------------
+2
View File
@@ -32,6 +32,8 @@
#include <TROOT.h>
#include <TSystem.h>
#include <TString.h>
#include <TObjArray.h>
#include <TObjString.h>
#include <TFolder.h>
#include "PRunBase.h"
+412 -121
View File
@@ -42,7 +42,6 @@
#include <string>
#include <sstream>
#include <memory>
#include <vector>
#include <TROOT.h>
#include <TSystem.h>
@@ -59,7 +58,6 @@
#include "TLemRunHeader.h"
#include "MuSR_td_PSI_bin.h"
#include "mud.h"
#include "PStringUtils.h"
#ifdef PNEXUS_ENABLED
#include "PNeXus.h"
@@ -1170,22 +1168,30 @@ Bool_t PRunDataHandler::FileExistsCheck(PMsrRunBlock &runInfo, const UInt_t idx)
if (pathName.CompareTo("???") == 0) { // not found in local directory and xml path
str = TString(musrpath);
// MUSRFULLDATAPATH has the structure: path_1:path_2:...:path_n
std::vector<std::string> tokens = PStringUtils::Split(str.Data(), ":");
for (UInt_t i=0; i<tokens.size(); i++) {
str = TString(tokens[i]) + TString("/") + *runInfo.GetRunName(idx);
TObjArray *tokens = str.Tokenize(":");
TObjString *ostr;
for (Int_t i=0; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString() + TString("/") + *runInfo.GetRunName(idx);
TestFileName(str, ext);
if (!str.IsNull()) {
pathName = str;
break;
}
}
// cleanup
if (tokens) {
delete tokens;
tokens = nullptr;
}
}
// check if the file is found in the generated default path
if (pathName.CompareTo("???") == 0) { // not found in MUSRFULLDATAPATH search
str = TString(musrpath);
// MUSRFULLDATAPATH has the structure: path_1:path_2:...:path_n
std::vector<std::string> tokens = PStringUtils::Split(str.Data(), ":");
TObjArray *tokens = str.Tokenize(":");
TObjString *ostr;
pstr = runInfo.GetInstitute(idx);
if (pstr == nullptr) {
std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** Couldn't obtain institute data." << std::endl;
@@ -1200,8 +1206,9 @@ Bool_t PRunDataHandler::FileExistsCheck(PMsrRunBlock &runInfo, const UInt_t idx)
}
pstr->ToUpper();
runInfo.SetBeamline(*pstr, idx);
for (UInt_t i=0; i<tokens.size(); i++) {
str = TString(tokens[i]) + TString("/DATA/") +
for (Int_t i=0; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString() + TString("/DATA/") +
*runInfo.GetInstitute(idx) + TString("/") +
*runInfo.GetBeamline(idx) + TString("/") +
*runInfo.GetRunName(idx);
@@ -1211,6 +1218,11 @@ Bool_t PRunDataHandler::FileExistsCheck(PMsrRunBlock &runInfo, const UInt_t idx)
break;
}
}
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
}
// no proper path name found
@@ -1295,14 +1307,21 @@ Bool_t PRunDataHandler::FileExistsCheck(const Bool_t fileName, const Int_t idx)
if (pathName.CompareTo("???") == 0) { // not found in local directory and xml path
str = TString(musrpath);
// MUSRFULLDATAPATH has the structure: path_1:path_2:...:path_n
std::vector<std::string> tokens = PStringUtils::Split(str.Data(), ":");
for (UInt_t i=0; i<tokens.size(); i++) {
str = TString(tokens[i]) + TString("/") + fln;
TObjArray *tokens = str.Tokenize(":");
TObjString *ostr;
for (Int_t i=0; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString() + TString("/") + fln;
if (gSystem->AccessPathName(str.Data())!=true) { // found
pathName = str;
break;
}
}
// cleanup
if (tokens) {
delete tokens;
tokens = nullptr;
}
}
// no proper path name found
if (pathName.CompareTo("???") == 0) {
@@ -1355,14 +1374,21 @@ Bool_t PRunDataHandler::FileExistsCheck(const TString fileName)
if (pathName.CompareTo("???") == 0) { // not found in local directory and xml path
str = TString(musrpath);
// MUSRFULLDATAPATH has the structure: path_1:path_2:...:path_n
std::vector<std::string> tokens = PStringUtils::Split(str.Data(), ":");
for (UInt_t i=0; i<tokens.size(); i++) {
str = TString(tokens[i]) + TString("/") + fileName;
TObjArray *tokens = str.Tokenize(":");
TObjString *ostr;
for (Int_t i=0; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString() + TString("/") + fileName;
if (gSystem->AccessPathName(str.Data())!=true) { // found
pathName = str;
break;
}
}
// cleanup
if (tokens) {
delete tokens;
tokens = nullptr;
}
}
// no proper path name found
if (pathName.CompareTo("???") == 0) {
@@ -1518,22 +1544,97 @@ Bool_t PRunDataHandler::ReadRootFile()
TString s;
TObjArrayIter summIter(runSummary);
TObjString *os(dynamic_cast<TObjString*>(summIter.Next()));
TObjArray *oa(nullptr);
TObjString *objTok(nullptr);
while (os != nullptr) {
s = os->GetString();
// a summary line has the structure 'RA-L = val RA-R = val ...', i.e. the value
// follows two tokens after the tag. More than one RA-value may be on one line.
std::vector<std::string> oa = PStringUtils::Split(s.Data(), " ");
for (UInt_t k=0; k+2 < oa.size(); k++) {
if (oa[k+1] != "=")
continue;
if (oa[k] == "RA-L")
runData.SetRingAnode(0, TString(oa[k+2]).Atof());
else if (oa[k] == "RA-R")
runData.SetRingAnode(1, TString(oa[k+2]).Atof());
else if (oa[k] == "RA-T")
runData.SetRingAnode(2, TString(oa[k+2]).Atof());
else if (oa[k] == "RA-B")
runData.SetRingAnode(3, TString(oa[k+2]).Atof());
// will put four parallel if's since it may be that more than one RA-values are on one line
if (s.Contains("RA-L")) {
oa = s.Tokenize(" ");
TObjArrayIter lineIter(oa);
objTok = dynamic_cast<TObjString*>(lineIter.Next());
while (objTok != nullptr) {
if (!objTok->GetString().CompareTo("RA-L")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
if ((objTok != nullptr) && !objTok->GetString().CompareTo("=")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
runData.SetRingAnode(0, objTok->GetString().Atof()); // fill RA-R value into the runData structure
break;
}
}
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
}
// clean up
if (oa) {
delete oa;
oa = nullptr;
}
}
if (s.Contains("RA-R")) {
oa = s.Tokenize(" ");
TObjArrayIter lineIter(oa);
objTok = dynamic_cast<TObjString*>(lineIter.Next());
while (objTok != nullptr){
if (!objTok->GetString().CompareTo("RA-R")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
if (objTok != nullptr && !objTok->GetString().CompareTo("=")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
runData.SetRingAnode(1, objTok->GetString().Atof()); // fill RA-R value into the runData structure
break;
}
}
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
}
// clean up
if (oa) {
delete oa;
oa = nullptr;
}
}
if (s.Contains("RA-T")) {
oa = s.Tokenize(" ");
TObjArrayIter lineIter(oa);
objTok = dynamic_cast<TObjString*>(lineIter.Next());
while (objTok != nullptr){
if (!objTok->GetString().CompareTo("RA-T")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
if ((objTok != nullptr) && !objTok->GetString().CompareTo("=")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
runData.SetRingAnode(2, objTok->GetString().Atof()); // fill RA-T value into the runData structure
break;
}
}
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
}
// clean up
if (oa) {
delete oa;
oa = nullptr;
}
}
if (s.Contains("RA-B")) {
oa = s.Tokenize(" ");
TObjArrayIter lineIter(oa);
objTok = dynamic_cast<TObjString*>(lineIter.Next());
while (objTok != nullptr){
if (!objTok->GetString().CompareTo("RA-B")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
if ((objTok != nullptr) && !objTok->GetString().CompareTo("=")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
runData.SetRingAnode(3, objTok->GetString().Atof()); // fill RA-B value into the runData structure
break;
}
}
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
}
// clean up
if (oa) {
delete oa;
oa = nullptr;
}
}
os = dynamic_cast<TObjString*>(summIter.Next()); // next summary line...
@@ -1861,22 +1962,97 @@ Bool_t PRunDataHandler::ReadRootFile()
TString s;
TObjArrayIter summIter(runSummary);
TObjString *os(dynamic_cast<TObjString*>(summIter.Next()));
TObjArray *oa(nullptr);
TObjString *objTok(nullptr);
while (os != nullptr) {
s = os->GetString();
// a summary line has the structure 'RA-L = val RA-R = val ...', i.e. the value
// follows two tokens after the tag. More than one RA-value may be on one line.
std::vector<std::string> oa = PStringUtils::Split(s.Data(), " ");
for (UInt_t k=0; k+2 < oa.size(); k++) {
if (oa[k+1] != "=")
continue;
if (oa[k] == "RA-L")
runData.SetRingAnode(0, TString(oa[k+2]).Atof());
else if (oa[k] == "RA-R")
runData.SetRingAnode(1, TString(oa[k+2]).Atof());
else if (oa[k] == "RA-T")
runData.SetRingAnode(2, TString(oa[k+2]).Atof());
else if (oa[k] == "RA-B")
runData.SetRingAnode(3, TString(oa[k+2]).Atof());
// will put four parallel if's since it may be that more than one RA-values are on one line
if (s.Contains("RA-L")) {
oa = s.Tokenize(" ");
TObjArrayIter lineIter(oa);
objTok = dynamic_cast<TObjString*>(lineIter.Next());
while (objTok != nullptr) {
if (!objTok->GetString().CompareTo("RA-L")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
if ((objTok != nullptr) && !objTok->GetString().CompareTo("=")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
runData.SetRingAnode(0, objTok->GetString().Atof()); // fill RA-R value into the runData structure
break;
}
}
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
}
// clean up
if (oa) {
delete oa;
oa = nullptr;
}
}
if (s.Contains("RA-R")) {
oa = s.Tokenize(" ");
TObjArrayIter lineIter(oa);
objTok = dynamic_cast<TObjString*>(lineIter.Next());
while (objTok != nullptr){
if (!objTok->GetString().CompareTo("RA-R")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
if ((objTok != nullptr) && !objTok->GetString().CompareTo("=")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
runData.SetRingAnode(1, objTok->GetString().Atof()); // fill RA-R value into the runData structure
break;
}
}
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
}
// clean up
if (oa) {
delete oa;
oa = nullptr;
}
}
if (s.Contains("RA-T")) {
oa = s.Tokenize(" ");
TObjArrayIter lineIter(oa);
objTok = dynamic_cast<TObjString*>(lineIter.Next());
while (objTok != nullptr){
if (!objTok->GetString().CompareTo("RA-T")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
if ((objTok != nullptr) && !objTok->GetString().CompareTo("=")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
runData.SetRingAnode(2, objTok->GetString().Atof()); // fill RA-T value into the runData structure
break;
}
}
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
}
// clean up
if (oa) {
delete oa;
oa = nullptr;
}
}
if (s.Contains("RA-B")) {
oa = s.Tokenize(" ");
TObjArrayIter lineIter(oa);
objTok = dynamic_cast<TObjString*>(lineIter.Next());
while (objTok != nullptr){
if (!objTok->GetString().CompareTo("RA-B")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
if ((objTok != nullptr) && !objTok->GetString().CompareTo("=")) {
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
runData.SetRingAnode(3, objTok->GetString().Atof()); // fill RA-B value into the runData structure
break;
}
}
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
}
// clean up
if (oa) {
delete oa;
oa = nullptr;
}
}
os = dynamic_cast<TObjString*>(summIter.Next()); // next summary line...
@@ -2278,7 +2454,8 @@ Bool_t PRunDataHandler::ReadWkmFile()
// read data ---------------------------------------------------------
UInt_t group_counter = 0;
Int_t val;
std::vector<std::string> tokens;
TObjArray *tokens;
TObjString *ostr;
TString str;
UInt_t histoNo = 0;
PRawRunDataSet dataSet;
@@ -2312,22 +2489,30 @@ Bool_t PRunDataHandler::ReadWkmFile()
f.getline(instr, sizeof(instr));
continue;
}
tokens = PStringUtils::Split(line.Data(), " ");
tokens = line.Tokenize(" ");
if (tokens.empty()) { // no tokens found
if (!tokens) { // no tokens found
std::cerr << std::endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** while reading data: coulnd't tokenize run data.";
return false;
}
for (UInt_t i=0; i<tokens.size(); i++) {
str = tokens[i];
for (Int_t i=0; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
val = ToInt(str, ok);
if (ok) {
histoData.push_back(val);
} else {
std::cerr << std::endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** while reading data: data line contains non-integer values.";
// clean up
delete tokens;
return false;
}
}
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
}
f.getline(instr, sizeof(instr));
@@ -2338,21 +2523,29 @@ Bool_t PRunDataHandler::ReadWkmFile()
if (strlen(instr) != 0) {
// extract values
line = TString(instr);
tokens = PStringUtils::Split(line.Data(), " ");
if (tokens.empty()) { // no tokens found
tokens = line.Tokenize(" ");
if (!tokens) { // no tokens found
std::cerr << std::endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** while reading data: coulnd't tokenize run data.";
return false;
}
for (UInt_t i=0; i<tokens.size(); i++) {
str = tokens[i];
for (Int_t i=0; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
val = ToInt(str, ok);
if (ok) {
histoData.push_back(val);
} else {
std::cerr << std::endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** while reading data: data line contains non-integer values.";
// clean up
delete tokens;
return false;
}
}
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
}
// save the last histo if not empty
@@ -3049,7 +3242,8 @@ Bool_t PRunDataHandler::ReadMduAsciiFile()
Bool_t headerTag = false;
Bool_t dataTag = false;
Int_t dataLineCounter = 0;
std::vector<std::string> tokens;
TObjString *ostr;
TObjArray *tokens = nullptr;
TString str;
Int_t groups = 0;
Int_t channels = 0;
@@ -3093,9 +3287,9 @@ Bool_t PRunDataHandler::ReadMduAsciiFile()
if (workStr.BeginsWith("title:", TString::kIgnoreCase)) {
runData.SetRunTitle(TString(workStr.Data()+workStr.First(":")+2));
} else if (workStr.BeginsWith("field:", TString::kIgnoreCase)) {
tokens = PStringUtils::Split(workStr.Data(), ":("); // field: val (units)
tokens = workStr.Tokenize(":("); // field: val (units)
// check if expected number of tokens present
if (tokens.size() != 3) {
if (tokens->GetEntries() != 3) {
std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", invalid field entry in header.";
std::cerr << std::endl << ">> " << line.Data();
std::cerr << std::endl;
@@ -3103,8 +3297,9 @@ Bool_t PRunDataHandler::ReadMduAsciiFile()
break;
}
// check if field value is a number
if (TString(tokens[1]).IsFloat()) {
dval = TString(tokens[1]).Atof();
ostr = dynamic_cast<TObjString*>(tokens->At(1));
if (ostr->GetString().IsFloat()) {
dval = ostr->GetString().Atof();
} else {
std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", field value is not float/doulbe.";
std::cerr << std::endl << ">> " << line.Data();
@@ -3113,9 +3308,10 @@ Bool_t PRunDataHandler::ReadMduAsciiFile()
break;
}
// check units, accept (G), (T)
if (TString(tokens[2]).Contains("G"))
ostr = dynamic_cast<TObjString*>(tokens->At(2));
if (ostr->GetString().Contains("G"))
unitScaling = 1.0;
else if (TString(tokens[2]).Contains("T"))
else if (ostr->GetString().Contains("T"))
unitScaling = 1.0e4;
else {
std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", unkown field units.";
@@ -3125,10 +3321,16 @@ Bool_t PRunDataHandler::ReadMduAsciiFile()
break;
}
runData.SetField(dval*unitScaling);
// clean up tokens
if (tokens) {
delete tokens;
tokens = nullptr;
}
} else if (workStr.BeginsWith("temp:", TString::kIgnoreCase)) {
tokens = PStringUtils::Split(workStr.Data(), ":("); // temp: val (units)
tokens = workStr.Tokenize(":("); // temp: val (units)
// check if expected number of tokens present
if (tokens.size() != 3) {
if (tokens->GetEntries() != 3) {
std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", invalid temperatue entry in header.";
std::cerr << std::endl << ">> " << line.Data();
std::cerr << std::endl;
@@ -3136,8 +3338,9 @@ Bool_t PRunDataHandler::ReadMduAsciiFile()
break;
}
// check if field value is a number
if (TString(tokens[1]).IsFloat()) {
dval = TString(tokens[1]).Atof();
ostr = dynamic_cast<TObjString*>(tokens->At(1));
if (ostr->GetString().IsFloat()) {
dval = ostr->GetString().Atof();
} else {
std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", temperature value is not float/doulbe.";
std::cerr << std::endl << ">> " << line.Data();
@@ -3146,6 +3349,12 @@ Bool_t PRunDataHandler::ReadMduAsciiFile()
break;
}
runData.SetTemperature(0, dval, 0.0);
// clean up tokens
if (tokens) {
delete tokens;
tokens = nullptr;
}
} else if (workStr.BeginsWith("setup:", TString::kIgnoreCase)) {
runData.SetSetup(TString(workStr.Data()+workStr.First(":")+2));
} else if (workStr.BeginsWith("groups:", TString::kIgnoreCase)) {
@@ -3168,9 +3377,9 @@ Bool_t PRunDataHandler::ReadMduAsciiFile()
break;
}
} else if (workStr.BeginsWith("resolution:", TString::kIgnoreCase)) {
tokens = PStringUtils::Split(workStr.Data(), ":("); // resolution: val (units)
tokens = workStr.Tokenize(":("); // resolution: val (units)
// check if expected number of tokens present
if (tokens.size() != 3) {
if (tokens->GetEntries() != 3) {
std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", invalid time resolution entry in header.";
std::cerr << std::endl << line.Data();
std::cerr << std::endl;
@@ -3178,8 +3387,9 @@ Bool_t PRunDataHandler::ReadMduAsciiFile()
break;
}
// check if timeresolution value is a number
if (TString(tokens[1]).IsFloat()) {
dval = TString(tokens[1]).Atof();
ostr = dynamic_cast<TObjString*>(tokens->At(1));
if (ostr->GetString().IsFloat()) {
dval = ostr->GetString().Atof();
} else {
std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", time resolution value is not float/doulbe.";
std::cerr << std::endl << ">> " << line.Data();
@@ -3188,13 +3398,14 @@ Bool_t PRunDataHandler::ReadMduAsciiFile()
break;
}
// check units, accept (fs), (ps), (ns), (us)
if (TString(tokens[2]).Contains("fs"))
ostr = dynamic_cast<TObjString*>(tokens->At(2));
if (ostr->GetString().Contains("fs"))
unitScaling = 1.0e-6;
else if (TString(tokens[2]).Contains("ps"))
else if (ostr->GetString().Contains("ps"))
unitScaling = 1.0e-3;
else if (TString(tokens[2]).Contains("ns"))
else if (ostr->GetString().Contains("ns"))
unitScaling = 1.0;
else if (TString(tokens[2]).Contains("us"))
else if (ostr->GetString().Contains("us"))
unitScaling = 1.0e3;
else {
std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", unkown time resolution units.";
@@ -3204,6 +3415,12 @@ Bool_t PRunDataHandler::ReadMduAsciiFile()
break;
}
runData.SetTimeResolution(dval*unitScaling);
// clean up tokens
if (tokens) {
delete tokens;
tokens = nullptr;
}
} else { // error
std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", illegal header line.";
std::cerr << std::endl;
@@ -3212,9 +3429,9 @@ Bool_t PRunDataHandler::ReadMduAsciiFile()
}
} else if (dataTag) {
dataLineCounter++;
tokens = PStringUtils::Split(line.Data(), " ,\t");
tokens = line.Tokenize(" ,\t");
// check if the number of data line entries is correct
if (static_cast<Int_t>(tokens.size()) != groups+1) {
if (tokens->GetEntries() != groups+1) {
std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** found data line with a wrong data format, cannot be handled (line no " << lineNo << ")";
std::cerr << std::endl << ">> line:";
std::cerr << std::endl << ">> " << line.Data();
@@ -3223,8 +3440,15 @@ Bool_t PRunDataHandler::ReadMduAsciiFile()
break;
}
for (UInt_t i=1; i<tokens.size(); i++) {
data[i-1].push_back(TString(tokens[i]).Atof());
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
data[i-1].push_back(ostr->GetString().Atof());
}
// clean up tokens
if (tokens) {
delete tokens;
tokens = nullptr;
}
}
}
@@ -3414,14 +3638,16 @@ Bool_t PRunDataHandler::ReadAsciiFile()
} else if (dataTag) {
if (line.IsWhitespace()) // ignore empty lines
continue;
TObjString *ostr;
TObjArray *tokens;
// Remove trailing end of line
line.Remove(TString::kTrailing, '\r');
// check if data have x, y [, error y] structure, and that x, y, and error y are numbers
std::vector<std::string> tokens = PStringUtils::Split(line.Data(), " ,\t");
tokens = line.Tokenize(" ,\t");
// check if the number of data line entries is 2 or 3
if ((tokens.size() != 2) && (tokens.size() != 3)) {
if ((tokens->GetEntries() != 2) && (tokens->GetEntries() != 3)) {
std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** found data line with a structure different than \"x, y [, error y]\", cannot be handled (line no " << lineNo << ")";
std::cerr << std::endl;
success = false;
@@ -3429,32 +3655,35 @@ Bool_t PRunDataHandler::ReadAsciiFile()
}
// get x
if (!TString(tokens[0]).IsFloat()) {
std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": x = " << tokens[0] << " is not a number, sorry.";
ostr = dynamic_cast<TObjString*>(tokens->At(0));
if (!ostr->GetString().IsFloat()) {
std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": x = " << ostr->GetString().Data() << " is not a number, sorry.";
std::cerr << std::endl;
success = false;
break;
}
x = TString(tokens[0]).Atof();
x = ostr->GetString().Atof();
// get y
if (!TString(tokens[1]).IsFloat()) {
std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": y = " << tokens[1] << " is not a number, sorry.";
ostr = dynamic_cast<TObjString*>(tokens->At(1));
if (!ostr->GetString().IsFloat()) {
std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": y = " << ostr->GetString().Data() << " is not a number, sorry.";
std::cerr << std::endl;
success = false;
break;
}
y = TString(tokens[1]).Atof();
y = ostr->GetString().Atof();
// get error y if present
if (tokens.size() == 3) {
if (!TString(tokens[2]).IsFloat()) {
std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": error y = " << tokens[2] << " is not a number, sorry.";
if (tokens->GetEntries() == 3) {
ostr = dynamic_cast<TObjString*>(tokens->At(2));
if (!ostr->GetString().IsFloat()) {
std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": error y = " << ostr->GetString().Data() << " is not a number, sorry.";
std::cerr << std::endl;
success = false;
break;
}
ey = TString(tokens[2]).Atof();
ey = ostr->GetString().Atof();
if (ey == 0) {
std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **WARNING** line no " << lineNo << ": error y = 0 which doesn't make sense. Will set it to 1.0. Please check!!";
std::cerr << std::endl;
@@ -3466,6 +3695,12 @@ Bool_t PRunDataHandler::ReadAsciiFile()
ey = 1.0;
}
// clean up tokens
if (tokens) {
delete tokens;
tokens = nullptr;
}
// keep values
xVec.push_back(x);
exVec.push_back(1.0);
@@ -3643,7 +3878,8 @@ Bool_t PRunDataHandler::ReadDBFile()
// variables needed to tokenize strings
TString tstr;
std::vector<std::string> tokens;
TObjString *ostr;
TObjArray *tokens = nullptr;
while (!f.eof()) {
// get next line from file
@@ -3679,9 +3915,16 @@ Bool_t PRunDataHandler::ReadDBFile()
dbTag = 4;
// filter out all data tags
tokens = PStringUtils::Split(workStr.Data(), " ,\t");
for (UInt_t i=1; i<tokens.size(); i++) {
runData.fDataNonMusr.AppendDataTag(TString(tokens[i]));
tokens = workStr.Tokenize(" ,\t");
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
runData.fDataNonMusr.AppendDataTag(ostr->GetString());
}
// clean up tokens
if (tokens) {
delete tokens;
tokens = nullptr;
}
continue;
}
@@ -3711,12 +3954,18 @@ Bool_t PRunDataHandler::ReadDBFile()
// check if first real data line
if (firstData) {
// check if data are given just as rows are as labelled columns (see description above)
tokens = PStringUtils::Split(workStr.Data(), ",");
if (!TString(tokens[0]).IsFloat()) {
tokens = workStr.Tokenize(",");
ostr = dynamic_cast<TObjString*>(tokens->At(0));
if (!ostr->GetString().IsFloat()) {
labelledFormat = true;
} else {
labelledFormat = false;
}
// clean up tokens
if (tokens) {
delete tokens;
tokens = nullptr;
}
// prepare data vector for use
PDoubleVector dummy;
@@ -3741,13 +3990,15 @@ Bool_t PRunDataHandler::ReadDBFile()
return false;
}
// split string in tokens
tokens = PStringUtils::Split(workStr.Data(), ","); // line has structure: runNo,,, runTitle
tstr = TString(tokens[0]);
tokens = workStr.Tokenize(","); // line has structure: runNo,,, runTitle
ostr = dynamic_cast<TObjString*>(tokens->At(0));
tstr = ostr->GetString();
if (!tstr.IsFloat()) {
std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
std::cerr << std::endl << ">> " << workStr.Data();
std::cerr << std::endl << ">> Expected db-data line with structure: runNo,,, runTitle";
std::cerr << std::endl << ">> runNo = " << tstr.Data() << ", seems to be not a number.";
delete tokens;
return false;
}
val = tstr.Atof();
@@ -3757,30 +4008,35 @@ Bool_t PRunDataHandler::ReadDBFile()
// remove all possible spaces
workStr.ReplaceAll(" ", "");
// split string in tokens
tokens = PStringUtils::Split(workStr.Data(), "=,"); // line has structure: tag = val,err1,err2,
if (tokens.size() < 3) {
tokens = workStr.Tokenize("=,"); // line has structure: tag = val,err1,err2,
if (tokens->GetEntries() < 3) {
std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
std::cerr << std::endl << ">> " << workStr.Data();
std::cerr << std::endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
delete tokens;
return false;
}
tstr = TString(tokens[0]);
ostr = dynamic_cast<TObjString*>(tokens->At(0));
tstr = ostr->GetString();
idx = GetDataTagIndex(tstr, runData.fDataNonMusr.GetDataTags());
if (idx == -1) {
std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
std::cerr << std::endl << ">> " << workStr.Data();
std::cerr << std::endl << ">> data tag error: " << tstr.Data() << " seems not present in the data tag list";
delete tokens;
return false;
}
switch (tokens.size()) {
switch (tokens->GetEntries()) {
case 3: // tag = val,,,
tstr = TString(tokens[1]);
ostr = dynamic_cast<TObjString*>(tokens->At(1));
tstr = ostr->GetString();
if (!tstr.IsFloat()) {
std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
std::cerr << std::endl << ">> " << workStr.Data();
std::cerr << std::endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
std::cerr << std::endl << ">> val = " << tstr.Data() << ", seems to be not a number.";
delete tokens;
return false;
}
val = tstr.Atof();
@@ -3790,23 +4046,27 @@ Bool_t PRunDataHandler::ReadDBFile()
case 4: // tag = val,err,,
case 5: // tag = val,err1,err2,
// handle val
tstr = TString(tokens[1]);
ostr = dynamic_cast<TObjString*>(tokens->At(1));
tstr = ostr->GetString();
if (!tstr.IsFloat()) {
std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
std::cerr << std::endl << ">> " << workStr.Data();
std::cerr << std::endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
std::cerr << std::endl << ">> val = " << tstr.Data() << ", seems to be not a number.";
delete tokens;
return false;
}
val = tstr.Atof();
runData.fDataNonMusr.AppendSubData(idx, val);
// handle err1 (err2 will be ignored for the time being)
tstr = TString(tokens[2]);
ostr = dynamic_cast<TObjString*>(tokens->At(2));
tstr = ostr->GetString();
if (!tstr.IsFloat()) {
std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
std::cerr << std::endl << ">> " << workStr.Data();
std::cerr << std::endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
std::cerr << std::endl << ">> err1 = " << tstr.Data() << ", seems to be not a number.";
delete tokens;
return false;
}
val = tstr.Atof();
@@ -3816,37 +4076,42 @@ Bool_t PRunDataHandler::ReadDBFile()
std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
std::cerr << std::endl << ">> " << workStr.Data();
std::cerr << std::endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
delete tokens;
return false;
}
}
} else { // handle row formated data
// split string in tokens
tokens = PStringUtils::Split(workStr.Data(), ","); // line has structure: val1, err11, err12, ..., valn, errn1, errn2, runNo, , , , runTitle
if (tokens.size() != 3*runData.fDataNonMusr.GetDataTags()->size()+1) {
tokens = workStr.Tokenize(","); // line has structure: val1, err11, err12, ..., valn, errn1, errn2, runNo, , , , runTitle
if (tokens->GetEntries() != static_cast<Int_t>(3*runData.fDataNonMusr.GetDataTags()->size()+1)) {
std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
std::cerr << std::endl << ">> " << workStr.Data();
std::cerr << std::endl << ">> Expected db-data line with structure: val1, err11, err12, ..., valn, errn1, errn2, runNo, , , , runTitle";
std::cerr << std::endl << ">> found = " << tokens.size() << " tokens, however expected " << 3*runData.fDataNonMusr.GetDataTags()->size()+1;
std::cerr << std::endl << ">> found = " << tokens->GetEntries() << " tokens, however expected " << 3*runData.fDataNonMusr.GetDataTags()->size()+1;
std::cerr << std::endl << ">> Perhaps there are commas without space inbetween, like 12.3,, 3.2,...";
delete tokens;
return false;
}
// extract data
Int_t j=0;
for (UInt_t i=0; i+1<tokens.size(); i+=3) {
for (Int_t i=0; i<tokens->GetEntries()-1; i+=3) {
// handle value
tstr = TString(tokens[i]);
ostr = dynamic_cast<TObjString*>(tokens->At(i));
tstr = ostr->GetString();
if (!tstr.IsFloat()) {
std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
std::cerr << std::endl << ">> " << workStr.Data();
std::cerr << std::endl << ">> Expected db-data line with structure: val1, err11, err12, ..., valn, errn1, errn2, runNo, , , , runTitle";
std::cerr << std::endl << ">> value=" << tstr.Data() << " seems not to be a number";
delete tokens;
return false;
}
runData.fDataNonMusr.AppendSubData(j, tstr.Atof());
// handle 1st error if present (2nd will be ignored for now)
tstr = TString(tokens[i+1]);
ostr = dynamic_cast<TObjString*>(tokens->At(i+1));
tstr = ostr->GetString();
if (tstr.IsWhitespace()) {
runData.fDataNonMusr.AppendSubErrData(j, 1.0);
} else if (tstr.IsFloat()) {
@@ -3856,6 +4121,7 @@ Bool_t PRunDataHandler::ReadDBFile()
std::cerr << std::endl << ">> " << workStr.Data();
std::cerr << std::endl << ">> Expected db-data line with structure: val1, err11, err12, ..., valn, errn1, errn2, runNo, , , , runTitle";
std::cerr << std::endl << ">> error1=" << tstr.Data() << " seems not to be a number";
delete tokens;
return false;
}
j++;
@@ -3875,6 +4141,10 @@ Bool_t PRunDataHandler::ReadDBFile()
std::cerr << std::endl << ">> number of LABELS found = " << runData.fDataNonMusr.GetLabels()->size();
std::cerr << std::endl << ">> number of Data tags found = " << runData.fDataNonMusr.GetDataTags()->size();
std::cerr << std::endl << ">> They have to be equal!!";
if (tokens) {
delete tokens;
tokens = nullptr;
}
return false;
}
@@ -3898,6 +4168,12 @@ Bool_t PRunDataHandler::ReadDBFile()
}
}
// clean up tokens
if (tokens) {
delete tokens;
tokens = nullptr;
}
// keep run name
runData.SetRunName(fRunName);
@@ -3942,7 +4218,8 @@ Bool_t PRunDataHandler::ReadDatFile()
// variables needed to tokenize strings
TString tstr;
std::vector<std::string> tokens;
TObjString *ostr;
TObjArray *tokens = nullptr;
UInt_t noOfDataSets = 0, noOfEntries = 0;
PBoolVector isData;
@@ -3962,8 +4239,8 @@ Bool_t PRunDataHandler::ReadDatFile()
if (line.IsWhitespace())
continue;
tokens = PStringUtils::Split(line.Data(), " \t");
if (tokens.empty()) { // error
tokens = line.Tokenize(" \t");
if (tokens == nullptr) { // error
std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** couldn't tokenize the line, in lineNo: " << lineNo;
std::cerr << std::endl << ">> line: '" << line << "'.";
std::cerr << std::endl;
@@ -3976,9 +4253,10 @@ Bool_t PRunDataHandler::ReadDatFile()
// filter out all data tags: this labels are used in the msr-file to select the proper data set
// for the dat-files, label and dataTag are the same
noOfEntries = tokens.size();
for (UInt_t i=0; i<noOfEntries; i++) {
tstr = TString(tokens[i]);
noOfEntries = tokens->GetEntries();
for (Int_t i=0; i<noOfEntries; i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
tstr = ostr->GetString();
if (!tstr.EndsWith("Err", TString::kExact)) {
noOfDataSets++;
isData.push_back(true);
@@ -3996,8 +4274,8 @@ Bool_t PRunDataHandler::ReadDatFile()
std::cerr << std::endl;
return false;
}
if (tokens.size() != noOfEntries) { // error
std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** data set with wrong number of entries: " << tokens.size() << ", should be " << noOfEntries << ".";
if (tokens->GetEntries() != noOfEntries) { // error
std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** data set with wrong number of entries: " << tokens->GetEntries() << ", should be " << noOfEntries << ".";
std::cerr << std::endl << ">> in line: " << lineNo;
std::cerr << std::endl << ">> line: '" << line << "'.";
std::cerr << std::endl;
@@ -4007,7 +4285,8 @@ Bool_t PRunDataHandler::ReadDatFile()
UInt_t idx = 0;
for (UInt_t i=0; i<noOfEntries; i++) {
// 1st: check that entry is indeed a number
tstr = TString(tokens[i]);
ostr = dynamic_cast<TObjString*>(tokens->At(i));
tstr = ostr->GetString();
if (!tstr.IsFloat()) { // make sure it is a number
std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** data set entry is not a number: " << tstr.Data();
std::cerr << std::endl << ">> in line: " << lineNo;
@@ -4031,6 +4310,11 @@ Bool_t PRunDataHandler::ReadDatFile()
}
}
}
// cleanup
if (tokens) {
delete tokens;
tokens = nullptr;
}
}
f.close();
@@ -6352,6 +6636,8 @@ TString PRunDataHandler::FileNameFromTemplate(TString &fileNameTemplate, Int_t r
{
TString result("");
TObjArray *tok=nullptr;
TObjString *ostr;
TString str;
// check year string
@@ -6374,18 +6660,19 @@ TString PRunDataHandler::FileNameFromTemplate(TString &fileNameTemplate, Int_t r
}
// tokenize template string
std::vector<std::string> tok = PStringUtils::Split(fileNameTemplate.Data(), "[]");
if (tok.empty()) {
tok = fileNameTemplate.Tokenize("[]");
if (tok == nullptr) {
std::cerr << std::endl << ">> PRunDataHandler::FileNameFromTemplate: **ERROR** couldn't tokenize template!" << std::endl;
return result;
}
if (tok.size()==1) {
if (tok->GetEntries()==1) {
std::cerr << std::endl << ">> PRunDataHandler::FileNameFromTemplate: **WARNING** template without tags." << std::endl;
}
// go through the tokens and generate the result string
for (UInt_t i=0; i<tok.size(); i++) {
str = TString(tok[i]);
for (Int_t i=0; i<tok->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tok->At(i));
str = ostr->GetString();
// check tokens
if (!str.CompareTo("yy", TString::kExact)) { // check for 'yy'
@@ -6413,6 +6700,10 @@ TString PRunDataHandler::FileNameFromTemplate(TString &fileNameTemplate, Int_t r
}
}
// clean up
if (tok)
delete tok;
// everything fine here
ok = true;
+23 -13
View File
@@ -36,12 +36,11 @@
#endif
#include <iostream>
#include <string>
#include <vector>
#include <TString.h>
#include <TObjArray.h>
#include <TObjString.h>
#include "PStringUtils.h"
#include "PRunMuMinus.h"
//--------------------------------------------------------------------------
@@ -384,7 +383,7 @@ Double_t PRunMuMinus::CalcMaxLikelihood(const std::vector<Double_t>& par)
Int_t chunk = (fEndTimeBin - fStartTimeBin)/omp_get_num_procs();
if (chunk < 10)
chunk = 10;
#pragma omp parallel for default(shared) private(i,time,theo,data) schedule(dynamic,chunk) reduction(+:mllh)
#pragma omp parallel for default(shared) private(i,time,theo,data) schedule(dynamic,chunk) reduction(-:mllh)
#endif
for (i=fStartTimeBin; i < fEndTimeBin; ++i) {
time = fData.GetDataTimeStart() + static_cast<Double_t>(i)*fData.GetDataTimeStep();
@@ -449,15 +448,18 @@ UInt_t PRunMuMinus::GetNoOfFitBins()
*/
void PRunMuMinus::SetFitRangeBin(const TString fitRange)
{
TObjArray *tok = nullptr;
TObjString *ostr = nullptr;
TString str;
Ssiz_t idx = -1;
Int_t offset = 0;
std::vector<std::string> tok = PStringUtils::Split(fitRange.Data(), " \t");
tok = fitRange.Tokenize(" \t");
if (tok.size() == 3) { // structure FIT_RANGE fgb+n0 lgb-n1
if (tok->GetEntries() == 3) { // structure FIT_RANGE fgb+n0 lgb-n1
// handle fgb+n0 entry
str = tok[1];
ostr = dynamic_cast<TObjString*>(tok->At(1));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("+");
if (idx != -1) { // offset present
@@ -468,7 +470,8 @@ void PRunMuMinus::SetFitRangeBin(const TString fitRange)
fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
// handle lgb-n1 entry
str = tok[2];
ostr = dynamic_cast<TObjString*>(tok->At(2));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("-");
if (idx != -1) { // offset present
@@ -477,15 +480,16 @@ void PRunMuMinus::SetFitRangeBin(const TString fitRange)
offset = str.Atoi();
}
fFitEndTime = (fGoodBins[1] - offset - fT0s[0]) * fTimeResolution;
} else if ((tok.size() > 3) && (tok.size() % 2 == 1)) { // structure FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
UInt_t pos = 2*(fRunNo+1)-1;
} else if ((tok->GetEntries() > 3) && (tok->GetEntries() % 2 == 1)) { // structure FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
Int_t pos = 2*(fRunNo+1)-1;
if (pos + 1 >= tok.size()) {
if (pos + 1 >= tok->GetEntries()) {
std::cerr << std::endl << ">> PRunMuMinus::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
} else {
// handle fgb+n0 entry
str = tok[pos];
ostr = dynamic_cast<TObjString*>(tok->At(pos));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("+");
if (idx != -1) { // offset present
@@ -496,7 +500,8 @@ void PRunMuMinus::SetFitRangeBin(const TString fitRange)
fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
// handle lgb-n1 entry
str = tok[pos+1];
ostr = dynamic_cast<TObjString*>(tok->At(pos+1));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("-");
if (idx != -1) { // offset present
@@ -510,6 +515,11 @@ void PRunMuMinus::SetFitRangeBin(const TString fitRange)
std::cerr << std::endl << ">> PRunMuMinus::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
}
// clean up
if (tok) {
delete tok;
}
}
//--------------------------------------------------------------------------
+36 -18
View File
@@ -38,13 +38,12 @@
#include <cmath>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <TString.h>
#include <TObjArray.h>
#include <TObjString.h>
#include "PMusr.h"
#include "PStringUtils.h"
#include "PRunSingleHisto.h"
//--------------------------------------------------------------------------
@@ -440,7 +439,7 @@ Double_t PRunSingleHisto::CalcChiSquareExpected(const std::vector<Double_t>& par
* <b>OpenMP Parallelization:</b>
* - Dynamic scheduling with chunk size = (N_bins / N_processors), minimum 10
* - Private variables per thread: i, time, theo, data
* - Reduction performed on mllh sum (reduction(+:mllh))
* - Reduction performed on mllh sum (note: reduction(-:mllh) for subtraction)
*
* <b>When to Use Maximum Likelihood vs. χ²:</b>
* - <b>Use likelihood:</b> Low count rates (< 100 counts/bin), asymmetric errors
@@ -516,7 +515,7 @@ Double_t PRunSingleHisto::CalcMaxLikelihood(const std::vector<Double_t>& par)
Int_t chunk = (fEndTimeBin - fStartTimeBin)/omp_get_num_procs();
if (chunk < 10)
chunk = 10;
#pragma omp parallel for default(shared) private(i,time,theo,data) schedule(dynamic,chunk) reduction(+:mllh)
#pragma omp parallel for default(shared) private(i,time,theo,data) schedule(dynamic,chunk) reduction(-:mllh)
#endif
for (i=fStartTimeBin; i<fEndTimeBin; ++i) {
time = fData.GetDataTimeStart() + static_cast<Double_t>(i)*fData.GetDataTimeStep();
@@ -651,7 +650,7 @@ Double_t PRunSingleHisto::CalcMaxLikelihoodExpected(const std::vector<Double_t>&
Int_t chunk = (fEndTimeBin - fStartTimeBin)/omp_get_num_procs();
if (chunk < 10)
chunk = 10;
#pragma omp parallel for default(shared) private(i,time,theo,data) schedule(dynamic,chunk) reduction(+:mllh)
#pragma omp parallel for default(shared) private(i,time,theo,data) schedule(dynamic,chunk) reduction(-:mllh)
#endif
for (i=fStartTimeBin; i<fEndTimeBin; ++i) {
time = fData.GetDataTimeStart() + static_cast<Double_t>(i)*fData.GetDataTimeStep();
@@ -845,15 +844,18 @@ UInt_t PRunSingleHisto::GetNoOfFitBins()
*/
void PRunSingleHisto::SetFitRangeBin(const TString fitRange)
{
TObjArray *tok = nullptr;
TObjString *ostr = nullptr;
TString str;
Ssiz_t idx = -1;
Int_t offset = 0;
std::vector<std::string> tok = PStringUtils::Split(fitRange.Data(), " \t");
tok = fitRange.Tokenize(" \t");
if (tok.size() == 3) { // structure FIT_RANGE fgb+n0 lgb-n1
if (tok->GetEntries() == 3) { // structure FIT_RANGE fgb+n0 lgb-n1
// handle fgb+n0 entry
str = tok[1];
ostr = dynamic_cast<TObjString*>(tok->At(1));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("+");
if (idx != -1) { // offset present
@@ -864,7 +866,8 @@ void PRunSingleHisto::SetFitRangeBin(const TString fitRange)
fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
// handle lgb-n1 entry
str = tok[2];
ostr = dynamic_cast<TObjString*>(tok->At(2));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("-");
if (idx != -1) { // offset present
@@ -873,15 +876,16 @@ void PRunSingleHisto::SetFitRangeBin(const TString fitRange)
offset = str.Atoi();
}
fFitEndTime = (fGoodBins[1] - offset - fT0s[0]) * fTimeResolution;
} else if ((tok.size() > 3) && (tok.size() % 2 == 1)) { // structure FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
UInt_t pos = 2*(fRunNo+1)-1;
} else if ((tok->GetEntries() > 3) && (tok->GetEntries() % 2 == 1)) { // structure FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
Int_t pos = 2*(fRunNo+1)-1;
if (pos + 1 >= tok.size()) {
if (pos + 1 >= tok->GetEntries()) {
std::cerr << std::endl << ">> PRunSingleHisto::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
} else {
// handle fgb+n0 entry
str = tok[pos];
ostr = dynamic_cast<TObjString*>(tok->At(pos));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("+");
if (idx != -1) { // offset present
@@ -892,7 +896,8 @@ void PRunSingleHisto::SetFitRangeBin(const TString fitRange)
fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
// handle lgb-n1 entry
str = tok[pos+1];
ostr = dynamic_cast<TObjString*>(tok->At(pos+1));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("-");
if (idx != -1) { // offset present
@@ -906,6 +911,11 @@ void PRunSingleHisto::SetFitRangeBin(const TString fitRange)
std::cerr << std::endl << ">> PRunSingleHisto::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
}
// clean up
if (tok) {
delete tok;
}
}
//--------------------------------------------------------------------------
@@ -2420,15 +2430,23 @@ Bool_t PRunSingleHisto::IsScaleN0AndBkg()
PMsrLines *cmd = fMsrInfo->GetMsrCommands();
for (UInt_t i=0; i<cmd->size(); i++) {
if (cmd->at(i).fLine.Contains("SCALE_N0_BKG", TString::kIgnoreCase)) {
std::vector<std::string> tokens = PStringUtils::Split(cmd->at(i).fLine.Data(), " \t");
if (tokens.size() != 2) {
TObjArray *tokens = nullptr;
TObjString *ostr = nullptr;
TString str;
tokens = cmd->at(i).fLine.Tokenize(" \t");
if (tokens->GetEntries() != 2) {
std::cerr << std::endl << ">> PRunSingleHisto::IsScaleN0AndBkg(): **WARNING** Found uncorrect 'SCALE_N0_BKG' command, will ignore it.";
std::cerr << std::endl << ">> Allowed commands: SCALE_N0_BKG TRUE | FALSE" << std::endl;
return willScale;
}
if (PStringUtils::IsEqualNoCase(tokens[1], "FALSE")) {
ostr = dynamic_cast<TObjString*>(tokens->At(1));
str = ostr->GetString();
if (!str.CompareTo("FALSE", TString::kIgnoreCase)) {
willScale = false;
}
// clean up
if (tokens)
delete tokens;
}
}
+22 -12
View File
@@ -39,14 +39,13 @@
#include <iostream>
#include <fstream>
#include <memory>
#include <string>
#include <vector>
#include <TString.h>
#include <TObjArray.h>
#include <TObjString.h>
#include <TH1F.h>
#include "PMusr.h"
#include "PStringUtils.h"
#include "PFourier.h"
#include "PRunSingleHistoRRF.h"
@@ -529,15 +528,18 @@ UInt_t PRunSingleHistoRRF::GetNoOfFitBins()
*/
void PRunSingleHistoRRF::SetFitRangeBin(const TString fitRange)
{
TObjArray *tok = nullptr;
TObjString *ostr = nullptr;
TString str;
Ssiz_t idx = -1;
Int_t offset = 0;
std::vector<std::string> tok = PStringUtils::Split(fitRange.Data(), " \t");
tok = fitRange.Tokenize(" \t");
if (tok.size() == 3) { // structure FIT_RANGE fgb+n0 lgb-n1
if (tok->GetEntries() == 3) { // structure FIT_RANGE fgb+n0 lgb-n1
// handle fgb+n0 entry
str = tok[1];
ostr = dynamic_cast<TObjString*>(tok->At(1));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("+");
if (idx != -1) { // offset present
@@ -548,7 +550,8 @@ void PRunSingleHistoRRF::SetFitRangeBin(const TString fitRange)
fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
// handle lgb-n1 entry
str = tok[2];
ostr = dynamic_cast<TObjString*>(tok->At(2));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("-");
if (idx != -1) { // offset present
@@ -557,15 +560,16 @@ void PRunSingleHistoRRF::SetFitRangeBin(const TString fitRange)
offset = str.Atoi();
}
fFitEndTime = (fGoodBins[1] - offset - fT0s[0]) * fTimeResolution;
} else if ((tok.size() > 3) && (tok.size() % 2 == 1)) { // structure FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
UInt_t pos = 2*(fRunNo+1)-1;
} else if ((tok->GetEntries() > 3) && (tok->GetEntries() % 2 == 1)) { // structure FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
Int_t pos = 2*(fRunNo+1)-1;
if (pos + 1 >= tok.size()) {
if (pos + 1 >= tok->GetEntries()) {
std::cerr << std::endl << ">> PRunSingleHistoRRF::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
} else {
// handle fgb+n0 entry
str = tok[pos];
ostr = dynamic_cast<TObjString*>(tok->At(pos));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("+");
if (idx != -1) { // offset present
@@ -576,7 +580,8 @@ void PRunSingleHistoRRF::SetFitRangeBin(const TString fitRange)
fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
// handle lgb-n1 entry
str = tok[pos+1];
ostr = dynamic_cast<TObjString*>(tok->At(pos+1));
str = ostr->GetString();
// check if there is an offset present
idx = str.First("-");
if (idx != -1) { // offset present
@@ -590,6 +595,11 @@ void PRunSingleHistoRRF::SetFitRangeBin(const TString fitRange)
std::cerr << std::endl << ">> PRunSingleHistoRRF::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
}
// clean up
if (tok) {
delete tok;
}
}
//--------------------------------------------------------------------------
+57 -38
View File
@@ -34,12 +34,13 @@
#include <iostream>
#include <fstream>
#include <TObjArray.h>
#include <TObjString.h>
#include <TColor.h>
#include <TList.h>
#include <TXMLAttr.h>
#include "PStartupHandler.h"
#include "PStringUtils.h"
ClassImpQ(PStartupHandler)
@@ -450,6 +451,8 @@ void PStartupHandler::OnEndElement(const Char_t *str)
*/
void PStartupHandler::OnCharacters(const Char_t *str)
{
TObjArray *tokens;
TObjString *ostr;
TString tstr;
Int_t color, r, g, b, ival;
@@ -478,44 +481,60 @@ void PStartupHandler::OnCharacters(const Char_t *str)
}
break;
case eColor:
{
// check that str is a rbg code
std::vector<std::string> rgb = PStringUtils::Split(str, ",");
// check there is the right number of tokens
if (rgb.size() != 3) {
std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a rbg code, will ignore it";
std::cerr << std::endl;
return;
}
// get r
if (PStringUtils::IsInt(rgb[0])) {
r = PStringUtils::ToInt(rgb[0]);
} else {
std::cerr << std::endl << "PStartupHandler **WARNING** r within the rgb code is not a number, will ignore it";
std::cerr << std::endl;
return;
}
// get g
if (PStringUtils::IsInt(rgb[1])) {
g = PStringUtils::ToInt(rgb[1]);
} else {
std::cerr << std::endl << "PStartupHandler **WARNING** g within the rgb code is not a number, will ignore it";
std::cerr << std::endl;
return;
}
// get b
if (PStringUtils::IsInt(rgb[2])) {
b = PStringUtils::ToInt(rgb[2]);
} else {
std::cerr << std::endl << "PStartupHandler **WARNING** b within the rgb code is not a number, will ignore it";
std::cerr << std::endl;
return;
}
// generate the ROOT color code based on str
color = TColor::GetColor(r,g,b);
// add the color code to the color list
fColorList.push_back(color);
// check that str is a rbg code
tstr = TString(str);
tokens = tstr.Tokenize(",");
// check that there any tokens
if (!tokens) {
std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a rbg code, will ignore it";
std::cerr << std::endl;
return;
}
// check there is the right number of tokens
if (tokens->GetEntries() != 3) {
std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a rbg code, will ignore it";
std::cerr << std::endl;
return;
}
// get r
ostr = dynamic_cast<TObjString*>(tokens->At(0));
tstr = ostr->GetString();
if (tstr.IsDigit()) {
r = tstr.Atoi();
} else {
std::cerr << std::endl << "PStartupHandler **WARNING** r within the rgb code is not a number, will ignore it";
std::cerr << std::endl;
return;
}
// get g
ostr = dynamic_cast<TObjString*>(tokens->At(1));
tstr = ostr->GetString();
if (tstr.IsDigit()) {
g = tstr.Atoi();
} else {
std::cerr << std::endl << "PStartupHandler **WARNING** g within the rgb code is not a number, will ignore it";
std::cerr << std::endl;
return;
}
// get b
ostr = dynamic_cast<TObjString*>(tokens->At(2));
tstr = ostr->GetString();
if (tstr.IsDigit()) {
b = tstr.Atoi();
} else {
std::cerr << std::endl << "PStartupHandler **WARNING** b within the rgb code is not a number, will ignore it";
std::cerr << std::endl;
return;
}
// clean up tokens
if (tokens) {
delete tokens;
tokens = nullptr;
}
// generate the ROOT color code based on str
color = TColor::GetColor(r,g,b);
// add the color code to the color list
fColorList.push_back(color);
break;
case eUnits:
tstr = TString(str);
-275
View File
@@ -1,275 +0,0 @@
/***************************************************************************
PStringUtils.cpp
Author: Andreas Suter
e-mail: andreas.suter@psi.ch
***************************************************************************/
/***************************************************************************
* Copyright (C) 2007-2026 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 <cctype>
#include <cerrno>
#include <charconv>
#include <cstdlib>
#include "PStringUtils.h"
//--------------------------------------------------------------------------
// Split (static)
//--------------------------------------------------------------------------
/**
* <p>Splits a string into tokens on any character contained in delimiters,
* skipping empty tokens. Mirrors the semantics of TString::Tokenize().
*
* \param str input string to be tokenized
* \param delimiters set of delimiter characters
* \return vector of tokens (without the delimiters)
*/
std::vector<std::string> PStringUtils::Split(const std::string &str, const std::string &delimiters)
{
std::vector<std::string> tokens;
std::string::size_type start = str.find_first_not_of(delimiters);
while (start != std::string::npos) {
std::string::size_type end = str.find_first_of(delimiters, start);
if (end == std::string::npos) {
tokens.push_back(str.substr(start));
break;
}
tokens.push_back(str.substr(start, end - start));
start = str.find_first_not_of(delimiters, end);
}
return tokens;
}
//--------------------------------------------------------------------------
// IsInt (static)
//--------------------------------------------------------------------------
/**
* <p>Returns true if the string is an integer literal, i.e. a non-empty
* sequence of decimal digits with an optional single leading sign (+/-).
* This is slightly more permissive than TString::IsDigit(), which rejects a
* sign, so that negative/positive integers such as "-5" or "+42" are also
* recognised.
*
* \param str string to be checked
* \return true if str is a (possibly signed) integer
*/
bool PStringUtils::IsInt(const std::string &str)
{
// all characters must be digits or whitespace, with an optional single
// leading sign (+/-) preceding the digits, and there must be at least one
// digit (surrounding/embedded whitespace is tolerated, e.g. for tokens
// split on ',' or ';' only).
bool hasDigit = false;
bool hasSign = false;
for (char c : str) {
if (std::isdigit(static_cast<unsigned char>(c))) {
hasDigit = true;
} else if (c == '+' || c == '-') {
// a sign is only valid before any digit and may appear at most once
if (hasDigit || hasSign)
return false;
hasSign = true;
} else if (!std::isspace(static_cast<unsigned char>(c))) {
return false;
}
}
return hasDigit;
}
//--------------------------------------------------------------------------
// IsFloat (static)
//--------------------------------------------------------------------------
/**
* <p>Returns true if the string is a complete integer or floating point
* literal (optionally signed, with decimal point and/or exponent). Mirrors
* the semantics of TString::IsFloat() for the relevant cases.
*
* \param str string to be checked
* \return true if str is a valid number
*/
bool PStringUtils::IsFloat(const std::string &str)
{
// mirror TString::IsFloat(): surrounding whitespace is ignored (e.g. for
// tokens split on ',' or ';' only), then a complete number is required.
const std::string ws(" \t\n\r\f\v");
std::string::size_type b = str.find_first_not_of(ws);
if (b == std::string::npos)
return false;
std::string::size_type e = str.find_last_not_of(ws);
const std::string t = str.substr(b, e - b + 1);
std::string::size_type i = 0;
if (t[i] == '+' || t[i] == '-')
++i;
// reject things like "inf"/"nan" which strtod would otherwise accept
if (i >= t.size() || !(std::isdigit(static_cast<unsigned char>(t[i])) || t[i] == '.'))
return false;
const char *begin = t.c_str();
char *end = nullptr;
std::strtod(begin, &end);
return end == begin + t.size();
}
//--------------------------------------------------------------------------
// ToInt (static)
//--------------------------------------------------------------------------
/**
* <p>Converts the leading part of the string to an int (base 10), mirroring
* TString::Atoi(). Returns 0 if no conversion is possible.
*
* <p>Uses std::from_chars so that conversion errors can be reported through
* the optional \a ok out-parameter: it is set to true when a valid integer
* was parsed (leading whitespace is skipped) and to false otherwise (no
* digits present, or the value is out of int range). Trailing non-numeric
* characters are ignored, as with TString::Atoi(). A null \a ok preserves the
* historic fire-and-forget behaviour.
*
* \param str string to be converted
* \param ok optional out-parameter signalling conversion success
* \return converted integer value (0 on error)
*/
int PStringUtils::ToInt(const std::string &str, bool *ok)
{
// mirror TString::Atoi(): skip leading whitespace, then parse the leading
// integer (a possible sign followed by decimal digits).
const char *begin = str.c_str();
const char *end = begin + str.size();
while (begin != end && std::isspace(static_cast<unsigned char>(*begin)))
++begin;
int value = 0;
const std::from_chars_result res = std::from_chars(begin, end, value);
if (ok != nullptr)
*ok = (res.ec == std::errc{});
return value;
}
//--------------------------------------------------------------------------
// ToDouble (static)
//--------------------------------------------------------------------------
/**
* <p>Converts the leading part of the string to a double, mirroring
* TString::Atof(). Returns 0.0 if no conversion is possible.
*
* <p>Like ToInt(), conversion errors can be reported through the optional
* \a ok out-parameter: it is set to true when a value was parsed and to
* false otherwise (no number present, or the value is out of range). This
* lets callers distinguish a legitimate 0.0 from a failed conversion.
* strtod() (rather than std::from_chars) is used so that the accepted input
* set stays identical to TString::Atof() (leading whitespace is skipped, a
* leading '+' is honoured, trailing characters are ignored). A null \a ok
* preserves the historic fire-and-forget behaviour.
*
* \param str string to be converted
* \param ok optional out-parameter signalling conversion success
* \return converted double value (0.0 on error)
*/
double PStringUtils::ToDouble(const std::string &str, bool *ok)
{
const char *begin = str.c_str();
char *end = nullptr;
errno = 0;
const double value = std::strtod(begin, &end);
if (ok != nullptr)
*ok = (end != begin) && (errno != ERANGE);
return value;
}
//--------------------------------------------------------------------------
// IsEqualNoCase (static)
//--------------------------------------------------------------------------
/**
* <p>Case-insensitive full-string equality, mirroring
* TString::CompareTo(..., TString::kIgnoreCase) == 0.
*
* \param a first string
* \param b second string
* \return true if a and b are equal ignoring case
*/
bool PStringUtils::IsEqualNoCase(const std::string &a, const std::string &b)
{
if (a.size() != b.size())
return false;
for (std::string::size_type i = 0; i < a.size(); ++i) {
if (std::tolower(static_cast<unsigned char>(a[i])) !=
std::tolower(static_cast<unsigned char>(b[i])))
return false;
}
return true;
}
//--------------------------------------------------------------------------
// ContainsNoCase (static)
//--------------------------------------------------------------------------
/**
* <p>Case-insensitive substring search, mirroring
* TString::Contains(..., TString::kIgnoreCase).
*
* \param haystack string to be searched in
* \param needle substring to be searched for
* \return true if needle is contained in haystack ignoring case
*/
bool PStringUtils::ContainsNoCase(const std::string &haystack, const std::string &needle)
{
if (needle.empty())
return true;
if (needle.size() > haystack.size())
return false;
auto toLower = [](unsigned char c) { return std::tolower(c); };
for (std::string::size_type i = 0; i + needle.size() <= haystack.size(); ++i) {
std::string::size_type j = 0;
for (; j < needle.size(); ++j) {
if (toLower(haystack[i+j]) != toLower(needle[j]))
break;
}
if (j == needle.size())
return true;
}
return false;
}
//--------------------------------------------------------------------------
// BeginsWithNoCase (static)
//--------------------------------------------------------------------------
/**
* <p>Case-insensitive prefix test, mirroring
* TString::BeginsWith(..., TString::kIgnoreCase).
*
* \param str string to be tested
* \param prefix prefix to be searched for
* \return true if str starts with prefix ignoring case
*/
bool PStringUtils::BeginsWithNoCase(const std::string &str, const std::string &prefix)
{
if (prefix.size() > str.size())
return false;
for (std::string::size_type i = 0; i < prefix.size(); ++i) {
if (std::tolower(static_cast<unsigned char>(str[i])) !=
std::tolower(static_cast<unsigned char>(prefix[i])))
return false;
}
return true;
}
+72 -24
View File
@@ -29,19 +29,19 @@
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <TObject.h>
#include <TString.h>
#include <TF1.h>
#include <TObjString.h>
#include <TObjArray.h>
#include <TClass.h>
#include <TMath.h>
#include <Math/SpecFuncMathMore.h>
#include "PMsrHandler.h"
#include "PStringUtils.h"
#include "PTheory.h"
#define SQRT_TWO 1.41421356237
@@ -169,14 +169,18 @@ PTheory::PTheory(PMsrHandler *msrInfo, UInt_t runNo, const Bool_t hasParent) : f
str.Resize(index);
// tokenize line
std::vector<std::string> tokens = PStringUtils::Split(str.Data(), " \t");
if (tokens.empty()) {
TObjArray *tokens;
TObjString *ostr;
tokens = str.Tokenize(" \t");
if (!tokens) {
std::cerr << std::endl << ">> PTheory::PTheory: **SEVERE ERROR** Couldn't tokenize theory block line " << line->fLineNo << ".";
std::cerr << std::endl << ">> line content: " << line->fLine.Data();
std::cerr << std::endl;
exit(0);
}
str = tokens[0];
ostr = dynamic_cast<TObjString*>(tokens->At(0));
str = ostr->GetString();
// search the theory function
UInt_t idx = SearchDataBase(str);
@@ -191,11 +195,11 @@ PTheory::PTheory(PMsrHandler *msrInfo, UInt_t runNo, const Bool_t hasParent) : f
}
// line is a valid function, hence analyze parameters
if ((static_cast<UInt_t>(tokens.size()-1) < fNoOfParam) &&
if ((static_cast<UInt_t>(tokens->GetEntries()-1) < fNoOfParam) &&
((idx != THEORY_USER_FCN) && (idx != THEORY_POLYNOM))) {
std::cerr << std::endl << ">> PTheory::PTheory: **ERROR** Theory line '" << line->fLine.Data() << "'";
std::cerr << std::endl << ">> in line no " << line->fLineNo;
std::cerr << std::endl << ">> expecting " << fgTheoDataBase[idx].fNoOfParam << ", but found " << tokens.size()-1;
std::cerr << std::endl << ">> expecting " << fgTheoDataBase[idx].fNoOfParam << ", but found " << tokens->GetEntries()-1;
std::cerr << std::endl;
fValid = false;
}
@@ -205,8 +209,9 @@ PTheory::PTheory(PMsrHandler *msrInfo, UInt_t runNo, const Bool_t hasParent) : f
Int_t status;
UInt_t value;
Bool_t ok = false;
for (UInt_t i=1; i<tokens.size(); i++) {
str = tokens[i];
for (Int_t i=1; i<tokens->GetEntries(); i++) {
ostr = dynamic_cast<TObjString*>(tokens->At(i));
str = ostr->GetString();
// if userFcn, the first entry is the function name and needs to be handled specially
if ((fType == THEORY_USER_FCN) && ((i == 1) || (i == 2))) {
@@ -299,6 +304,11 @@ PTheory::PTheory(PMsrHandler *msrInfo, UInt_t runNo, const Bool_t hasParent) : f
std::cerr << std::endl << ">> See line no " << line->fLineNo;
std::cerr << std::endl;
fValid = false;
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
return;
} else if (!TClass::GetDict(fUserFcnClassName.Data())) {
std::cerr << std::endl << ">> PTheory::PTheory: **ERROR** user function class '" << fUserFcnClassName.Data() << "' not found.";
@@ -306,6 +316,11 @@ PTheory::PTheory(PMsrHandler *msrInfo, UInt_t runNo, const Bool_t hasParent) : f
std::cerr << std::endl << ">> See line no " << line->fLineNo;
std::cerr << std::endl;
fValid = false;
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
return;
}
}
@@ -332,6 +347,12 @@ PTheory::PTheory(PMsrHandler *msrInfo, UInt_t runNo, const Bool_t hasParent) : f
}
}
}
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
}
//--------------------------------------------------------------------------
@@ -924,6 +945,8 @@ void PTheory::MakeCleanAndTidyTheoryBlock(PMsrLines *fullTheoryBlock)
PMsrLineStructure *line;
TString str, tidy;
Char_t substr[256];
TObjArray *tokens = nullptr;
TObjString *ostr = nullptr;
Int_t idx = THEORY_UNDEFINED;
for (UInt_t i=1; i<fullTheoryBlock->size(); i++) {
@@ -936,11 +959,10 @@ void PTheory::MakeCleanAndTidyTheoryBlock(PMsrLines *fullTheoryBlock)
if (index > 0) // theory line comment present
str.Resize(index);
// tokenize line
std::vector<std::string> tokens = PStringUtils::Split(str.Data(), " \t");
if (tokens.empty())
continue;
tokens = str.Tokenize(" \t");
// make a handable string out of the asymmetry token
str = tokens[0];
ostr = dynamic_cast<TObjString*>(tokens->At(0));
str = ostr->GetString();
// check if the line is just a '+' if so nothing to be done
if (str.Contains("+"))
continue;
@@ -965,13 +987,14 @@ void PTheory::MakeCleanAndTidyTheoryBlock(PMsrLines *fullTheoryBlock)
if (idx == THEORY_UNDEFINED)
return;
// check that there enough tokens. This should not be necessay at this point but ...
if (static_cast<UInt_t>(tokens.size()) < fgTheoDataBase[idx].fNoOfParam + 1)
if (static_cast<UInt_t>(tokens->GetEntries()) < fgTheoDataBase[idx].fNoOfParam + 1)
return;
// make tidy string
snprintf(substr, sizeof(substr), "%-10s", fgTheoDataBase[idx].fName.Data());
tidy = TString(substr);
for (UInt_t j=1; j<tokens.size(); j++) {
str = tokens[j];
for (Int_t j=1; j<tokens->GetEntries(); j++) {
ostr = dynamic_cast<TObjString*>(tokens->At(j));
str = ostr->GetString();
snprintf(substr, sizeof(substr), "%6s", str.Data());
tidy += TString(substr);
}
@@ -982,13 +1005,19 @@ void PTheory::MakeCleanAndTidyTheoryBlock(PMsrLines *fullTheoryBlock)
} else {
tidy += TString(" ");
}
if (static_cast<UInt_t>(tokens.size()) == fgTheoDataBase[idx].fNoOfParam + 1) // no tshift
if (static_cast<UInt_t>(tokens->GetEntries()) == fgTheoDataBase[idx].fNoOfParam + 1) // no tshift
tidy += fgTheoDataBase[idx].fComment;
else
tidy += fgTheoDataBase[idx].fCommentTimeShift;
}
// write tidy string back into theory block
(*fullTheoryBlock)[i].fLine = tidy;
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
}
}
@@ -1012,6 +1041,8 @@ void PTheory::MakeCleanAndTidyPolynom(UInt_t i, PMsrLines *fullTheoryBlock)
{
PMsrLineStructure *line;
TString str, tidy;
TObjArray *tokens = nullptr;
TObjString *ostr;
Char_t substr[256];
// init tidy
@@ -1021,12 +1052,13 @@ void PTheory::MakeCleanAndTidyPolynom(UInt_t i, PMsrLines *fullTheoryBlock)
// copy line content to str in order to remove comments
str = line->fLine.Copy();
// tokenize line
std::vector<std::string> tokens = PStringUtils::Split(str.Data(), " \t");
tokens = str.Tokenize(" \t");
// check if comment is already present, and if yes ignore it by setting max correctly
Int_t max = static_cast<Int_t>(tokens.size());
Int_t max = tokens->GetEntries();
for (Int_t j=1; j<max; j++) {
str = tokens[j];
ostr = dynamic_cast<TObjString*>(tokens->At(j));
str = ostr->GetString();
if (str.Contains("(")) { // comment present
max=j;
break;
@@ -1034,7 +1066,8 @@ void PTheory::MakeCleanAndTidyPolynom(UInt_t i, PMsrLines *fullTheoryBlock)
}
for (Int_t j=1; j<max; j++) {
str = tokens[j];
ostr = dynamic_cast<TObjString*>(tokens->At(j));
str = ostr->GetString();
snprintf(substr, sizeof(substr), "%6s", str.Data());
tidy += TString(substr);
}
@@ -1044,6 +1077,12 @@ void PTheory::MakeCleanAndTidyPolynom(UInt_t i, PMsrLines *fullTheoryBlock)
// write tidy string back into theory block
(*fullTheoryBlock)[i].fLine = tidy;
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
}
//--------------------------------------------------------------------------
@@ -1065,6 +1104,8 @@ void PTheory::MakeCleanAndTidyUserFcn(UInt_t i, PMsrLines *fullTheoryBlock)
{
PMsrLineStructure *line;
TString str, tidy;
TObjArray *tokens = nullptr;
TObjString *ostr;
// init tidy
tidy = TString("userFcn ");
@@ -1073,15 +1114,22 @@ void PTheory::MakeCleanAndTidyUserFcn(UInt_t i, PMsrLines *fullTheoryBlock)
// copy line content to str in order to remove comments
str = line->fLine.Copy();
// tokenize line
std::vector<std::string> tokens = PStringUtils::Split(str.Data(), " \t");
tokens = str.Tokenize(" \t");
for (UInt_t j=1; j<tokens.size(); j++) {
str = tokens[j];
for (Int_t j=1; j<tokens->GetEntries(); j++) {
ostr = dynamic_cast<TObjString*>(tokens->At(j));
str = ostr->GetString();
tidy += TString(" ") + str;
}
// write tidy string back into theory block
(*fullTheoryBlock)[i].fLine = tidy;
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
}
//--------------------------------------------------------------------------
+1 -2
View File
@@ -102,8 +102,7 @@ static inline void SobolIni(This *t)
int inibits = -1, bit;
for( j = powers; j; j >>= 1 ) ++inibits;
if( inibits > 0 )
memcpy(pv, pini, inibits*sizeof *pini);
memcpy(pv, pini, inibits*sizeof *pini);
pini += 8;
for( bit = inibits; bit <= nbits; ++bit ) {
-150
View File
@@ -1,150 +0,0 @@
/***************************************************************************
PStringUtils.h
Author: Andreas Suter
e-mail: andreas.suter@psi.ch
***************************************************************************/
/***************************************************************************
* Copyright (C) 2007-2026 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. *
***************************************************************************/
#ifndef _PSTRINGUTILS_H_
#define _PSTRINGUTILS_H_
#include <string>
#include <vector>
//-------------------------------------------------------------
/**
* \brief Lightweight, dependency-free string utilities (pure C++17).
*
* PStringUtils collects small string helpers used throughout the musrfit
* suite, in particular for tokenizing and parsing the plain-text MSR file
* format. The implementation deliberately relies only on the C++ standard
* library (no ROOT) so that it can be reused freely.
*
* The provided helpers replicate the semantics of the corresponding
* ROOT TString methods that were previously used:
* - Split replaces TString::Tokenize() (+ TObjArray/TObjString)
* - IsInt replaces TString::IsDigit()
* - IsFloat replaces TString::IsFloat()
* - ToInt replaces TString::Atoi()
* - ToDouble replaces TString::Atof()
* - IsEqualNoCase replaces TString::CompareTo(..., TString::kIgnoreCase)
*
* All methods are static; the class is a pure namespace-like utility.
*/
class PStringUtils
{
public:
/**
* <p>Splits a string into tokens on any character contained in
* delimiters, skipping empty tokens. Mirrors TString::Tokenize().
*
* @param str input string to be tokenized
* @param delimiters set of delimiter characters
* @return vector of tokens (without the delimiters)
*/
static std::vector<std::string> Split(const std::string &str, const std::string &delimiters);
/**
* <p>Returns true if the string is a (possibly signed) integer literal,
* i.e. a non-empty sequence of decimal digits with an optional single
* leading sign (+/-). Slightly more permissive than TString::IsDigit(),
* which rejects a sign, so that e.g. "-5" is also recognised.
*
* @param str string to be checked
* @return true if str is a (possibly signed) integer
*/
static bool IsInt(const std::string &str);
/**
* <p>Returns true if the string is a complete integer or floating point
* literal (optionally signed, with decimal point and/or exponent).
* Mirrors TString::IsFloat() for the relevant cases.
*
* @param str string to be checked
* @return true if str is a valid number
*/
static bool IsFloat(const std::string &str);
/**
* <p>Converts the leading part of the string to an int (base 10).
* Mirrors TString::Atoi(). Returns 0 if no conversion is possible.
*
* <p>If \a ok is non-null it is set to true when a valid integer was
* parsed and to false on error (no digits, or value out of int range).
* This allows callers to distinguish a legitimate 0 from a failed
* conversion, which the bare return value cannot express.
*
* @param str string to be converted
* @param ok optional out-parameter signalling conversion success
* @return converted integer value (0 on error)
*/
static int ToInt(const std::string &str, bool *ok = nullptr);
/**
* <p>Converts the leading part of the string to a double.
* Mirrors TString::Atof(). Returns 0.0 if no conversion is possible.
*
* <p>If \a ok is non-null it is set to true when a value was parsed and
* to false on error (no number, or value out of range), allowing callers
* to distinguish a legitimate 0.0 from a failed conversion.
*
* @param str string to be converted
* @param ok optional out-parameter signalling conversion success
* @return converted double value (0.0 on error)
*/
static double ToDouble(const std::string &str, bool *ok = nullptr);
/**
* <p>Case-insensitive full-string equality.
* Mirrors TString::CompareTo(..., TString::kIgnoreCase) == 0.
*
* @param a first string
* @param b second string
* @return true if a and b are equal ignoring case
*/
static bool IsEqualNoCase(const std::string &a, const std::string &b);
/**
* <p>Case-insensitive substring search.
* Mirrors TString::Contains(..., TString::kIgnoreCase).
*
* @param haystack string to be searched in
* @param needle substring to be searched for
* @return true if needle is contained in haystack ignoring case
*/
static bool ContainsNoCase(const std::string &haystack, const std::string &needle);
/**
* <p>Case-insensitive prefix test.
* Mirrors TString::BeginsWith(..., TString::kIgnoreCase).
*
* @param str string to be tested
* @param prefix prefix to be searched for
* @return true if str starts with prefix ignoring case
*/
static bool BeginsWithNoCase(const std::string &str, const std::string &prefix);
};
#endif // _PSTRINGUTILS_H_
+86 -52
View File
@@ -35,8 +35,8 @@
#include <cstdlib>
#include <TString.h>
#include "PStringUtils.h"
#include <TObjArray.h>
#include <TObjString.h>
//-------------------------------------------------------------
// msr block header tags
@@ -88,6 +88,8 @@ bool msr2msr_run(char *str, const std::size_t size)
TString run(str);
TString line(str);
TObjArray *tokens;
TObjString *ostr[2];
// for filtering
run.ToUpper();
@@ -98,8 +100,8 @@ bool msr2msr_run(char *str, const std::size_t size)
line.Remove(idx);
// tokenize run
std::vector<std::string> tokens = PStringUtils::Split(line.Data(), " \t");
if (tokens.size() < 4) {
tokens = line.Tokenize(" \t");
if (tokens->GetEntries() < 4) {
std::cout << std::endl << "**ERROR**: Something is wrong with the RUN block header:";
std::cout << std::endl << " >> " << str;
std::cout << std::endl << " >> no <msr-file-out> is created";
@@ -107,22 +109,35 @@ bool msr2msr_run(char *str, const std::size_t size)
return false;
}
if (tokens.size() == 5) { // already a new msr file, do only add the proper run comment
if (tokens->GetEntries() == 5) { // already a new msr file, do only add the proper run comment
snprintf(str, size, "%s (name beamline institute data-file-format)", line.Data());
return true;
}
if (run.Contains("NEMU")) {
snprintf(str, size, "RUN %s MUE4 PSI WKM (name beamline institute data-file-format)", tokens[1].c_str());
ostr[0] = dynamic_cast<TObjString*>(tokens->At(1)); // file name
snprintf(str, size, "RUN %s MUE4 PSI WKM (name beamline institute data-file-format)", ostr[0]->GetString().Data());
} else if (run.Contains("PSI")) {
ostr[0] = dynamic_cast<TObjString*>(tokens->At(1)); // file name
ostr[1] = dynamic_cast<TObjString*>(tokens->At(2)); // beamline
snprintf(str, size, "RUN %s %s PSI PSI-BIN (name beamline institute data-file-format)",
tokens[1].c_str(), tokens[2].c_str());
ostr[0]->GetString().Data(), ostr[1]->GetString().Data());
} else if (run.Contains("TRIUMF")) {
ostr[0] = dynamic_cast<TObjString*>(tokens->At(1)); // file name
ostr[1] = dynamic_cast<TObjString*>(tokens->At(2)); // beamline
snprintf(str, size, "RUN %s %s TRIUMF MUD (name beamline institute data-file-format)",
tokens[1].c_str(), tokens[2].c_str());
ostr[0]->GetString().Data(), ostr[1]->GetString().Data());
} else if (run.Contains("RAL")) {
ostr[0] = dynamic_cast<TObjString*>(tokens->At(1)); // file name
ostr[1] = dynamic_cast<TObjString*>(tokens->At(2)); // beamline
snprintf(str, size, "RUN %s %s RAL NEXUS (name beamline institute data-file-format)",
tokens[1].c_str(), tokens[2].c_str());
ostr[0]->GetString().Data(), ostr[1]->GetString().Data());
}
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
return true;
@@ -150,34 +165,38 @@ bool msr2msr_param(char *str)
// handle parameter line
TString line(str);
TObjArray *tokens;
TObjString *ostr[6];
char sstr[256];
char spaces[256];
std::vector<std::string> tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
if (noTokens == 4) {
for (unsigned int i=0; i<4; i++)
ostr[i] = dynamic_cast<TObjString*>(tokens->At(i));
// number
snprintf(sstr, sizeof(sstr), "%10s", tokens[0].c_str());
snprintf(sstr, sizeof(sstr), "%10s", ostr[0]->GetString().Data());
// name
strcat(sstr, " ");
strcat(sstr, tokens[1].c_str());
strcat(sstr, ostr[1]->GetString().Data());
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 12-strlen(tokens[1].c_str()));
memset(spaces, ' ', 12-strlen(ostr[1]->GetString().Data()));
strcat(sstr, spaces);
// value
strcat(sstr, tokens[2].c_str());
if (strlen(tokens[2].c_str()) < 10) {
strcat(sstr, ostr[2]->GetString().Data());
if (strlen(ostr[2]->GetString().Data()) < 10) {
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 10-strlen(tokens[2].c_str()));
memset(spaces, ' ', 10-strlen(ostr[2]->GetString().Data()));
strcat(sstr, spaces);
} else {
strcat(sstr, " ");
}
// step
strcat(sstr, tokens[3].c_str());
if (strlen(tokens[3].c_str()) < 12) {
strcat(sstr, ostr[3]->GetString().Data());
if (strlen(ostr[3]->GetString().Data()) < 12) {
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 12-strlen(tokens[3].c_str()));
memset(spaces, ' ', 12-strlen(ostr[3]->GetString().Data()));
strcat(sstr, spaces);
} else {
strcat(sstr, " ");
@@ -185,28 +204,30 @@ bool msr2msr_param(char *str)
strcat(sstr, "none");
strcpy(str, sstr);
} else if (noTokens == 6) {
for (unsigned int i=0; i<6; i++)
ostr[i] = dynamic_cast<TObjString*>(tokens->At(i));
// number
snprintf(sstr, sizeof(sstr), "%10s", tokens[0].c_str());
snprintf(sstr, sizeof(sstr), "%10s", ostr[0]->GetString().Data());
// name
strcat(sstr, " ");
strcat(sstr, tokens[1].c_str());
strcat(sstr, ostr[1]->GetString().Data());
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 12-strlen(tokens[1].c_str()));
memset(spaces, ' ', 12-strlen(ostr[1]->GetString().Data()));
strcat(sstr, spaces);
// value
strcat(sstr, tokens[2].c_str());
if (strlen(tokens[2].c_str()) < 10) {
strcat(sstr, ostr[2]->GetString().Data());
if (strlen(ostr[2]->GetString().Data()) < 10) {
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 10-strlen(tokens[2].c_str()));
memset(spaces, ' ', 10-strlen(ostr[2]->GetString().Data()));
strcat(sstr, spaces);
} else {
strcat(sstr, " ");
}
// step
strcat(sstr, tokens[3].c_str());
if (strlen(tokens[3].c_str()) < 12) {
strcat(sstr, ostr[3]->GetString().Data());
if (strlen(ostr[3]->GetString().Data()) < 12) {
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 12-strlen(tokens[3].c_str()));
memset(spaces, ' ', 12-strlen(ostr[3]->GetString().Data()));
strcat(sstr, spaces);
} else {
strcat(sstr, " ");
@@ -214,19 +235,25 @@ bool msr2msr_param(char *str)
// pos. error
strcat(sstr, "none ");
// lower boundary
strcat(sstr, tokens[4].c_str());
if (strlen(tokens[4].c_str()) < 8) {
strcat(sstr, ostr[4]->GetString().Data());
if (strlen(ostr[4]->GetString().Data()) < 8) {
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 8-strlen(tokens[4].c_str()));
memset(spaces, ' ', 8-strlen(ostr[4]->GetString().Data()));
strcat(sstr, spaces);
} else {
strcat(sstr, " ");
}
// upper boundary
strcat(sstr, tokens[5].c_str());
strcat(sstr, ostr[5]->GetString().Data());
strcpy(str, sstr);
}
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
return true;
}
@@ -247,7 +274,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
{
// handle theory line
TString line(str);
std::vector<std::string> tokens;
TObjArray *tokens;
TObjString *ostr;
char sstr[256];
if ((line.Contains("sktt") || line.Contains("statKTTab")) && line.Contains("glf")) { // static Gauss KT LF table
@@ -255,8 +283,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcpy(sstr, "statGssKTLF ");
// tokenize the rest and extract the first two parameters
tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
if (noTokens < 3) {
std::cout << std::endl << "**ERROR** in THEORY block";
std::cout << std::endl << " Line: '" << str << "' is not a valid statKTTab statement.";
@@ -265,7 +293,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
}
for (Int_t i=1; i<3; i++) {
strcat(sstr, " ");
strcat(sstr, tokens[i].c_str());
ostr = dynamic_cast<TObjString*>(tokens->At(i));
strcat(sstr, ostr->GetString().Data());
}
strcat(sstr, " (frequency damping)");
strcpy(str, sstr);
@@ -274,8 +303,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcpy(sstr, "statExpKTLF ");
// tokenize the rest and extract the first two parameters
tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
if (noTokens < 3) {
std::cout << std::endl << "**ERROR** in THEORY block";
std::cout << std::endl << " Line: '" << str << "' is not a valid statKTTab statement.";
@@ -284,7 +313,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
}
for (Int_t i=1; i<3; i++) {
strcat(sstr, " ");
strcat(sstr, tokens[i].c_str());
ostr = dynamic_cast<TObjString*>(tokens->At(i));
strcat(sstr, ostr->GetString().Data());
}
strcat(sstr, " (frequency damping)");
strcpy(str, sstr);
@@ -293,8 +323,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcpy(sstr, "dynGssKTLF ");
// tokenize the rest and extract the first three parameters
tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
if (noTokens < 4) {
std::cout << std::endl << "**ERROR** in THEORY block";
std::cout << std::endl << " Line: '" << str << "' is not a valid dynmKTTab statement.";
@@ -303,7 +333,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
}
for (Int_t i=1; i<4; i++) {
strcat(sstr, " ");
strcat(sstr, tokens[i].c_str());
ostr = dynamic_cast<TObjString*>(tokens->At(i));
strcat(sstr, ostr->GetString().Data());
}
strcat(sstr, " (frequency damping hopping-rate)");
strcpy(str, sstr);
@@ -312,8 +343,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcpy(sstr, "dynExpKTLF ");
// tokenize the rest and extract the first three parameters
tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
if (noTokens < 4) {
std::cout << std::endl << "**ERROR** in THEORY block";
std::cout << std::endl << " Line: '" << str << "' is not a valid dynmKTTab statement.";
@@ -322,7 +353,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
}
for (Int_t i=1; i<4; i++) {
strcat(sstr, " ");
strcat(sstr, tokens[i].c_str());
ostr = dynamic_cast<TObjString*>(tokens->At(i));
strcat(sstr, ostr->GetString().Data());
}
strcat(sstr, " (frequency damping hopping-rate)");
strcpy(str, sstr);
@@ -334,8 +366,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcpy(sstr, "internFld ");
// tokenize the rest and extract the first three parameters
tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
if (noTokens < 4) {
std::cout << std::endl << "**ERROR** in THEORY block";
std::cout << std::endl << " Line: '" << str << "' is not a valid internFld statement.";
@@ -345,7 +377,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcat(sstr, " _x_");
for (Int_t i=1; i<4; i++) {
strcat(sstr, " ");
strcat(sstr, tokens[i].c_str());
ostr = dynamic_cast<TObjString*>(tokens->At(i));
strcat(sstr, ostr->GetString().Data());
}
strcat(sstr, " (fraction phase frequency Trate Lrate)");
strcpy(str, sstr);
@@ -357,8 +390,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcpy(sstr, "internBsl ");
// tokenize the rest and extract the first three parameters
tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
if (noTokens < 4) {
std::cout << std::endl << "**ERROR** in THEORY block";
std::cout << std::endl << " Line: '" << str << "' is not a valid internBsl statement.";
@@ -368,7 +401,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcat(sstr, " _x_");
for (Int_t i=1; i<4; i++) {
strcat(sstr, " ");
strcat(sstr, tokens[i].c_str());
ostr = dynamic_cast<TObjString*>(tokens->At(i));
strcat(sstr, ostr->GetString().Data());
}
strcat(sstr, " (fraction phase frequency Trate Lrate)");
strcpy(str, sstr);
+13 -6
View File
@@ -36,12 +36,13 @@
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <memory>
#include <TApplication.h>
#include <TROOT.h>
#include <TString.h>
#include <TObjArray.h>
#include <TObjString.h>
#include <TSAXParser.h>
#ifdef HAVE_GIT_REV_H
@@ -49,7 +50,6 @@
#endif
#include "PMusr.h"
#include "PStringUtils.h"
#include "PStartupHandler.h"
#include "PMsrHandler.h"
#include "PRunDataHandler.h"
@@ -234,15 +234,17 @@ Bool_t musrFT_filter_histo(Int_t &i, Int_t argc, Char_t *argv[], musrFT_startup_
return false;
}
} else { // should be something like h0-hN with h0, hN numbers
std::vector<std::string> tok = PStringUtils::Split(tstr.Data(), "-");
if (tok.size() != 2) {
TObjArray *tok = tstr.Tokenize("-");
if (tok->GetEntries() != 2) {
std::cerr << std::endl << ">> musrFT **ERROR** found --histo argument '" << tstr << "' which is not of the form <h0>-<hN>." << std::endl;
startupParam.histo.clear();
return false;
}
TObjString *ostr;
TString sstr("");
Int_t first=0, last=0;
sstr = tok[0];
ostr = dynamic_cast<TObjString*>(tok->At(0));
sstr = ostr->GetString();
if (sstr.IsDigit()) {
first = sstr.Atoi();
} else {
@@ -251,7 +253,8 @@ Bool_t musrFT_filter_histo(Int_t &i, Int_t argc, Char_t *argv[], musrFT_startup_
startupParam.histo.clear();
return false;
}
sstr = tok[1];
ostr = dynamic_cast<TObjString*>(tok->At(1));
sstr = ostr->GetString();
if (sstr.IsDigit()) {
last = sstr.Atoi();
} else {
@@ -270,6 +273,10 @@ Bool_t musrFT_filter_histo(Int_t &i, Int_t argc, Char_t *argv[], musrFT_startup_
for (Int_t k=first; k<=last; k++) {
startupParam.histo.push_back(k);
}
// clean up
if (tok)
delete tok;
}
}
+10
View File
@@ -168,6 +168,8 @@ bool PAdminXMLParser::startElement()
fKeyWord = eEstimateN0;
} else if (qName == "yaml_out") {
fKeyWord = eYamlOut;
} else if (qName == "use_no_of_threads") {
fKeyWord = eNoOfTreadsToBeUsed;
} else if (qName == "chisq_per_run_block") {
fKeyWord = eChisqPreRunBlock;
} else if (qName == "path_file_name") {
@@ -420,6 +422,11 @@ bool PAdminXMLParser::characters()
fAdmin->fMsr2DataParam.perRunBlockChisq = flag;
fAdmin->setChisqPerRunBlockFlag(flag);
break;
case eNoOfTreadsToBeUsed:
ival = QString(str.toLatin1()).trimmed().toInt(&ok);
if (ok)
fAdmin->setNoOfThreadsToBeUsed(ival);
break;
case eRecentFile:
fAdmin->addRecentFile(QString(str.toLatin1()).trimmed());
break;
@@ -988,6 +995,9 @@ int PAdmin::savePrefs(QString pref_fln)
else
data[i] = " <yaml_out>n</yaml_out>";
}
if (data[i].contains("<use_no_of_threads>") && data[i].contains("</use_no_of_threads>")) {
data[i] = " <use_no_of_threads>" + QString("%1").arg(fNoOfThreadsToBeUsed) + "</use_no_of_threads>";
}
if (data[i].contains("<musrview_show_fourier>") && data[i].contains("</musrview_show_fourier>")) {
if (fMusrviewShowFourier)
data[i] = " <musrview_show_fourier>y</musrview_show_fourier>";
+4 -1
View File
@@ -70,7 +70,7 @@ class PAdminXMLParser
private:
enum EAdminKeyWords {eEmpty, eTimeout, eKeepMinuit2Output, eDumpAscii, eDumpRoot,
eTitleFromDataFile, eChisqPreRunBlock, eEstimateN0, eYamlOut,
eTitleFromDataFile, eChisqPreRunBlock, eEstimateN0, eYamlOut, eNoOfTreadsToBeUsed,
eMusrviewShowFourier, eMusrviewShowAvg, eMusrviewShowOneToOne, eEnableMusrT0,
eDarkThemeIconsMenu, eDarkThemeIconsToolbar, eIgnoreThemeAutoDetection, eEditW, eEditH,
eFontName, eFontSize, eExecPath, eDefaultSavePath,
@@ -128,6 +128,7 @@ class PAdmin : public QObject
bool getDumpRootFlag() { return fDumpRoot; }
bool getEstimateN0Flag() { return fEstimateN0; }
bool getYamlOutFlag() { return fYamlOut; }
int getNoOfThreadsToBeUsed() { return fNoOfThreadsToBeUsed; }
bool getChisqPerRunBlockFlag() { return fChisqPreRunBlock; }
bool getIgnoreThemeAutoDetection() { return fIgnoreThemeAutoDetection; }
bool getDarkThemeIconsMenuFlag() { return fDarkThemeIconsMenu; }
@@ -158,6 +159,7 @@ class PAdmin : public QObject
void setDumpRootFlag(const bool flag) { fDumpRoot = flag; }
void setEstimateN0Flag(const bool flag) { fEstimateN0 = flag; }
void setYamlOutFlag(const bool flag) { fYamlOut = flag; }
void setNoOfThreadsToBeUsed(const int num) { fNoOfThreadsToBeUsed = num; }
void setChisqPerRunBlockFlag(const bool flag) { fChisqPreRunBlock = flag; }
void setIgnoreThemeAutoDetection(const bool flag) { fIgnoreThemeAutoDetection = flag; }
void setDarkThemeIconsMenuFlag(const bool flag) { fDarkThemeIconsMenu = flag; }
@@ -209,6 +211,7 @@ class PAdmin : public QObject
bool fChisqPreRunBlock{false}; ///< flag indicating if musrfit shall write 'per run block' chisq to the msr-file (default: no).
bool fEstimateN0{true}; ///< flag indicating if musrfit shall estimate N0 for single histogram fits (default: yes).
bool fYamlOut{false}; ///< flag indicating if the MINUIT2.OUTPUT file should also be written as <msr-file>.yaml output. (default: no).
int fNoOfThreadsToBeUsed{1}; ///< number of threads to be used
bool fEnableMusrT0{true}; ///< flag indicating if musrT0 shall be enabled at startup from within musredit (default: yes).
bool fIgnoreThemeAutoDetection{false}; ///< flag indicating that the theme autodetection shall be ignored. (default: no)
bool fDarkThemeIconsMenu{false}; ///< flag indicating if dark theme icons shall be used in the menu (default: no)
@@ -28,6 +28,7 @@
***************************************************************************/
#include <memory>
#include <unistd.h> // for # of threads
#include "PChangeDefaultPathsDialog.h"
#include "PPrefsDialog.h"
@@ -90,6 +91,15 @@ PPrefsDialog::PPrefsDialog(PAdmin *admin) : fAdmin(admin)
fTimeout_lineEdit->setText(QString("%1").arg(fAdmin->getTimeout()));
fTimeout_lineEdit->setValidator(new QIntValidator(fTimeout_lineEdit));
// get number of threads info from the systems
long nprocs = sysconf(_SC_NPROCESSORS_ONLN);
if (fAdmin->getNoOfThreadsToBeUsed() > nprocs)
fAdmin->setNoOfThreadsToBeUsed(nprocs);
for (auto i=0; i<nprocs; i++)
fNumberOfThreads_comboBox->addItem(QString("%1").arg(i+1));
fNumberOfThreads_comboBox->setCurrentIndex(fAdmin->getNoOfThreadsToBeUsed()-1);
QObject::connect(fNumberOfThreads_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(numberOfThreadsChanged(int)));
QObject::connect(fDefaultPath_pushButton, SIGNAL(clicked()), this, SLOT(handleDefaultPaths()));
}
@@ -145,6 +155,17 @@ void PPrefsDialog::handleDefaultPaths()
}
}
//----------------------------------------------------------------------------------------------------
/**
* @brief Slot: keeps the number of threads to be used for fitting.
*
* @param idx index of the comboBox
*/
void PPrefsDialog::numberOfThreadsChanged(int idx)
{
fAdmin->setNoOfThreadsToBeUsed(idx+1);
}
//----------------------------------------------------------------------------------------------------
// END
//----------------------------------------------------------------------------------------------------
+1
View File
@@ -66,6 +66,7 @@ class PPrefsDialog : public QDialog, private Ui::PPrefsDialog
void dumpAscii();
void dumpRoot();
void handleDefaultPaths();
void numberOfThreadsChanged(int idx);
private:
PAdmin *fAdmin;
+8 -3
View File
@@ -2046,7 +2046,7 @@ void PTextEdit::musrWiz()
// handle return status of musrWiz
connect(proc, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
[=, this](int exitCode, QProcess::ExitStatus exitStatus){ exitStatusMusrWiz(exitCode, exitStatus); });
[=](int exitCode, QProcess::ExitStatus exitStatus){ exitStatusMusrWiz(exitCode, exitStatus); });
// make sure that the system environment variables are properly set
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
@@ -2162,6 +2162,11 @@ void PTextEdit::musrFit()
cmd.append("--yaml");
}
// check how many threads to be used
cmd.append("--use-no-of-threads");
QString noThreads = QString("%1").arg(fAdmin->getNoOfThreadsToBeUsed());
cmd.append(noThreads);
// check per-run-block-chisq flag
if (fAdmin->getChisqPerRunBlockFlag()) {
cmd.append("--per-run-block-chisq");
@@ -2761,7 +2766,7 @@ void PTextEdit::musrT0()
proc->setWorkingDirectory(workDir);
connect(proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[=, this](int exitCode, QProcess::ExitStatus exitStatus){ fileReload(); });
[=](int exitCode, QProcess::ExitStatus exitStatus){ fileReload(); });
proc->start(cmd, arg);
if (!proc->waitForStarted()) {
@@ -2921,7 +2926,7 @@ void PTextEdit::musrSetSteps()
// handle return status of musrStep
connect(proc, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
[=, this](int exitCode, QProcess::ExitStatus exitStatus){ exitStatusMusrSetSteps(exitCode, exitStatus); });
[=](int exitCode, QProcess::ExitStatus exitStatus){ exitStatusMusrSetSteps(exitCode, exitStatus); });
// make sure that the system environment variables are properly set
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
@@ -15,6 +15,7 @@
<chisq_per_run_block>n</chisq_per_run_block>
<estimate_n0>y</estimate_n0>
<yaml_out>n</yaml_out>
<use_no_of_threads>1024</use_no_of_threads>
<musrview_show_fourier>n</musrview_show_fourier>
<musrview_show_avg>n</musrview_show_avg>
<musrview_show_one_to_one>n</musrview_show_one_to_one>
+10
View File
@@ -212,6 +212,8 @@ bool PAdminXMLParser::startElement()
fKeyWord = eEstimateN0;
} else if (qName == "yaml_out") {
fKeyWord = eYamlOut;
} else if (qName == "use_no_of_threads") {
fKeyWord = eNoOfTreadsToBeUsed;
} else if (qName == "chisq_per_run_block") {
fKeyWord = eChisqPreRunBlock;
} else if (qName == "path_file_name") {
@@ -469,6 +471,11 @@ bool PAdminXMLParser::characters()
fAdmin->fMsr2DataParam.yamlOut = flag;
fAdmin->setYamlOutFlag(flag);
break;
case eNoOfTreadsToBeUsed:
ival = QString(str.toLatin1()).trimmed().toInt(&ok);
if (ok)
fAdmin->setNoOfThreadsToBeUsed(ival);
break;
case eChisqPreRunBlock:
if (str == "y")
flag = true;
@@ -1134,6 +1141,9 @@ int PAdmin::savePrefs(QString pref_fln)
else
data[i] = " <yaml_out>n</yaml_out>";
}
if (data[i].contains("<use_no_of_threads>") && data[i].contains("</use_no_of_threads>")) {
data[i] = " <use_no_of_threads>" + QString("%1").arg(fNoOfThreadsToBeUsed) + "</use_no_of_threads>";
}
if (data[i].contains("<musrview_show_fourier>") && data[i].contains("</musrview_show_fourier>")) {
if (fMusrviewShowFourier)
data[i] = " <musrview_show_fourier>y</musrview_show_fourier>";
+4 -1
View File
@@ -143,7 +143,7 @@ class PAdminXMLParser
* The parser uses these to determine how to process element content.
*/
enum EAdminKeyWords {eEmpty, eTimeout, eKeepMinuit2Output, eDumpAscii, eDumpRoot,
eTitleFromDataFile, eChisqPreRunBlock, eEstimateN0, eYamlOut,
eTitleFromDataFile, eChisqPreRunBlock, eEstimateN0, eYamlOut, eNoOfTreadsToBeUsed,
eMusrviewShowFourier, eMusrviewShowAvg, eMusrviewShowOneToOne, eEnableMusrT0,
eIgnoreThemeAutoDetection, eDarkThemeIconsMenu, eDarkThemeIconsToolbar, eEditW, eEditH,
eFontName, eFontSize, eExecPath, eDefaultSavePath,
@@ -225,6 +225,7 @@ class PAdmin : public QObject
bool getMusrviewShowOneToOneFlag() { return fMusrviewShowOneToOne; } ///< Check if one-to-one theory display is enabled.
bool getEnableMusrT0Flag() { return fEnableMusrT0; } ///< Check if musrT0 is enabled.
bool getYamlOutFlag() { return fYamlOut; } ///< Check if YAML output is enabled.
int getNoOfThreadsToBeUsed() { return fNoOfThreadsToBeUsed; } ///< Get number of threads to be used
bool getKeepMinuit2OutputFlag() { return fKeepMinuit2Output; } ///< Check if MINUIT2 output files are preserved.
bool getDumpAsciiFlag() { return fDumpAscii; } ///< Check if ASCII dump is enabled.
bool getDumpRootFlag() { return fDumpRoot; } ///< Check if ROOT dump is enabled.
@@ -264,6 +265,7 @@ class PAdmin : public QObject
void setDumpRootFlag(const bool flag) { fDumpRoot = flag; } ///< Enable/disable ROOT dump.
void setEstimateN0Flag(const bool flag) { fEstimateN0 = flag; } ///< Enable/disable N0 estimation.
void setYamlOutFlag(const bool flag) { fYamlOut = flag; } ///< Enable/disable YAML output.
void setNoOfThreadsToBeUsed(const int num) { fNoOfThreadsToBeUsed = num; } ///< set number of threads to be used
void setChisqPerRunBlockFlag(const bool flag) { fChisqPreRunBlock = flag; } ///< Enable/disable per-run-block chi-square.
void setIgnoreThemeAutoDetection(const bool flag) { fIgnoreThemeAutoDetection = flag; } ///< Enable/disable theme auto-detection.
void setDarkThemeIconsMenuFlag(const bool flag) { fDarkThemeIconsMenu = flag; } ///< Enable/disable dark theme menu icons.
@@ -356,6 +358,7 @@ class PAdmin : public QObject
bool fChisqPreRunBlock{false}; ///< If true, write per-run-block chi-square values to msr-file.
bool fEstimateN0{true}; ///< If true, estimate N0 parameter for single histogram fits.
bool fYamlOut{false}; ///< If true, write MINUIT2 output additionally as \<msr-file\>.yaml.
int fNoOfThreadsToBeUsed{1}; ///< number of threads to be used
/** @} */
/** @name MSR File Defaults
@@ -45,6 +45,7 @@
*/
#include <memory>
#include <unistd.h> // for # of threads
#include "PChangeDefaultPathsDialog.h"
#include "PPrefsDialog.h"
@@ -164,6 +165,15 @@ PPrefsDialog::PPrefsDialog(PAdmin *admin) : fAdmin(admin)
fTimeout_lineEdit->setText(QString("%1").arg(fAdmin->getTimeout()));
fTimeout_lineEdit->setValidator(new QIntValidator(fTimeout_lineEdit));
// get number of threads info from the systems
long nprocs = sysconf(_SC_NPROCESSORS_ONLN);
if (fAdmin->getNoOfThreadsToBeUsed() > nprocs)
fAdmin->setNoOfThreadsToBeUsed(nprocs);
for (auto i=0; i<nprocs; i++)
fNumberOfThreads_comboBox->addItem(QString("%1").arg(i+1));
fNumberOfThreads_comboBox->setCurrentIndex(fAdmin->getNoOfThreadsToBeUsed()-1);
QObject::connect(fNumberOfThreads_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(numberOfThreadsChanged(int)));
QObject::connect(fDefaultPath_pushButton, SIGNAL(clicked()), this, SLOT(handleDefaultPaths()));
}
@@ -340,6 +350,17 @@ void PPrefsDialog::handleDefaultPaths()
}
}
//----------------------------------------------------------------------------------------------------
/**
* @brief Slot: keeps the number of threads to be used for fitting.
*
* @param idx index of the comboBox
*/
void PPrefsDialog::numberOfThreadsChanged(int idx)
{
fAdmin->setNoOfThreadsToBeUsed(idx+1);
}
//----------------------------------------------------------------------------------------------------
// END
//----------------------------------------------------------------------------------------------------
+7
View File
@@ -318,6 +318,13 @@ class PPrefsDialog : public QDialog, private Ui::PPrefsDialog
*/
void handleDefaultPaths();
/**
* @brief Slot: called when the current index of the number of threads to be used has changed
*
* @param idx index of the comboBox
*/
void numberOfThreadsChanged(int idx);
private:
PAdmin *fAdmin; ///< Pointer to global administration object storing all preferences.
};
+8 -3
View File
@@ -2160,7 +2160,7 @@ void PTextEdit::musrWiz()
// handle return status of musrWiz
connect(proc, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
[=, this](int exitCode, QProcess::ExitStatus exitStatus){ exitStatusMusrWiz(exitCode, exitStatus); });
[=](int exitCode, QProcess::ExitStatus exitStatus){ exitStatusMusrWiz(exitCode, exitStatus); });
// make sure that the system environment variables are properly set
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
@@ -2273,6 +2273,11 @@ void PTextEdit::musrFit()
cmd.append("--yaml");
}
// check how many threads to be used
cmd.append("--use-no-of-threads");
QString noThreads = QString("%1").arg(fAdmin->getNoOfThreadsToBeUsed());
cmd.append(noThreads);
// check per-run-block-chisq flag
if (fAdmin->getChisqPerRunBlockFlag()) {
cmd.append("--per-run-block-chisq");
@@ -2868,7 +2873,7 @@ void PTextEdit::musrT0()
proc->setWorkingDirectory(workDir);
connect(proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[=, this](int exitCode, QProcess::ExitStatus exitStatus){ fileReload(); });
[=](int exitCode, QProcess::ExitStatus exitStatus){ fileReload(); });
proc->start(cmd, arg);
if (!proc->waitForStarted()) {
@@ -3022,7 +3027,7 @@ void PTextEdit::musrSetSteps()
// handle return status of musrStep
connect(proc, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
[=, this](int exitCode, QProcess::ExitStatus exitStatus){ exitStatusMusrSetSteps(exitCode, exitStatus); });
[=](int exitCode, QProcess::ExitStatus exitStatus){ exitStatusMusrSetSteps(exitCode, exitStatus); });
// make sure that the system environment variables are properly set
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
@@ -3,7 +3,7 @@
<class>PPrefsDialog</class>
<widget class="QDialog" name="PPrefsDialog">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
<enum>Qt::WindowModality::WindowModal</enum>
</property>
<property name="geometry">
<rect>
@@ -26,13 +26,13 @@
<item>
<widget class="QTabWidget" name="fTabWidget">
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="QWidget" name="fGeneral_tab">
<attribute name="title">
<string>general</string>
</attribute>
<widget class="QWidget" name="">
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>11</x>
@@ -57,7 +57,7 @@
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -97,7 +97,7 @@
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -117,7 +117,7 @@
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -225,6 +225,28 @@
<string>yaml out</string>
</property>
</widget>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>10</x>
<y>90</y>
<width>291</width>
<height>34</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QComboBox" name="fNumberOfThreads_comboBox"/>
</item>
<item>
<widget class="QLabel" name="fNumberOfThreads_label">
<property name="text">
<string># threads to be used</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="fMusrview_tab">
<attribute name="title">
@@ -302,7 +324,7 @@
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -15,6 +15,7 @@
<chisq_per_run_block>n</chisq_per_run_block>
<estimate_n0>y</estimate_n0>
<yaml_out>n</yaml_out>
<use_no_of_threads>1024</use_no_of_threads>
<musrview_show_fourier>n</musrview_show_fourier>
<musrview_show_avg>n</musrview_show_avg>
<musrview_show_one_to_one>n</musrview_show_one_to_one>
-37
View File
@@ -1,37 +0,0 @@
#------------------------------------------------------
# CMakeLists.txt for strToNum
#
# little stand-alone test driver for the dependency-free
# PStringUtils class (pure C++17, no ROOT needed).
#
# build (stand-alone):
# cmake -S . -B build
# cmake --build build
# ./build/strToNum
#
# Andreas Suter, 2026/06/06
#------------------------------------------------------
cmake_minimum_required(VERSION 3.9)
project(strToNum VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif (NOT CMAKE_BUILD_TYPE)
#--- the class under test lives in src/classes, its header in src/include -----
set(MUSRFIT_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../classes)
set(MUSRFIT_INC ${CMAKE_CURRENT_SOURCE_DIR}/../../include)
add_executable(strToNum
strToNum.cpp
${MUSRFIT_SRC}/PStringUtils.cpp
)
target_include_directories(strToNum
PRIVATE ${MUSRFIT_INC}
)
-304
View File
@@ -1,304 +0,0 @@
/***************************************************************************
strToNum.cpp
Author: Andreas Suter
e-mail: andreas.suter@psi.ch
Little stand-alone test driver for the PStringUtils class. It exercises
Split / IsInt / IsFloat / ToInt / ToDouble / IsEqualNoCase /
ContainsNoCase / BeginsWithNoCase and reports a pass/fail summary.
Usage:
strToNum -> run the built-in test suite
strToNum <string> -> show what PStringUtils makes of the given
string(s) on the command line (ad-hoc checks)
strToNum -i -> interactive mode: type a string at the prompt
and see the result of every PStringUtils method
(empty line or 'quit' to leave)
***************************************************************************/
/***************************************************************************
* Copyright (C) 2007-2026 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 <cmath>
#include <iostream>
#include <string>
#include <vector>
#include "PStringUtils.h"
//--------------------------------------------------------------------------
// tiny test bookkeeping
//--------------------------------------------------------------------------
static int gPassed = 0;
static int gFailed = 0;
static void check(const std::string &what, bool ok)
{
if (ok) {
++gPassed;
std::cout << " [ ok ] " << what << std::endl;
} else {
++gFailed;
std::cout << " [FAIL] " << what << std::endl;
}
}
//--------------------------------------------------------------------------
static std::string vecToStr(const std::vector<std::string> &v)
{
std::string s = "{";
for (std::vector<std::string>::size_type i = 0; i < v.size(); ++i) {
s += "'" + v[i] + "'";
if (i + 1 < v.size())
s += ", ";
}
s += "}";
return s;
}
//--------------------------------------------------------------------------
static void testSplit()
{
std::cout << "Split:" << std::endl;
std::vector<std::string> r = PStringUtils::Split("alpha beta gamma", " ");
std::cout << " input: 'alpha beta gamma', delim: ' '" << std::endl;
check("3 tokens on single space delimiter",
r.size() == 3 && r[0] == "alpha" && r[1] == "beta" && r[2] == "gamma");
std::cout << "----" << std::endl;
r = PStringUtils::Split(" , 1 , 2 ,, 3 ,", " ,");
std::cout << " input: ' , 1 , 2 ,, 3 ,', delim: ' ,'" << std::endl;
std::cout << " -> ";
for (auto i: r)
std::cout << i << ", ";
std::cout << std::endl;
check("mixed/repeated delimiters, empty tokens skipped",
r.size() == 3 && r[0] == "1" && r[1] == "2" && r[2] == "3");
std::cout << "----" << std::endl;
r = PStringUtils::Split("", " ");
check("empty input -> no tokens", r.empty());
r = PStringUtils::Split(" ", " ");
check("delimiters only -> no tokens", r.empty());
r = PStringUtils::Split("nodelim", ",;");
check("no delimiter present -> single token",
r.size() == 1 && r[0] == "nodelim");
}
//--------------------------------------------------------------------------
static void testIsInt()
{
std::cout << "IsInt:" << std::endl;
check("'12345' is int", PStringUtils::IsInt("12345"));
check("' 42 ' (surrounding ws) is int", PStringUtils::IsInt(" 42 "));
check("'-5' is int (negative)", PStringUtils::IsInt("-5"));
check("'+42' is int (positive sign)", PStringUtils::IsInt("+42"));
check("'' is not int", !PStringUtils::IsInt(""));
check("' ' (ws only) is not int", !PStringUtils::IsInt(" "));
check("'-' (sign only) is not int", !PStringUtils::IsInt("-"));
check("'+-5' (double sign) is not int", !PStringUtils::IsInt("+-5"));
check("'5-3' (sign after digit) is not int", !PStringUtils::IsInt("5-3"));
check("'3.14' is not int", !PStringUtils::IsInt("3.14"));
check("'12a' is not int", !PStringUtils::IsInt("12a"));
}
//--------------------------------------------------------------------------
static void testIsFloat()
{
std::cout << "IsFloat:" << std::endl;
check("'3.14' is float", PStringUtils::IsFloat("3.14"));
check("'-1.2e-3' is float", PStringUtils::IsFloat("-1.2e-3"));
check("'+42' is float", PStringUtils::IsFloat("+42"));
check("'.5' is float", PStringUtils::IsFloat(".5"));
check("' 6.022e23 ' (surrounding ws) is float",
PStringUtils::IsFloat(" 6.022e23 "));
check("'' is not float", !PStringUtils::IsFloat(""));
check("'nan' is not float", !PStringUtils::IsFloat("nan"));
check("'inf' is not float", !PStringUtils::IsFloat("inf"));
check("'1.2.3' is not float", !PStringUtils::IsFloat("1.2.3"));
check("'12abc' is not float", !PStringUtils::IsFloat("12abc"));
}
//--------------------------------------------------------------------------
static void testToInt()
{
std::cout << "ToInt:" << std::endl;
bool ok = false;
check("'42' -> 42, ok", PStringUtils::ToInt("42", &ok) == 42 && ok);
check("' -7' -> -7, ok", PStringUtils::ToInt(" -7", &ok) == -7 && ok);
check("'123abc' -> 123, ok (trailing ignored)",
PStringUtils::ToInt("123abc", &ok) == 123 && ok);
check("'abc' -> 0, !ok", PStringUtils::ToInt("abc", &ok) == 0 && !ok);
check("'' -> 0, !ok", PStringUtils::ToInt("", &ok) == 0 && !ok);
check("'99999999999999999999' -> out of range, !ok",
(PStringUtils::ToInt("99999999999999999999", &ok), !ok));
check("null ok pointer is tolerated", PStringUtils::ToInt("17") == 17);
}
//--------------------------------------------------------------------------
static void testToDouble()
{
std::cout << "ToDouble:" << std::endl;
bool ok = false;
check("'3.14' -> 3.14, ok",
std::fabs(PStringUtils::ToDouble("3.14", &ok) - 3.14) < 1e-12 && ok);
check("' +1.5e2' -> 150, ok",
std::fabs(PStringUtils::ToDouble(" +1.5e2", &ok) - 150.0) < 1e-9 && ok);
check("'2.5xyz' -> 2.5, ok (trailing ignored)",
std::fabs(PStringUtils::ToDouble("2.5xyz", &ok) - 2.5) < 1e-12 && ok);
check("'abc' -> 0.0, !ok", PStringUtils::ToDouble("abc", &ok) == 0.0 && !ok);
check("'' -> 0.0, !ok", PStringUtils::ToDouble("", &ok) == 0.0 && !ok);
check("'1e400' -> out of range, !ok",
(PStringUtils::ToDouble("1e400", &ok), !ok));
check("null ok pointer is tolerated",
std::fabs(PStringUtils::ToDouble("0.25") - 0.25) < 1e-12);
}
//--------------------------------------------------------------------------
static void testCaseHelpers()
{
std::cout << "IsEqualNoCase / ContainsNoCase / BeginsWithNoCase:" << std::endl;
check("'Fit' == 'fIT' (no case)", PStringUtils::IsEqualNoCase("Fit", "fIT"));
check("'Fit' != 'Fits'", !PStringUtils::IsEqualNoCase("Fit", "Fits"));
check("'' == ''", PStringUtils::IsEqualNoCase("", ""));
check("'Hello World' contains 'LO WO' (no case)",
PStringUtils::ContainsNoCase("Hello World", "LO WO"));
check("empty needle is contained",
PStringUtils::ContainsNoCase("abc", ""));
check("needle longer than haystack is not contained",
!PStringUtils::ContainsNoCase("ab", "abc"));
check("'THEORY' begins with 'the' (no case)",
PStringUtils::BeginsWithNoCase("THEORY", "the"));
check("'THEORY' does not begin with 'ory'",
!PStringUtils::BeginsWithNoCase("THEORY", "ory"));
}
//--------------------------------------------------------------------------
static void inspect(const std::string &str)
{
std::cout << "Inspecting '" << str << "':" << std::endl;
std::cout << " Split(' \\t,;') = "
<< vecToStr(PStringUtils::Split(str, " \t,;")) << std::endl;
std::cout << " IsInt = " << (PStringUtils::IsInt(str) ? "true" : "false") << std::endl;
std::cout << " IsFloat = " << (PStringUtils::IsFloat(str) ? "true" : "false") << std::endl;
bool ok = false;
int i = PStringUtils::ToInt(str, &ok);
std::cout << " ToInt = " << i << " (ok=" << (ok ? "true" : "false") << ")" << std::endl;
double d = PStringUtils::ToDouble(str, &ok);
std::cout << " ToDouble = " << d << " (ok=" << (ok ? "true" : "false") << ")" << std::endl;
}
//--------------------------------------------------------------------------
static void usage(const char *prog)
{
std::cout
<< "usage: " << prog << " [options] [string ...]\n"
<< "\n"
<< "Little stand-alone test driver for the PStringUtils class. It exercises\n"
<< "Split / IsInt / IsFloat / ToInt / ToDouble / IsEqualNoCase /\n"
<< "ContainsNoCase / BeginsWithNoCase.\n"
<< "\n"
<< "options:\n"
<< " -h, --help show this help and exit\n"
<< " -i, --interactive interactive mode: type a string at the prompt and\n"
<< " see the result of every PStringUtils method\n"
<< " (empty line, 'quit'/'exit' or Ctrl-D leaves)\n"
<< "\n"
<< "arguments:\n"
<< " string ... one or more strings to inspect; the result of every\n"
<< " PStringUtils method is printed for each of them\n"
<< "\n"
<< "with no options and no arguments the built-in test suite is run; the exit\n"
<< "code is 0 if all checks pass and 1 otherwise.\n"
<< "\n"
<< "examples:\n"
<< " " << prog << " run the built-in test suite\n"
<< " " << prog << " \" -42xyz\" 1.5e-3 inspect the given strings\n"
<< " " << prog << " -i interactive mode\n";
}
//--------------------------------------------------------------------------
static void interactive()
{
std::cout << "==== PStringUtils interactive mode ====" << std::endl;
std::cout << "Enter a string to test the methods on it." << std::endl;
std::cout << "An empty line or 'quit' leaves." << std::endl << std::endl;
std::string line;
while (true) {
std::cout << "strToNum> " << std::flush;
if (!std::getline(std::cin, line)) // EOF (e.g. Ctrl-D)
break;
if (line.empty() || line == "quit" || line == "exit")
break;
inspect(line);
std::cout << std::endl;
}
}
//--------------------------------------------------------------------------
int main(int argc, char *argv[])
{
if (argc > 1) {
const std::string arg1 = argv[1];
if (arg1 == "-h" || arg1 == "--help") {
usage(argv[0]);
return 0;
}
if (arg1 == "-i" || arg1 == "--interactive") {
interactive();
return 0;
}
// ad-hoc mode: inspect the strings given on the command line
for (int i = 1; i < argc; ++i) {
inspect(argv[i]);
std::cout << std::endl;
}
return 0;
}
std::cout << "==== PStringUtils test suite ====" << std::endl << std::endl;
testSplit();
testIsInt();
testIsFloat();
testToInt();
testToDouble();
testCaseHelpers();
std::cout << std::endl
<< "==== summary: " << gPassed << " passed, "
<< gFailed << " failed ====" << std::endl;
return (gFailed == 0) ? 0 : 1;
}