// ************************************************************************ // // Analysis Task using PndSimpleCombiner // // ************************************************************************ // // Parameters: // - anadecay : Decay specification, e.g. "phi -> K+ K-; D_s+ -> phi pi+" (automatic charged conjugation; particle used have to be defined beforehand) // Keyword 'nocc' at end of decay definition suppresses automatic charged conjugation // This string is handed over to PndSimpleCombiner // // - params : configuration parameters, e.g. "fit4c:qamc". The string contains also parameters handled by PndSimpleCombiner; those handled by this task are: // - fit4c[ K+ K-; D_s+ -> phi pi+", '!ntp0' would skip dump of TTree for phi->KK // // K.Goetzen 1/2015 // // ************************************************************************ // The header file #include "PndSimpleCombinerTask.h" // C++ headers #include #include // FAIR headers #include "FairRootManager.h" #include "FairRunAna.h" #include "FairRuntimeDb.h" #include "FairRun.h" #include "FairRuntimeDb.h" // ROOT headers #include "TClonesArray.h" #include "TVector3.h" #include "TH1F.h" #include "TH2F.h" #include "TDatabasePDG.h" // RHO headers #include "RhoCandidate.h" #include "RhoHistogram/RhoTuple.h" #include "RhoFactory.h" #include "RhoMassParticleSelector.h" #include "RhoTuple.h" // Analysis headers #include "PndAnalysis.h" #include "Pnd4CFitter.h" #include "PndKinVtxFitter.h" #include "PndKinFitter.h" #include "PndVtxPoca.h" #include "PndRhoTupleQA.h" #include "PndEventShape.h" #include "PndSimpleCombiner.h" // Soft Trigger Header #include "PndOnlineFilterInfo.h" using std::cout; using std::endl; // ----- Default constructor ------------------------------------------- PndSimpleCombinerTask::PndSimpleCombinerTask(TString anadecay, TString anaparms, double p, int run, int mode) : FairTask("PndSimpleCombinerTask"), fVerbose(0), fEvtCount(0), fRun(run), fMode(mode), fRunMult(10000), fAnaDecay(anadecay), fAnaParms(anaparms), fNntp(0), fPidAlgo("PidAlgoEmcBayes;PidAlgoDrc;PidAlgoDisc;PidAlgoStt;PidAlgoMdtHardCuts;PidAlgoSciT;PidAlgoRich;PidAlgoFtof"), fQaMC(false), fQaEventShape(false), fQaRecoInfo(0), fQaEvShapeNtp(false), fFit4C(false), fBest4C(false), fFitVtx(false), fFit4CChiCut(1e15), fFitVtxChiCut(1e8), fAnalysis(0), fSimpleCombiner(0), fNodump(0), nmc(0), nevt(0) { fIni.SetXYZT(0,0,0,0); double mp = 0.938272; if (p>0.0001) fIni.SetXYZT(0,0,p, sqrt(p*p+mp*mp)+mp); } // ------------------------------------------------------------------------- // ----- Destructor ---------------------------------------------------- PndSimpleCombinerTask::~PndSimpleCombinerTask() { if (fSimpleCombiner) delete fSimpleCombiner; delete fAnalysis; } // ------------------------------------------------------------------------- void PndSimpleCombinerTask::InitParms() { fAnaParms.ReplaceAll(" ",""); StringList pars; SplitString(fAnaParms,":",pars); // loop over all parameters for (unsigned int i=0;i=0 && ntpnum<32) fNodump |= (1<SetVerbose(fVerbose); fSimpleCombiner->Print(); } // ******* // ******* PREPARE/CREATE THE STUFF YOU NEED // ******* // *** // *** Prepare RhoTuple output // *** // *** Save current gDirectory TDirectory *dir = gDirectory; FairRootManager::Instance()->GetOutFile()->cd(); std::vector toks; fNntp = SplitString(fAnaDecay,";",toks); // *** create some ntuples for (int i=0;iGetInternalTree()->SetDirectory(gDirectory); } vntp.push_back(n); TString pname = toks[i](0,toks[i].Index("->")); pname.ReplaceAll(" ",""); if (TDatabasePDG::Instance()->GetParticle(pname)) {vmpdg.push_back(TDatabasePDG::Instance()->GetParticle(pname)->PdgCode());} } // *** create MC ntuple if (fQaMC) nmc = new RhoTuple("nmc", "mctruth info"); if (nmc) nmc->GetInternalTree()->SetDirectory(gDirectory); // *** create EventShape ntuple if (fQaEvShapeNtp) nevt = new RhoTuple("nevt", "event shape info"); if (nevt) nevt->GetInternalTree()->SetDirectory(gDirectory); // *** restore original gDirectory dir->cd(); // *** Connect to the Online Filter Info fOnlineFilterInfo = ( TClonesArray* ) FairRootManager::Instance()->GetObject ( "OnlineFilterInfo" ); // ****** Print out some info from PndSimpleCombinerTask cout <<"\n------------------------------------------"<GetParticle(vmpdg[i])->GetName()<<") "; cout <<"\n------------------------------------------\n\n"<NDaughters();++i) { if (fabs(c->Daughter(i)->Charge())>1e-6) nd++; } return nd; } // ------------------------------------------------------------------------- int PndSimpleCombinerTask::SplitString(TString s, TString delim, StringList &toks) { toks.clear(); TObjArray *tok = s.Tokenize(delim); int N = tok->GetEntries(); for (int i=0;iAt(i))->String(); st.ReplaceAll("\t",""); st = st.Strip(TString::kBoth); if (st != "") toks.push_back(st); } return toks.size(); } // ------------------------------------------------------------------------- // ----- Public method Exec -------------------------------------------- void PndSimpleCombinerTask::Exec(Option_t*) { // *** some variables int i=0,j=0; // *** necessary to read the next event fAnalysis->GetEventInTask(); // *** print event counter if (!(++fEvtCount%100)) cout << "[PndSimpleCombinerTask] evt "<At ( 0 ); // determine pbarmom if not done so far if (fIni.T()<1e-6) { RhoCandList mclist; fAnalysis->FillList(mclist, "McTruth"); if (mclist.GetLength()>0) { double p = mclist[0]->P3().Pz(); double mp = 0.938272; fIni.SetXYZT(0,0,p, sqrt(p*p+mp*mp)+mp); } } // *** QA tool for simple dumping of analysis results in RhoRuple // *** WIKI: https://panda-wiki.gsi.de/foswiki/bin/view/Computing/PandaRootAnalysisJuly13#PndRhoTupleQA PndRhoTupleQA qa(fAnalysis,fIni.P()); // *** RhoCandLists for the analysis RhoCandList l1, l2, all; // *** store MC info in ntuple if (nmc) { nmc->Column("ev", (Int_t) fEvtCount); qa.qaMcList(nmc); nmc->DumpData(); } // *** Setup event shape object PndEventShape *evsh = 0; if (fQaEventShape || fQaEvShapeNtp) { fAnalysis->FillList(all, "All", fPidAlgo); evsh = new PndEventShape(all, fIni, 0.05, 0.1); } // *** Store event shape info in ntuple if (fQaEvShapeNtp) { nevt->Column("ev", (Int_t) fEvtCount); nevt->Column("run", (Int_t) fRun); nevt->Column("uid", (Int_t) fRun*fRunMult+fEvtCount); nevt->Column("mode", (Int_t) fMode); qa.qaP4("beam", fIni, nevt); qa.qaEventShape("es", evsh, nevt); nevt->DumpData(); } // ***** // *** combinatorics // ***** if (fSimpleCombiner) { fSimpleCombiner->Combine(); // ntuple dump for (i=0;iGetParticle(pdg)->AntiParticle()) apdg = TDatabasePDG::Instance()->GetParticle(pdg)->AntiParticle()->PdgCode(); // check whether there is an own ntuple connected to the anti-particle pdg; if yes, reset apdg for (j=0; jGetList(l1, pdg); if (apdg!=0 && fSimpleCombiner->GetList(l2, apdg)) l1.Append(l2); //RhoMassParticleSelector msel("msel",TDatabasePDG::Instance()->GetParticle(pdg)->Mass(),0.2); //l1.Select(&msel); // number of charged daughters for vtx fit int ncdau = -1; // determine the best chi2 from 4C fit in case we only want to store the best candidate double best4cChi2 = 1e10; for (j=0;jP4())).M(); Float_t msum = l1[j]->M() + mmiss; // in case we do 4C fit, we need to do determine first, whether the candidate is the best one // flag whether the fit is accepted bool fitaccept = true; // for the last list we perform a 4C fit if (fFit4C && i==fNntp-1) { PndKinFitter fit4c(l1[j]); fit4c.Add4MomConstraint(fIni); fit4c.Fit(); double chi2_4c = fit4c.GetChi2(); if (chi2_4c>=fFit4CChiCut) fitaccept = false; if (chi2_4c>best4cChi2 || !fitaccept) continue; best4cChi2 = chi2_4c; RhoCandidate *cfit = l1[j]->GetFit(); vntp[i]->Column("chi24c", (Float_t) chi2_4c); qa.qaP4("f4cx", cfit->P4(), vntp[i]); for (int k=0;kNDaughters();++k) { RhoCandidate *d0fit = cfit->Daughter(k); qa.qaP4(TString::Format("f4cxd%d",k),d0fit->P4(),vntp[i]); for (int k2=0;k2NDaughters();++k2) { RhoCandidate *ddfit = d0fit->Daughter(k2); qa.qaP4(TString::Format("f4cxd%dd%d",k,k2),ddfit->P4(),vntp[i]); } } } vntp[i]->Column("ev", (Int_t) fEvtCount); vntp[i]->Column("cand", (Int_t) j); vntp[i]->Column("ncand", (Int_t) l1.GetLength()); vntp[i]->Column("run", (Int_t) fRun); vntp[i]->Column("uid", (Int_t) fRun*fRunMult+fEvtCount); vntp[i]->Column("mode", (Int_t) fMode); vntp[i]->Column("mmiss", (Float_t) mmiss); vntp[i]->Column("msum", (Float_t) msum); qa.qaP4("beam", fIni, vntp[i]); // store information about composite candidate tree recursively (see PndTools/AnalysisTools/PndRhoTupleQA) qa.qaComp("x", l1[j], vntp[i]); // also optional for reco info if (fQaRecoInfo==1) qa.qaRecoShortTree("x", l1[j], vntp[i]); else if (fQaRecoInfo==2) qa.qaRecoFullTree("x", l1[j], vntp[i]); // store info about event shapes if (fQaEventShape) qa.qaEventShapeShort("es",evsh, vntp[i]); // *** store info from trigger if (stInfo) { vntp[i]->Column("trig", (Int_t) stInfo->Tagged() ); // event triggered vntp[i]->Column("ntrig", (Int_t) stInfo->GetNTagTotal()); // total number of triggered candidates from all active lines } // store the 4-vector of the truth matched candidate (or a dummy, if not matched to keep ntuple consistent) RhoCandidate *truth = l1[j]->GetMcTruth(); TLorentzVector lv; if (truth) lv = truth->P4(); qa.qaP4("trx", lv, vntp[i]); // shall we do a vertex fit? if (fFitVtx && ncdau>1) { PndKinVtxFitter vtxfitter(l1[j]); // *** instantiate the vertex fitter; input is the object to be fitted vtxfitter.Fit(); // *** perform fit RhoCandidate *cfit = l1[j]->GetFit(); // *** get the fitted candidate qa.qaVtx("fvxx",cfit,vntp[i]); qa.qaP4("fvxx", cfit->P4(), vntp[i]); double chi2_vtx = vtxfitter.GetChi2(); // *** and the chi^2 of the fit vntp[i]->Column("chi2vx", (Float_t) chi2_vtx); if (chi2_vtx>=fFitVtxChiCut) fitaccept = false; } if (fitaccept && ((iDumpData(); } if (fBest4C && i==fNntp-1 && best4cChi2<1e10) { vntp[i]->DumpData();} } } if (evsh) delete evsh; } void PndSimpleCombinerTask::Finish() { if (nmc) nmc->GetInternalTree()->Write(); if (nevt) nevt->GetInternalTree()->Write(); for (int i=0;iGetInternalTree()->Write(); } ClassImp(PndSimpleCombinerTask)