48 #include "TClonesArray.h"
49 #include "TStopwatch.h"
51 #include "fileUtils.hpp"
63 const int errCode = 0)
65 cerr <<
"verify that given .key files do not violate physics" << endl
69 <<
" [-d test data -n max. # of events -p PDG file -t tree name -e max. diff. -l leaf names -v -h] key file(s)" << endl
71 <<
" -d file path to file with test data (.evt or .root format)" << endl
72 <<
" -n # maximum number of events to read (default: all)" << endl
73 <<
" -p file path to particle data table file (default: ./particleDataTable.txt)" << endl
74 <<
" -t name name of tree in ROOT data files (default: rootPwaEvtTree)" << endl
75 <<
" -e # maximum deviation of amplitude ratios from 1 (default: 1E-6)" << endl
76 <<
" -l names semicolon separated object/leaf names in input data (default: 'prodKinParticles;prodKinMomenta;decayKinParticles;decayKinMomenta')" << endl
77 <<
" -v verbose; print debug output (default: false)" << endl
78 <<
" -h print help" << endl
85 const string& keyFileName,
86 vector<string>& keyFileErrors,
87 const long int maxNmbEvents = -1,
88 const bool debug =
false,
89 const double maxDelta = 1e-6,
90 const TClonesArray* prodKinPartNames = 0,
91 const TClonesArray* decayKinPartNames = 0,
92 const string& prodKinMomentaLeafName =
"prodKinMomenta",
93 const string& decayKinMomentaLeafName =
"decayKinMomenta")
100 printWarn <<
"problems constructing decay topology from key file '" << keyFileName <<
"'. "
101 <<
"skipping." << endl;
102 keyFileErrors.push_back(
"parsing errors");
106 printInfo <<
"checking decay topology" << endl;
108 if (not decayTopo->checkTopology()) {
109 keyFileErrors.push_back(
"problematic topology");
112 if (not decayTopo->checkConsistency()) {
113 keyFileErrors.push_back(
"inconsistent decay");
119 if (not inTree or not prodKinPartNames or not decayKinPartNames)
122 printInfo <<
"calculating amplitudes for ";
123 if (maxNmbEvents < 0)
126 cout << maxNmbEvents;
127 cout <<
" events" << endl;
135 vector<complex<double> > ampValues;
136 if (not
processTree(*inTree, *prodKinPartNames, *decayKinPartNames,
137 amplitude, ampValues, maxNmbEvents,
138 prodKinMomentaLeafName, decayKinMomentaLeafName,
false)) {
139 printWarn <<
"problems reading tree" << endl;
142 if (ampValues.size() < 1) {
143 printWarn <<
"no amplitude were calculated" << endl;
148 vector<complex<double> > ampSpaceInvValues;
149 amplitude->enableSpaceInversion(
true);
150 if (not
processTree(*inTree, *prodKinPartNames, *decayKinPartNames,
151 amplitude, ampSpaceInvValues, maxNmbEvents,
152 prodKinMomentaLeafName, decayKinMomentaLeafName,
false)) {
153 printWarn <<
"problems reading tree" << endl;
158 vector<complex<double> > ampReflValues;
159 amplitude->enableSpaceInversion(
false);
160 amplitude->enableReflection (
true);
161 if (not
processTree(*inTree, *prodKinPartNames, *decayKinPartNames,
162 amplitude, ampReflValues, maxNmbEvents,
163 prodKinMomentaLeafName, decayKinMomentaLeafName,
false)) {
164 printWarn <<
"problems reading tree" << endl;
168 if ( (ampValues.size() != ampSpaceInvValues.size())
169 or (ampValues.size() != ampReflValues.size ())) {
170 printWarn <<
"different number of amplitudes for space inverted "
171 <<
"(" << ampSpaceInvValues.size() <<
"), reflected "
172 <<
"(" << ampReflValues.size() <<
"), and unmodified data "
173 <<
"(" << ampValues.size() <<
")." << endl;
177 printInfo <<
"checking symmetry properties of amplitudes" << endl;
178 unsigned int countAmpZero = 0;
179 unsigned int countAmpRatioNotOk = 0;
180 unsigned int countSpaceInvEigenValNotOk = 0;
181 unsigned int countReflEigenValNotOk = 0;
182 for (
unsigned int i = 0;
i < ampValues.size(); ++
i) {
184 bool ampZero =
false;
185 if (ampValues[
i] == complex<double>(0, 0)) {
189 const unsigned int nmbDigits = numeric_limits<double>::digits10 + 1;
191 s.precision(nmbDigits);
192 s.setf(ios_base::scientific, ios_base::floatfield);
194 printDebug <<
"amplitude " <<
i <<
": " << endl;
195 s <<
" ampl. = " << ampValues[
i];
197 s <<
" <! zero amplitude";
199 <<
" ampl. space inv. = " << ampSpaceInvValues[
i] << endl
200 <<
" ampl. refl. = " << ampReflValues [
i] << endl;
205 const complex<double> spaceInvRatio
206 = complex<double>((ampSpaceInvValues[
i].real() != 0) ?
207 ampValues[
i].real() / ampSpaceInvValues[
i].real() : 0,
208 (ampSpaceInvValues[
i].imag() != 0) ?
209 ampValues[
i].imag() / ampSpaceInvValues[
i].imag() : 0);
210 bool spaceInvAmpRatioOk =
true;
211 if ( (fabs(spaceInvRatio.real()) - 1 > maxDelta)
212 or (fabs(spaceInvRatio.imag()) - 1 > maxDelta)) {
213 spaceInvAmpRatioOk =
false;
214 ++countAmpRatioNotOk;
216 const int spaceInvEigenValue = decayTopo->spaceInvEigenValue();
217 bool spaceInvEigenValOk =
true;
218 if ( ( (spaceInvRatio.real() != 0)
219 and (spaceInvRatio.real() / fabs(spaceInvRatio.real()) != spaceInvEigenValue))
220 or ( (spaceInvRatio.imag() != 0)
221 and (spaceInvRatio.imag() / fabs(spaceInvRatio.imag()) != spaceInvEigenValue))) {
222 spaceInvEigenValOk =
false;
223 ++countSpaceInvEigenValNotOk;
227 s <<
"Re[ampl.] / Re[ampl.] space inv. - 1 = " << setw(23) << spaceInvRatio.real() - 1 <<
", "
228 <<
"Im[ampl.] / Im[ampl.] space inv. - 1 = " << setw(23) << spaceInvRatio.imag() - 1;
229 cout <<
" " << s.str();
230 if (not spaceInvAmpRatioOk)
231 cout <<
" <! larger than " << maxDelta;
232 if (not spaceInvEigenValOk)
233 cout <<
" <! eigenvalue != " << spaceInvEigenValue;
238 const complex<double> reflRatio
239 = complex<double>((ampReflValues[
i].real() != 0) ?
240 ampValues[
i].real() / ampReflValues[
i].real() : 0,
241 (ampReflValues[
i].imag() != 0) ?
242 ampValues[
i].imag() / ampReflValues[
i].imag() : 0);
243 bool reflAmpRatioOk =
true;
244 if ( (fabs(reflRatio.real()) - 1 > maxDelta)
245 or (fabs(reflRatio.imag()) - 1 > maxDelta)) {
246 reflAmpRatioOk =
false;
247 ++countAmpRatioNotOk;
249 const int reflEigenValue = decayTopo->reflectionEigenValue();
250 bool reflEigenValOk =
true;
251 if ( ( (reflRatio.real() != 0)
252 and (reflRatio.real() / fabs(reflRatio.real()) != reflEigenValue))
253 or ( (reflRatio.imag() != 0)
254 and (reflRatio.imag() / fabs(reflRatio.imag()) != reflEigenValue))) {
255 reflEigenValOk =
false;
256 ++countReflEigenValNotOk;
260 s <<
"Re[ampl.] / Re[ampl.] refl. - 1 = " << setw(23) << reflRatio.real() - 1 <<
", "
261 <<
"Im[ampl.] / Im[ampl.] refl. - 1 = " << setw(23) << reflRatio.imag() - 1;
262 cout <<
" " << s.str();
263 if (not reflAmpRatioOk)
264 cout <<
" <! larger than " << maxDelta;
265 if (not reflEigenValOk)
266 cout <<
" <! eigenvalue != " << reflEigenValue;
271 if (countAmpZero > 0) {
272 keyFileErrors.push_back(
"zero amplitude");
275 if (countAmpRatioNotOk > 0) {
277 s <<
"amplitude deviation in symmetry check larger than " << maxDelta;
278 keyFileErrors.push_back(s.str());
281 if (countSpaceInvEigenValNotOk > 0) {
282 keyFileErrors.push_back(
"wrong space inversion eigenvalue");
285 if (countReflEigenValNotOk > 0) {
286 keyFileErrors.push_back(
"wrong eigenvalue for reflection through production plane");
303 const string progName = argv[0];
304 string dataFileName =
"";
305 long int maxNmbEvents = -1;
306 string pdgFileName =
"./particleDataTable.txt";
307 string inTreeName =
"rootPwaEvtTree";
308 double maxDelta = 1e-6;
309 string leafNames =
"prodKinParticles;prodKinMomenta;decayKinParticles;decayKinMomenta";
314 while ((c = getopt(argc, argv,
"d:n:p:t:e:l:r:vh")) != -1)
317 dataFileName = optarg;
320 maxNmbEvents = atol(optarg);
323 pdgFileName = optarg;
329 maxDelta = atof(optarg);
344 waveDescription::setDebug(
true);
351 if (optind >= argc) {
352 printErr <<
"you need to specify at least one key file to process. aborting." << endl;;
355 vector<string> keyFileNames;
356 while (optind < argc) {
357 const string fileName = argv[optind++];
358 keyFileNames.push_back(fileName);
362 string prodKinPartNamesObjName, prodKinMomentaLeafName;
363 string decayKinPartNamesObjName, decayKinMomentaLeafName;
365 decayKinPartNamesObjName, decayKinMomentaLeafName);
369 TClonesArray* prodKinPartNames = 0;
370 TClonesArray* decayKinPartNames = 0;
371 if (dataFileName ==
"")
372 printInfo <<
"No test data file was specified (option -d). "
373 <<
"skipping symmetry checks of amplitude." << endl;
375 vector<string> rootFileNames;
376 vector<string> evtFileNames;
377 const string fileExt = extensionFromPath(dataFileName);
378 if (fileExt ==
"root")
379 rootFileNames.push_back(dataFileName);
380 else if (fileExt ==
"evt")
381 evtFileNames.push_back(dataFileName);
383 printErr <<
"specified input files is neither a .root nor a .evt file. aborting.";
386 vector<TTree*> inTrees;
388 rootFileNames, evtFileNames,
389 inTreeName, prodKinPartNamesObjName, prodKinMomentaLeafName,
390 decayKinPartNamesObjName, decayKinMomentaLeafName, debug)) {
391 printErr <<
"problems opening input file(s). aborting." << endl;
398 particleDataTable::readFile(pdgFileName);
401 map<string, vector<string> > keyFileErrors;
402 unsigned int countKeyFileErr = 0;
403 for (
unsigned int i = 0;
i < keyFileNames.size(); ++
i) {
405 printInfo <<
"checking key file '" << keyFileNames[
i] <<
"'" << endl;
406 vector<string> errors;
407 if (not
testAmplitude(inTree, keyFileNames[
i], errors, maxNmbEvents, debug, maxDelta,
408 prodKinPartNames, decayKinPartNames,
409 prodKinMomentaLeafName, decayKinMomentaLeafName)) {
411 printWarn <<
"key file '" << keyFileNames[
i] <<
"' did not pass all tests. "
412 <<
"see summary below." << endl;
414 printSucc <<
"key file '" << keyFileNames[
i] <<
"' passed all tests" << endl;
416 for (
unsigned int j = 0; j < errors.size(); ++j)
417 keyFileErrors[errors[j]].push_back(keyFileNames[i]);
426 if (countKeyFileErr == 0) {
427 printSucc <<
"all " << keyFileNames.size() <<
" keyfile(s) passed all tests" << endl;
431 printInfo << keyFileNames.size() - countKeyFileErr <<
" of " << keyFileNames.size()
432 <<
" keyfile(s) passed all tests" << endl;
433 if (keyFileErrors.size() > 0) {
434 printInfo << countKeyFileErr <<
" problematic keyfile(s):" << endl;
435 for (map<
string, vector<string> >::const_iterator entry = keyFileErrors.begin();
436 entry != keyFileErrors.end(); ++entry) {
437 cout <<
" " << entry->first <<
":" << endl;
438 for (
unsigned int i = 0;
i < entry->second.size(); ++
i)
439 cout <<
" " << entry->second[
i] << endl;