1 //--------------------------------------------------------------------------
4 // This software is part of the EvtGen package developed jointly
5 // for the BaBar and CLEO collaborations. If you use all or part
6 // of it, please give an appropriate acknowledgement.
8 // Copyright Information: See EvtGen/COPYRIGHT
9 // Copyright (C) 1998 Caltech, UCSB
11 // Module: EvtGen/EvtGenericDalitz.hh
13 // Description: Model to describe a generic dalitz decay
15 // Modification history:
17 // DCC 16 December, 2011 Module created
19 //------------------------------------------------------------------------
21 #include "EvtGenModels/EvtDalitzTable.hh"
22 #include "EvtGenBase/EvtReport.hh"
23 #include "EvtGenBase/EvtParserXml.hh"
24 #include "EvtGenBase/EvtPDL.hh"
25 #include "EvtGenBase/EvtSpinType.hh"
26 #include "EvtGenBase/EvtDalitzPlot.hh"
27 #include "EvtGenBase/EvtCyclic3.hh"
36 EvtDalitzTable::EvtDalitzTable() {
41 EvtDalitzTable::~EvtDalitzTable() {
46 EvtDalitzTable* EvtDalitzTable::getInstance(const std::string dec_name, bool verbose) {
48 static EvtDalitzTable* theDalitzTable = 0;
50 if(theDalitzTable == 0) {
51 theDalitzTable = new EvtDalitzTable();
54 if(!theDalitzTable->fileHasBeenRead(dec_name)) {
55 theDalitzTable->readXMLDecayFile(dec_name,verbose);
58 return theDalitzTable;
62 bool EvtDalitzTable::fileHasBeenRead(const std::string dec_name) {
63 std::vector<std::string>::iterator i = _readFiles.begin();
64 for( ; i!=_readFiles.end(); i++) {
65 if((*i).compare(dec_name) == 0) {
72 void EvtDalitzTable::readXMLDecayFile(const std::string dec_name, bool verbose){
75 report(INFO,"EvtGen")<<"EvtDalitzTable: Reading in xml parameter file "<<dec_name<<endl;
78 _readFiles.push_back(dec_name);
80 EvtDalitzDecayInfo* dalitzDecay = 0;
83 std::string decayParent = "";
84 std::string daugStr = "";
89 std::vector< std::pair<EvtCyclic3::Pair,EvtCyclic3::Pair> > angAndResPairs;
90 std::string shape("");
91 EvtSpinType::spintype spinType(EvtSpinType::SCALAR);
92 double mass(0.), width(0.), FFp(0.), FFr(0.);
93 std::vector<EvtFlatteParam> flatteParams;
97 double aLass(0.), rLass(0.), BLass(0.), phiBLass(0.), RLass(0.), phiRLass(0.), cutoffLass(-1.);
100 parser.open(dec_name);
102 bool endReached = false;
104 while(parser.readNextTag()) {
105 //TAGS FOUND UNDER DATA
106 if(parser.getParentTagTitle() == "data") {
107 if(parser.getTagTitle() == "dalitzDecay") {
110 decayParent = parser.readAttribute("particle");
111 daugStr = parser.readAttribute("daughters");
112 probMax = parser.readAttributeDouble("probMax",-1);
114 checkParticle(decayParent);
115 ipar=EvtPDL::getId(decayParent);
117 std::istringstream daugStream(daugStr);
120 while(std::getline(daugStream, daugh, ' ')) {
121 checkParticle(daugh);
122 daughter[nDaughters++] = EvtPDL::getId(daugh);
126 report(ERROR,"EvtGen") <<
127 "Expected to find three daughters for dalitzDecay of "<<decayParent<<" near line "
128 <<parser.getLineNumber()<<", "<<"found "<<nDaughters<<endl;
129 report(ERROR,"EvtGen") << "Will terminate execution!"<<endl;
133 double m_d1 = EvtPDL::getMass(daughter[0]), m_d2 = EvtPDL::getMass(daughter[1]), m_d3 = EvtPDL::getMass(daughter[2]), M = EvtPDL::getMass(ipar);
135 dp = EvtDalitzPlot( m_d1, m_d2, m_d3, M );
137 dalitzDecay = new EvtDalitzDecayInfo(daughter[0],daughter[1],daughter[2]);
139 } else if(parser.getTagTitle() == "copyDalitz") {
142 int nCopyDaughters = 0;
143 EvtId copyDaughter[3];
145 decayParent = parser.readAttribute("particle");
146 daugStr = parser.readAttribute("daughters");
148 std::string copyParent = parser.readAttribute("copy");
149 std::string copyDaugStr = parser.readAttribute("copyDaughters");
151 checkParticle(decayParent);
152 ipar=EvtPDL::getId(decayParent);
154 checkParticle(copyParent);
155 EvtId copypar=EvtPDL::getId(copyParent);
157 std::istringstream daugStream(daugStr);
158 std::istringstream copyDaugStream(copyDaugStr);
161 while(std::getline(daugStream, daugh, ' ')) {
162 checkParticle(daugh);
163 daughter[nDaughters++] = EvtPDL::getId(daugh);
165 while(std::getline(copyDaugStream, daugh, ' ')) {
166 checkParticle(daugh);
167 copyDaughter[nCopyDaughters++] = EvtPDL::getId(daugh);
170 if(nDaughters!=3 || nCopyDaughters!=3) {
171 report(ERROR,"EvtGen") <<
172 "Expected to find three daughters for copyDecay of "<<decayParent<<
173 " from "<<copyParent<<" near line "<<parser.getLineNumber()<<
174 ", "<<"found "<<nDaughters<<" and "<<nCopyDaughters<<endl;
175 report(ERROR,"EvtGen") << "Will terminate execution!"<<endl;
179 copyDecay(ipar, daughter, copypar, copyDaughter);
181 } else if(parser.getTagTitle() == "/data") { //end of data
186 //TAGS FOUND UNDER DALITZDECAY
187 } else if(parser.getParentTagTitle() == "dalitzDecay") {
188 if(parser.getTagTitle() == "resonance") {
190 flatteParams.clear();
193 EvtComplex ampFactor(parser.readAttributeDouble("ampFactorReal",1.),
194 parser.readAttributeDouble("ampFactorImag",0.));
195 double mag = parser.readAttributeDouble("mag",-999.);
196 double phase = parser.readAttributeDouble("phase",-999.);
197 double real = parser.readAttributeDouble("real",-999.);
198 double imag = parser.readAttributeDouble("imag",-999.);
200 if((real!=-999. || imag!=-999.) && mag==-999. && phase==-999.) {
201 if(real==-999.) { real = 0; }
202 if(imag==-999.) { imag = 0; }
203 mag = sqrt(real*real + imag*imag);
204 phase = atan2(imag,real) * EvtConst::radToDegrees;
213 cAmp = ampFactor*EvtComplex(cos(phase*1.0/EvtConst::radToDegrees),sin(phase*1.0/EvtConst::radToDegrees))*mag;
215 //Resonance particle properties
218 spinType = EvtSpinType::SCALAR;
220 std::string particle = parser.readAttribute("particle");
222 EvtId resId = EvtPDL::getId(particle);
223 if(resId == EvtId(-1,-1)) {
224 report(ERROR,"EvtGen") <<"Unknown particle name:"<<particle.c_str()<<endl;
225 report(ERROR,"EvtGen") <<"Will terminate execution!"<<endl;
228 mass = EvtPDL::getMeanMass(resId);
229 width = EvtPDL::getWidth(resId);
230 spinType = EvtPDL::getSpinType(resId);
234 width = parser.readAttributeDouble("width",width);
235 mass = parser.readAttributeDouble("mass",mass);
236 switch(parser.readAttributeInt("spin",-1)) {
237 case -1://not set here
240 spinType = EvtSpinType::SCALAR;
243 spinType = EvtSpinType::VECTOR;
246 spinType = EvtSpinType::TENSOR;
249 report(ERROR,"EvtGen") << "Unsupported spin near line "<<parser.getLineNumber()<<" of XML file."<<endl;
253 //Shape and form factors
254 shape = parser.readAttribute("shape");
255 FFp = parser.readAttributeDouble("BlattWeisskopfFactorParent",0.0);
256 FFr = parser.readAttributeDouble("BlattWeisskopfFactorResonance",1.5);
258 //Shape specific attributes
259 if(shape=="NonRes_Exp") {
260 alpha = parser.readAttributeDouble("alpha",0.0);
263 aLass = parser.readAttributeDouble("a",2.07);
264 rLass = parser.readAttributeDouble("r",3.32);
265 BLass = parser.readAttributeDouble("B",1.0);
266 phiBLass = parser.readAttributeDouble("phiB",0.0);
267 RLass = parser.readAttributeDouble("R",1.0);
268 phiRLass = parser.readAttributeDouble("phiR",0.0);
269 cutoffLass = parser.readAttributeDouble("cutoff",-1.0);
272 //Daughter pairs for resonance
273 angAndResPairs.clear();
275 std::string resDaugStr = parser.readAttribute("resDaughters");
276 if(resDaugStr != "") {
277 std::istringstream resDaugStream(resDaugStr);
280 EvtId resDaughter[2];
281 while(std::getline(resDaugStream, resDaug, ' ')) {
282 checkParticle(resDaug);
283 resDaughter[nResDaug++] = EvtPDL::getId(resDaug);
286 report(ERROR,"EvtGen") << "Resonance must have exactly 2 daughters near line "<<parser.getLineNumber()<<" of XML file."<<endl;
289 int nRes = getDaughterPairs(resDaughter, daughter, angAndResPairs);
291 report(ERROR,"EvtGen") << "Resonance daughters must match decay daughters near line "<<parser.getLineNumber()<<" of XML file."<<endl;
294 if(parser.readAttributeBool("normalise",true)) cAmp /= sqrt(nRes);
296 if(angAndResPairs.empty()) {
297 switch(parser.readAttributeInt("daughterPair")) {
299 angAndResPairs.push_back(std::make_pair(EvtCyclic3::BC,EvtCyclic3::AB));
302 angAndResPairs.push_back(std::make_pair(EvtCyclic3::CA,EvtCyclic3::BC));
305 angAndResPairs.push_back(std::make_pair(EvtCyclic3::AB,EvtCyclic3::CA));
308 if(shape == "NonRes") { //We don't expect a pair for non-resonant terms but add dummy values for convenience
309 angAndResPairs.push_back(std::make_pair(EvtCyclic3::AB,EvtCyclic3::AB));
312 report(ERROR,"EvtGen") << "Daughter pair must be 1, 2 or 3 near line "<<parser.getLineNumber()<<" of XML file."<<endl;
317 if(parser.isTagInline()) {
318 std::vector< std::pair<EvtCyclic3::Pair,EvtCyclic3::Pair> >::iterator it = angAndResPairs.begin();
319 for( ; it != angAndResPairs.end(); it++) {
320 std::pair<EvtCyclic3::Pair,EvtCyclic3::Pair> pairs = *it;
321 EvtDalitzReso resonance = getResonance(shape, dp, pairs.first, pairs.second, spinType, mass, width, FFp, FFr, alpha, aLass, rLass, BLass, phiBLass, RLass, phiRLass, cutoffLass);
322 dalitzDecay->addResonance(cAmp,resonance);
325 } else if(parser.getTagTitle() == "/dalitzDecay") {
327 report(INFO,"EvtGen") << "probMax is not defined for " << decayParent << " -> " << daugStr << endl;
328 report(INFO,"EvtGen") << "Will now estimate probMax. This may take a while. Once probMax is calculated, update the XML file to skip this step in future." << endl;
329 probMax = calcProbMax(dp,dalitzDecay);
331 dalitzDecay->setProbMax(probMax);
332 addDecay(ipar, *dalitzDecay);
336 report(INFO,"EvtGen") << "Unexpected tag "<<parser.getTagTitle()
337 <<" found in XML decay file near line "
338 <<parser.getLineNumber()<<". Tag will be ignored."<<endl;
340 //TAGS FOUND UNDER RESONANCE
341 } else if(parser.getParentTagTitle() == "resonance"){
342 if(parser.getTagTitle() == "flatteParam") {
343 EvtFlatteParam param(parser.readAttributeDouble("mass1"),
344 parser.readAttributeDouble("mass2"),
345 parser.readAttributeDouble("g"));
346 flatteParams.push_back(param);
347 } else if(parser.getTagTitle() == "/resonance") {
348 std::vector< std::pair<EvtCyclic3::Pair,EvtCyclic3::Pair> >::iterator it = angAndResPairs.begin();
349 for( ; it != angAndResPairs.end(); it++) {
350 std::pair<EvtCyclic3::Pair,EvtCyclic3::Pair> pairs = *it;
351 EvtDalitzReso resonance = getResonance(shape, dp, pairs.first, pairs.second, spinType, mass, width, FFp, FFr, alpha, aLass, rLass, BLass, phiBLass, RLass, phiRLass, cutoffLass);
353 std::vector<EvtFlatteParam>::iterator flatteIt = flatteParams.begin();
354 for( ; flatteIt != flatteParams.end(); flatteIt++) {
355 resonance.addFlatteParam((*flatteIt));
358 dalitzDecay->addResonance(cAmp,resonance);
365 report(ERROR,"EvtGen") << "Either the decay file ended prematurely or the file is badly formed.\n"
366 <<"Error occured near line"<<parser.getLineNumber()<<endl;
371 void EvtDalitzTable::checkParticle(std::string particle) {
372 if (EvtPDL::getId(particle)==EvtId(-1,-1)) {
373 report(ERROR,"EvtGen") <<"Unknown particle name:"<<particle.c_str()<<endl;
374 report(ERROR,"EvtGen") <<"Will terminate execution!"<<endl;
379 void EvtDalitzTable::addDecay(EvtId parent, const EvtDalitzDecayInfo& dec) {
380 if(_dalitztable.find(parent)!=_dalitztable.end()) {
381 _dalitztable[parent].push_back(dec);
383 _dalitztable[parent].push_back(dec);
387 void EvtDalitzTable::copyDecay(EvtId parent, EvtId* daughters,
388 EvtId copy, EvtId* copyd) {
389 EvtDalitzDecayInfo decay(daughters[0],daughters[1],daughters[2]);
390 std::vector<EvtDalitzDecayInfo> copyTable = getDalitzTable(copy);
391 std::vector<EvtDalitzDecayInfo>::iterator i = copyTable.begin();
392 for( ; i != copyTable.end(); i++) {
393 EvtId daughter1 = (*i).daughter1();
394 EvtId daughter2 = (*i).daughter2();
395 EvtId daughter3 = (*i).daughter3();
397 if((copyd[0] == daughter1 && copyd[1] == daughter2 && copyd[2] == daughter3) ||
398 (copyd[0] == daughter1 && copyd[1] == daughter3 && copyd[2] == daughter2) ||
399 (copyd[0] == daughter2 && copyd[1] == daughter1 && copyd[2] == daughter3) ||
400 (copyd[0] == daughter2 && copyd[1] == daughter3 && copyd[2] == daughter1) ||
401 (copyd[0] == daughter3 && copyd[1] == daughter1 && copyd[2] == daughter2) ||
402 (copyd[0] == daughter3 && copyd[1] == daughter2 && copyd[2] == daughter1)) {
403 decay.setProbMax((*i).getProbMax());
404 std::vector<std::pair<EvtComplex, EvtDalitzReso> >::const_iterator j = (*i).getResonances().begin();
405 for( ; j != (*i).getResonances().end(); j++) {
406 decay.addResonance((*j));
408 addDecay(parent,decay);
412 //if we get here then there was no match
413 report(ERROR,"EvtGen") << "Did not find dalitz decays for particle:"
417 std::vector<EvtDalitzDecayInfo> EvtDalitzTable::getDalitzTable(const EvtId& parent) {
418 std::vector<EvtDalitzDecayInfo> table;
419 if ( _dalitztable.find(parent)!=_dalitztable.end() ) {
420 table=_dalitztable[parent];
424 report(ERROR,"EvtGen") << "Did not find dalitz decays for particle:"
432 EvtDalitzReso EvtDalitzTable::getResonance(std::string shape, EvtDalitzPlot dp, EvtCyclic3::Pair angPair, EvtCyclic3::Pair resPair,
433 EvtSpinType::spintype spinType, double mass, double width, double FFp, double FFr, double alpha,
434 double aLass, double rLass, double BLass, double phiBLass, double RLass, double phiRLass, double cutoffLass) {
435 if( shape=="RBW" || shape=="RBW_CLEO") {
436 return EvtDalitzReso( dp, angPair, resPair, spinType, mass, width, EvtDalitzReso::RBW_CLEO, FFp, FFr );
437 } else if( shape=="RBW_CLEO_ZEMACH" ) {
438 return EvtDalitzReso( dp, angPair, resPair, spinType, mass, width, EvtDalitzReso::RBW_CLEO_ZEMACH, FFp, FFr );
439 } else if( shape=="GS" || shape=="GS_CLEO" ) {
440 return EvtDalitzReso( dp, angPair, resPair, spinType, mass, width, EvtDalitzReso::GS_CLEO, FFp, FFr );
441 } else if( shape=="GS_CLEO_ZEMACH" ) {
442 return EvtDalitzReso( dp, angPair, resPair, spinType, mass, width, EvtDalitzReso::GS_CLEO_ZEMACH, FFp, FFr );
443 } else if( shape=="GAUSS" || shape=="GAUSS_CLEO" ) {
444 return EvtDalitzReso( dp, angPair, resPair, spinType, mass, width, EvtDalitzReso::GAUSS_CLEO, FFp, FFr );
445 } else if( shape=="GAUSS_CLEO_ZEMACH" ) {
446 return EvtDalitzReso( dp, angPair, resPair, spinType, mass, width, EvtDalitzReso::GAUSS_CLEO_ZEMACH, FFp, FFr );
447 } else if( shape=="Flatte" ) {
448 return EvtDalitzReso( dp, resPair, mass );
449 } else if( shape=="LASS" ) {
450 return EvtDalitzReso( dp, resPair, mass, width, aLass, rLass, BLass, phiBLass, RLass, phiRLass, cutoffLass, true );
451 } else if( shape=="NonRes" ) {
452 return EvtDalitzReso( );
453 } else if( shape=="NonRes_Linear" ) {
454 return EvtDalitzReso( dp, resPair, EvtDalitzReso::NON_RES_LIN );
455 } else if( shape=="NonRes_Exp" ) {
456 return EvtDalitzReso( dp, resPair, EvtDalitzReso::NON_RES_EXP, alpha );
458 if( shape!="NBW") report(WARNING,"EvtGen")<<"EvtDalitzTable: shape "<<shape<<" is unknown. Defaulting to NBW."<<endl;
459 return EvtDalitzReso( dp, angPair, resPair, spinType, mass, width, EvtDalitzReso::NBW, FFp, FFr );
463 int EvtDalitzTable::getDaughterPairs(EvtId* resDaughter, EvtId* daughter, std::vector< std::pair<EvtCyclic3::Pair,EvtCyclic3::Pair> >& angAndResPairs) {
465 if(resDaughter[0]==daughter[0] && resDaughter[1]==daughter[1]) {
466 angAndResPairs.push_back(std::make_pair(EvtCyclic3::BC,EvtCyclic3::AB)); n++;
467 } else if(resDaughter[0]==daughter[1] && resDaughter[1]==daughter[0]) {
468 angAndResPairs.push_back(std::make_pair(EvtCyclic3::CA,EvtCyclic3::AB)); n++;
471 if(resDaughter[0]==daughter[1] && resDaughter[1]==daughter[2]) {
472 angAndResPairs.push_back(std::make_pair(EvtCyclic3::CA,EvtCyclic3::BC)); n++;
473 } else if(resDaughter[0]==daughter[2] && resDaughter[1]==daughter[1]) {
474 angAndResPairs.push_back(std::make_pair(EvtCyclic3::AB,EvtCyclic3::BC)); n++;
477 if(resDaughter[0]==daughter[2] && resDaughter[1]==daughter[0]) {
478 angAndResPairs.push_back(std::make_pair(EvtCyclic3::AB,EvtCyclic3::CA)); n++;
479 } else if(resDaughter[0]==daughter[0] && resDaughter[1]==daughter[2]) {
480 angAndResPairs.push_back(std::make_pair(EvtCyclic3::BC,EvtCyclic3::CA)); n++;
486 double EvtDalitzTable::calcProbMax(EvtDalitzPlot dp, EvtDalitzDecayInfo* model) {
488 double factor = 1.2; //factor to increase our final answer by
489 int nStep(1000); //number of steps - total points will be 3*nStep*nStep
492 double min(0), max(0), step(0), min2(0), max2(0), step2(0);
495 min = dp.qAbsMin(EvtCyclic3::AB);
496 max = dp.qAbsMax(EvtCyclic3::AB);
497 step = (max-min)/nStep;
498 for(int i=0; i<nStep; ++i) {
499 double qAB = min + i*step;
500 min2 = dp.qMin(EvtCyclic3::BC,EvtCyclic3::AB,qAB);
501 max2 = dp.qMax(EvtCyclic3::BC,EvtCyclic3::AB,qAB);
502 step2 = (max2-min2)/nStep;
503 for(int j=0; j<nStep; ++j) {
504 double qBC = min2+ j*step2;
505 EvtDalitzCoord coord(EvtCyclic3::AB,qAB,EvtCyclic3::BC,qBC);
506 EvtDalitzPoint point(dp,coord);
507 double prob = calcProb(point,model);
508 if(prob > maxProb) maxProb = prob;
513 min = dp.qAbsMin(EvtCyclic3::BC);
514 max = dp.qAbsMax(EvtCyclic3::BC);
515 step = (max-min)/nStep;
516 for(int i=0; i<nStep; ++i) {
517 double qBC = min + i*step;
518 min2 = dp.qMin(EvtCyclic3::CA,EvtCyclic3::BC,qBC);
519 max2 = dp.qMax(EvtCyclic3::CA,EvtCyclic3::BC,qBC);
520 step2 = (max2-min2)/nStep;
521 for(int j=0; j<nStep; ++j) {
522 double qCA = min2+ j*step2;
523 EvtDalitzCoord coord(EvtCyclic3::BC,qBC,EvtCyclic3::CA,qCA);
524 EvtDalitzPoint point(dp,coord);
525 double prob = calcProb(point,model);
526 if(prob > maxProb) maxProb = prob;
531 min = dp.qAbsMin(EvtCyclic3::CA);
532 max = dp.qAbsMax(EvtCyclic3::CA);
533 step = (max-min)/nStep;
534 for(int i=0; i<nStep; ++i) {
535 double qCA = min + i*step;
536 min2 = dp.qMin(EvtCyclic3::AB,EvtCyclic3::CA,qCA);
537 max2 = dp.qMax(EvtCyclic3::AB,EvtCyclic3::CA,qCA);
538 step2 = (max2-min2)/nStep;
539 for(int j=0; j<nStep; ++j) {
540 double qAB = min2+ j*step2;
541 EvtDalitzCoord coord(EvtCyclic3::CA,qCA,EvtCyclic3::AB,qAB);
542 EvtDalitzPoint point(dp,coord);
543 double prob = calcProb(point,model);
544 if(prob > maxProb) maxProb = prob;
547 report(INFO,"EvtGen") << "Largest probability found was " << maxProb << endl;
548 report(INFO,"EvtGen") << "Setting probMax to " << factor*maxProb << endl;
549 return factor*maxProb;
552 double EvtDalitzTable::calcProb(EvtDalitzPoint point, EvtDalitzDecayInfo* model) {
554 std::vector<std::pair<EvtComplex,EvtDalitzReso> > resonances = model->getResonances();
557 std::vector<std::pair<EvtComplex,EvtDalitzReso> >::iterator i = resonances.begin();
558 for( ; i!= resonances.end(); i++) {
559 std::pair<EvtComplex,EvtDalitzReso> res = (*i);
560 amp += res.first * res.second.evaluate( point );