//-------------------------------------------------------------------------- // // Environment: // This software is part of the EvtGen package developed jointly // for the BaBar and CLEO collaborations. If you use all or part // of it, please give an appropriate acknowledgement. // // Copyright Information: See EvtGen/COPYRIGHT // Copyright (C) 1998 Caltech, UCSB // // Module: EvtDecayTable.cc // // Description: // // Modification history: // // DJL/RYD September 25, 1996 Module created // //------------------------------------------------------------------------ // #include "EvtGenBase/EvtPatches.hh" #include #include #include #include #include #include #include #include "EvtGenBase/EvtParticle.hh" #include "EvtGenBase/EvtRandom.hh" #include "EvtGenBase/EvtDecayTable.hh" #include "EvtGenBase/EvtPDL.hh" #include "EvtGenBase/EvtSymTable.hh" #include "EvtGenBase/EvtDecayBase.hh" #include "EvtGenBase/EvtModel.hh" #include "EvtGenBase/EvtParser.hh" #include "EvtGenBase/EvtParserXml.hh" #include "EvtGenBase/EvtReport.hh" #include "EvtGenBase/EvtModelAlias.hh" #include "EvtGenBase/EvtRadCorr.hh" #include "EvtGenBase/EvtExtGeneratorCommandsTable.hh" using std::endl; using std::fstream; using std::ifstream; EvtDecayTable::EvtDecayTable() { _decaytable.clear(); } EvtDecayTable::~EvtDecayTable() { _decaytable.clear(); } EvtDecayTable* EvtDecayTable::getInstance() { static EvtDecayTable* theDecayTable = 0; if (theDecayTable == 0) { theDecayTable = new EvtDecayTable(); } return theDecayTable; } int EvtDecayTable::getNMode(int ipar){ return _decaytable[ipar].getNMode(); } EvtDecayBase* EvtDecayTable::getDecay(int ipar, int imode){ return _decaytable[ipar].getDecayModel(imode); } void EvtDecayTable::printSummary(){ for(size_t i=0;igetId().getAlias(); if ( _decaytable[partnum].getNMode()==0 ) return 0; return _decaytable[partnum].getDecayModel(p); } void EvtDecayTable::readDecayFile(const std::string dec_name, bool verbose){ if ( _decaytable.size() < EvtPDL::entries() ) _decaytable.resize(EvtPDL::entries()); EvtModel &modelist=EvtModel::instance(); EvtExtGeneratorCommandsTable* extGenCommands = EvtExtGeneratorCommandsTable::getInstance(); std::string colon(":"), equals("="); int i; report(INFO,"EvtGen") << "In readDecayFile, reading:"< modelAliasList; do{ token=parser.getToken(itoken++); //Easy way to turn off photos... Lange September 5, 2000 if (token=="noPhotos"){ EvtRadCorr::setNeverRadCorr(); if ( verbose ) report(INFO,"EvtGen") << "As requested, PHOTOS will be turned off."< modelArgList; std::string aliasName=parser.getToken(itoken++); std::string modelName=parser.getToken(itoken++); std::string nameTemp; do{ nameTemp=parser.getToken(itoken++); if (nameTemp!=";") { modelArgList.push_back(nameTemp); } }while(nameTemp!=";"); EvtModelAlias newAlias(aliasName,modelName,modelArgList); modelAliasList.push_back(newAlias); } else if (token=="ChargeConj"){ std::string aname; std::string abarname; aname=parser.getToken(itoken++); abarname=parser.getToken(itoken++); EvtId a=EvtPDL::getId(aname); EvtId abar=EvtPDL::getId(abarname); if (a==EvtId(-1,-1)) { report(ERROR,"EvtGen") <<"Unknown particle name:"<addCommand("PYTHIA", command); } else if (modelist.isCommand(token)){ std::string cnfgstr; cnfgstr=parser.getToken(itoken++); modelist.storeCommand(token,cnfgstr); } else if (token == "PythiaGenericParam" || token == "PythiaAliasParam" || token == "PythiaBothParam") { // Read in any Pythia 8 commands, which will be of the form // pythiaParam module:param=value, with no spaces in the parameter // string! Here, specifies whether the command is for generic // decays, alias decays, or both. // Pythia 6 commands will be defined by the old JetSetPar command // name, which is handled by the modelist.isCommand() statement above. std::string pythiaCommand = parser.getToken(itoken++); std::string pythiaModule(""), pythiaParam(""), pythiaValue(""); // Separate out the string into the 3 sections using the delimiters // ":" and "=". std::vector pComVect1 = this->splitString(pythiaCommand, colon); if (pComVect1.size() == 2) { pythiaModule = pComVect1[0]; std::string pCom2 = pComVect1[1]; std::vector pComVect2 = this->splitString(pCom2, equals); if (pComVect2.size() == 2) { pythiaParam = pComVect2[0]; pythiaValue = pComVect2[1]; } } // Define the Pythia 8 command and pass it to the external generator // command list. Command command; if (token == "PythiaGenericParam") { command["GENERATOR"] = "Generic"; } else if (token == "PythiaAliasParam") { command["GENERATOR"] = "Alias"; } else { command["GENERATOR"] = "Both"; } command["MODULE"] = pythiaModule; command["PARAM"] = pythiaParam; command["VALUE"] = pythiaValue; command["VERSION"] = "PYTHIA8"; extGenCommands->addCommand("PYTHIA", command); } else if (token=="CDecay"){ std::string name; name=parser.getToken(itoken++); ipar=EvtPDL::getId(name); if (ipar==EvtId(-1,-1)) { report(ERROR,"EvtGen") <<"Unknown particle name:"< 3 ) newWidth=atof(parser.getToken(itoken++).c_str()); //Now make the change! EvtPDL::reSetMass(thisPart, newMass); EvtPDL::reSetWidth(thisPart, newWidth); if (verbose ) report(INFO,"EvtGen") << "Changing particle properties of " << pname.c_str() << " Mass=" << newMass << " Width="<=0; int ismodel=modelist.isModel(parser.getToken(itoken)); if (!(isname||ismodel)){ //see if this is an aliased model for(size_t iAlias=0;iAlias=0){ sdaug=parser.getToken(itoken++); daught[n_daugh++]=EvtPDL::getId(sdaug); if (daught[n_daugh-1]==EvtId(-1,-1)) { report(ERROR,"EvtGen") <<"Unknown particle name:"<setPHOTOS(); } if (verbose){ temp_fcn_new->setVerbose(); } if (summary){ temp_fcn_new->setSummary(); } std::vector temp_fcn_new_args; std::string name; int ierr; if ( foundAnAlias==-1 ) { do{ name=parser.getToken(itoken++); if (name!=";") { temp_fcn_new_args.push_back(EvtSymTable::get(name,ierr)); if (ierr) { report(ERROR,"EvtGen") <<"Reading arguments and found:"<< name.c_str()<<" on line:"<< parser.getLineofToken(itoken-1)<=0; int ismodel=modelist.isModel(name); if (ismodel) { report(ERROR,"EvtGen") <<"Expected ';' but found:"<< name.c_str()<<" on line:"<< parser.getLineofToken(itoken-1)< copyMe=modelAliasList[foundAnAlias].getArgList(); temp_fcn_new_args=copyMe; itoken++; } //Found one decay. brfrsum+=brfr; temp_fcn_new->saveDecayInfo(ipar,n_daugh, daught, temp_fcn_new_args.size(), temp_fcn_new_args, temp_fcn_new_model, brfr); double massmin=0.0; // for (i=0;inRealDaughters();i++){ if ( EvtPDL::getMinMass(daught[i])>0.0001 ){ massmin+=EvtPDL::getMinMass(daught[i]); } else { massmin+=EvtPDL::getMeanMass(daught[i]); } } _decaytable[ipar.getAlias()].addMode(temp_fcn_new,brfrsum,massmin); } } while(token!="Enddecay"); _decaytable[ipar.getAlias()].finalize(); } // Allow copying of decays from one particle to another; useful // in combination with RemoveDecay else if (token=="CopyDecay") { std::string newname; std::string oldname; newname=parser.getToken(itoken++); oldname=parser.getToken(itoken++); EvtId newipar=EvtPDL::getId(newname); EvtId oldipar=EvtPDL::getId(oldname); if (oldipar==EvtId(-1,-1)) { report(ERROR,"EvtGen") <<"Unknown particle name:"<= 0) { sdaug = parser.getToken(itoken++); daught[n_daugh++] = EvtPDL::getId(sdaug); if (daught[n_daugh-1]==EvtId(-1,-1)) { report(ERROR,"EvtGen") <<"Unknown particle name:"< temp_fcn_new_args; std::string temp_fcn_new_model("PHSP"); temp_fcn_new->saveDecayInfo(ipar, n_daugh, daught, 0, temp_fcn_new_args, temp_fcn_new_model, 0.); _decaytable[ipar.getAlias()].removeMode(temp_fcn_new); } } while (token != "Enddecay"); itoken++; } else if (token!="End"){ report(ERROR,"EvtGen") << "Found unknown command:'"< EvtPDL::getMinMass(temp) ) { if ( verbose ) report(INFO,"EvtGen") << "Given allowed decays, resetting minMass " << EvtPDL::name(temp).c_str() << " " << EvtPDL::getMinMass(temp) << " to " << minMass << endl; EvtPDL::reSetMassMin(temp,minMass); } } } void EvtDecayTable::readXMLDecayFile(const std::string dec_name, bool verbose){ if ( _decaytable.size() < EvtPDL::entries() ) _decaytable.resize(EvtPDL::entries()); EvtModel &modelist=EvtModel::instance(); EvtExtGeneratorCommandsTable* extGenCommands = EvtExtGeneratorCommandsTable::getInstance(); EvtParserXml parser; parser.open(dec_name); EvtId ipar; std::string decayParent = ""; double brfrSum = 0.; std::vector modelAliasList; bool endReached = false; while(parser.readNextTag()) { //TAGS FOUND UNDER DATA if(parser.getParentTagTitle() == "data") { if(parser.getTagTitle() == "photos") { std::string usage = parser.readAttribute("usage"); if(usage == "always") { EvtRadCorr::setAlwaysRadCorr(); if ( verbose ) report(INFO,"EvtGen") << "As requested, PHOTOS will be turned on for all decays."< modelArgList; std::string alias = parser.readAttribute("name"); std::string model = parser.readAttribute("model"); std::string paramStr = parser.readAttribute("params"); std::istringstream paramStream(paramStr); std::string param; if(paramStr=="") { EvtDecayBase* fcn = modelist.getFcn(model); int i(0); std::string paramName = fcn->getParamName(0); while(paramName!="") { param = parser.readAttribute(paramName,fcn->getParamDefault(i)); if(param=="") break; modelArgList.push_back(param); ++i; paramName = fcn->getParamName(i); } } else { while(std::getline(paramStream, param, ' ')) { modelArgList.push_back(param); } } EvtModelAlias newAlias(alias,model,modelArgList); modelAliasList.push_back(newAlias); } else if(parser.getTagTitle() == "chargeConj") { std::string particle = parser.readAttribute("particle"); std::string conjugate = parser.readAttribute("conjugate"); EvtId a=EvtPDL::getId(particle); EvtId abar=EvtPDL::getId(conjugate); checkParticle(particle); checkParticle(conjugate); EvtPDL::aliasChgConj(a,abar); } else if(parser.getTagTitle() == "conjDecay") { std::string particle = parser.readAttribute("particle"); EvtId a=EvtPDL::getId(particle); EvtId abar=EvtPDL::chargeConj(a); checkParticle(particle); checkParticle(abar.getName()); if (_decaytable[a.getAlias()].getNMode()!=0) { if ( verbose ) report(DEBUG,"EvtGen") << "Redefined decay of "<addCommand("PYTHIA", command); } else if(parser.getTagTitle() == "pythia6Param") { Command command; command["GENERATOR"] = parser.readAttribute("generator"); command["MODULE"] = parser.readAttribute("module"); command["PARAM"] = parser.readAttribute("param"); command["VALUE"] = parser.readAttribute("value"); command["VERSION"] = "PYTHIA6"; extGenCommands->addCommand("PYTHIA", command); } else if(parser.getTagTitle() == "/data") { //end of data endReached = true; parser.close(); break; } else if(parser.getTagTitle() == "Title" || parser.getTagTitle() == "Details" || parser.getTagTitle() == "Author" || parser.getTagTitle() == "Version" //the above tags are expected to be in the XML decay file but are not used by EvtGen || parser.getTagTitle() == "dalitzDecay" || parser.getTagTitle() == "copyDalitz") { //the above tags are only used by EvtGenModels/EvtDalitzTable } else { report(INFO,"EvtGen") << "Unknown tag "< temp_fcn_new_args; double brfr = parser.readAttributeDouble("br"); std::string daugStr = parser.readAttribute("daughters"); std::istringstream daugStream(daugStr); std::string model = parser.readAttribute("model"); std::string paramStr = parser.readAttribute("params"); std::istringstream paramStream(paramStr); bool decVerbose = parser.readAttributeBool("verbose"); bool decPhotos = parser.readAttributeBool("photos"); bool decSummary = parser.readAttributeBool("summary"); std::string daugh; while(std::getline(daugStream, daugh, ' ')) { checkParticle(daugh); daughter[nDaughters++] = EvtPDL::getId(daugh); } int modelAlias = -1; for(size_t iAlias=0;iAliassetPHOTOS(); if(decVerbose) temp_fcn_new->setVerbose(); if(decSummary) temp_fcn_new->setSummary(); int ierr; if(modelAlias == -1) { std::string param; if(paramStr == "") { int i(0); std::string paramName = temp_fcn_new->getParamName(0); while(paramName != "") { param = parser.readAttribute(paramName,temp_fcn_new->getParamDefault(i)); if(param == "") break; //params must be added in order so we can't just skip the missing ones temp_fcn_new_args.push_back(EvtSymTable::get(param,ierr)); if (ierr) { report(ERROR,"EvtGen") <<"Reading arguments near line "<getParamName(i); } } else {//if the params are not set seperately while(std::getline(paramStream, param, ' ')) { temp_fcn_new_args.push_back(EvtSymTable::get(param,ierr)); if (ierr) { report(ERROR,"EvtGen") <<"Reading arguments near line "< copyMe=modelAliasList[modelAlias].getArgList(); temp_fcn_new_args=copyMe; } brfrSum+=brfr; temp_fcn_new->saveDecayInfo(ipar,nDaughters, daughter, temp_fcn_new_args.size(), temp_fcn_new_args, temp_fcn_new_model, brfr); double massMin=0.0; for (int i=0;inRealDaughters();i++){ if ( EvtPDL::getMinMass(daughter[i])>0.0001 ){ massMin+=EvtPDL::getMinMass(daughter[i]); } else { massMin+=EvtPDL::getMeanMass(daughter[i]); } } _decaytable[ipar.getAlias()].addMode(temp_fcn_new,brfrSum,massMin); } else if(parser.getTagTitle() == "/decay") { //end of a particle _decaytable[ipar.getAlias()].finalize(); } else report(INFO,"EvtGen") << "Unexpected tag "< temp_fcn_new_args; std::string temp_fcn_new_model("PHSP"); temp_fcn_new->saveDecayInfo(ipar, nDaughters, daughter, 0, temp_fcn_new_args, temp_fcn_new_model, 0.); _decaytable[ipar.getAlias()].removeMode(temp_fcn_new); } else if(parser.getTagTitle() != "/removeDecay") { report(INFO,"EvtGen") << "Unexpected tag "< EvtPDL::getMinMass(temp) ) { if ( verbose ) report(INFO,"EvtGen") << "Given allowed decays, resetting minMass " << EvtPDL::name(temp).c_str() << " " << EvtPDL::getMinMass(temp) << " to " << minMass << endl; EvtPDL::reSetMassMin(temp,minMass); } } } bool EvtDecayTable::stringToBoolean(std::string valStr) { return (valStr == "true" || valStr == "1" || valStr == "on" || valStr == "yes"); } void EvtDecayTable::checkParticle(std::string particle) { if (EvtPDL::getId(particle)==EvtId(-1,-1)) { report(ERROR,"EvtGen") <<"Unknown particle name:"<findDecayModel(aliasInt, modeInt); return theModel; } EvtDecayBase* EvtDecayTable::findDecayModel(int aliasInt, int modeInt) { EvtDecayBase* theModel(0); if (aliasInt >= 0 && aliasInt < (int) EvtPDL::entries()) { theModel = _decaytable[aliasInt].getDecayModel(modeInt); } return theModel; } bool EvtDecayTable::hasPythia(EvtId id) { bool hasPythia = this->hasPythia(id.getAlias()); return hasPythia; } bool EvtDecayTable::hasPythia(int aliasInt) { bool hasPythia(false); if (aliasInt >= 0 && aliasInt < (int) EvtPDL::entries()) { hasPythia = _decaytable[aliasInt].isJetSet(); } return hasPythia; } int EvtDecayTable::getNModes(EvtId id) { int nModes = this->getNModes(id.getAlias()); return nModes; } int EvtDecayTable::getNModes(int aliasInt) { int nModes(0); if (aliasInt >= 0 && aliasInt < (int) EvtPDL::entries()) { nModes = _decaytable[aliasInt].getNMode(); } return nModes; } int EvtDecayTable::findChannel(EvtId parent, std::string model, int ndaug, EvtId *daugs, int narg, std::string *args){ int i,j,right; EvtId daugs_scratch[50]; int nmatch,k; for(i=0;i<_decaytable[parent.getAlias()].getNMode();i++){ right=1; right=right&&model==_decaytable[parent.getAlias()]. getDecay(i).getDecayModel()->getModelName(); right=right&&(ndaug==_decaytable[parent.getAlias()]. getDecay(i).getDecayModel()->getNDaug()); right=right&&(narg==_decaytable[parent.getAlias()]. getDecay(i).getDecayModel()->getNArg()); if ( right ){ for(j=0;jgetNDaug();j++){ for(k=0;kgetDaug(j)){ daugs_scratch[k]=EvtId(-1,-1); nmatch++; break; } } } right=right&&(nmatch==ndaug); for(j=0;j<_decaytable[parent.getAlias()]. getDecay(i).getDecayModel()->getNArg();j++){ right=right&&(args[j]==_decaytable[parent.getAlias()]. getDecay(i).getDecayModel()->getArgStr(j)); } } if (right) return i; } return -1; } int EvtDecayTable::inChannelList(EvtId parent, int ndaug, EvtId *daugs){ int i,j,k; EvtId daugs_scratch[MAX_DAUG]; int dsum=0; for(i=0;igetDSum()==dsum){ int nd=thedecaymodel->getNDaug(); if (ndaug==nd){ for(j=0;jgetDaug(j)){ daugs_scratch[k]=EvtId(-1,-1); nmatch++; break; } } } if ((nmatch==ndaug)&& (! ((thedecaymodel->getModelName()=="JETSET")|| (thedecaymodel->getModelName()=="PYTHIA")))){ return i; } } } } return -1; } std::vector EvtDecayTable::splitString(std::string& theString, std::string& splitter) { // Code from STLplus std::vector result; if (!theString.empty() && !splitter.empty()) { for (std::string::size_type offset = 0;;) { std::string::size_type found = theString.find(splitter, offset); if (found != std::string::npos) { std::string tmpString = theString.substr(offset, found-offset); if (tmpString.size() > 0) {result.push_back(tmpString);} offset = found + splitter.size(); } else { std::string tmpString = theString.substr(offset, theString.size()-offset); if (tmpString.size() > 0) {result.push_back(tmpString);} break; } } } return result; }