MpdConvPi0.cxx 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  1. #include <iostream>
  2. #include <fstream> // std::ifstream
  3. #include "MpdKalmanFilter.h"
  4. #include "MpdMCTrack.h"
  5. #include "MpdTpcKalmanTrack.h"
  6. #include "MpdEmcClusterKI.h"
  7. #include "MpdParticle.h"
  8. #include "MpdVertex.h"
  9. #include "MpdEvent.h"
  10. #include "MpdEmcGeoUtils.h"
  11. #include "MpdConvPi0.h"
  12. #include "TFile.h"
  13. ClassImp(MpdConvPi0)
  14. MpdConvPi0::MpdConvPi0(std::string input, std::string config){
  15. mParamConfig=config ;
  16. //Create TChain
  17. mChain = new TChain("mpdsim") ;
  18. std::ifstream ifs (input);
  19. std::string fname;
  20. if (ifs.is_open()) {
  21. while(ifs >> fname){
  22. cout << "Adding to chain: "<< fname << endl ;
  23. mChain->AddFile(fname.data()) ;
  24. }
  25. }
  26. else {
  27. std::cout << "Error opening file " << input << endl ;
  28. }
  29. ifs.close() ;
  30. }
  31. void MpdConvPi0::init(){
  32. mParams.ReadFromFile(mParamConfig) ;
  33. mParams.Print() ;
  34. // Setup branches
  35. mChain->SetBranchAddress("MCEventHeader.", &mMCHeader);
  36. mChain->SetBranchAddress("MCTrack", &mMCTracks);
  37. mChain->SetBranchAddress("MPDEvent.", &mMPDEvent);
  38. mEMCClusters = new TObjArray() ;
  39. mChain->SetBranchAddress("EmcCluster",&mEMCClusters);
  40. mChain->SetBranchAddress("Vertex",&mVertexes);
  41. mChain->SetBranchAddress("TpcKalmanTrack",&mKalmanTracks);
  42. //Prepare histograms etc.
  43. mHistoList.SetOwner(kTRUE);
  44. //General QA
  45. mhEvents = new TH1F("hEvents","Number of events",10,0.,10.) ;
  46. mHistoList.Add(mhEvents) ;
  47. mhVertex = new TH1F("hVertex","Event vertex distribution",50,-100.,100.) ;
  48. mHistoList.Add(mhVertex) ;
  49. mhCentrality=new TH1F("hCentrality","Centrality distribution",100,0.,100.) ;
  50. mHistoList.Add(mhCentrality) ;
  51. //V0selection
  52. const int nPtbin = 100;
  53. const float pTmin=0.;
  54. const float pTmax=5.;
  55. mhCutEff = new TH2F("hCutEff","track cut efficiency",21,0.,21.,nPtbin,pTmin,pTmax) ;
  56. mHistoList.Add(mhCutEff) ;
  57. mhNhits = new TH1F("hNhits","Number of hits per track",100,0.,100.) ;
  58. mHistoList.Add(mhNhits) ;
  59. mhTracks = new TH2F("hTracks","track occupancy pt vs eta",nPtbin,pTmin,pTmax,100,-1.5,1.5) ;
  60. mHistoList.Add(mhTracks) ;
  61. mhProbEl = new TH2F("hProbEl","Electron probability",100,0.,1.,nPtbin,pTmin,pTmax) ;
  62. mHistoList.Add(mhProbEl) ;
  63. mhdEdx = new TH2F("hdEdx","dEdx",100,-10,10.,nPtbin,pTmin,pTmax) ;
  64. mHistoList.Add(mhdEdx) ;
  65. mhConvMap = new TH3F("hConvMap","Conversion map (r,phi,z)",100,0.,280.,100,0.,TMath::Pi(),100,-200.,200.) ;
  66. mHistoList.Add(mhConvMap) ;
  67. mhAlpha = new TH2F("hAlpha","#alpha distribution",100,0.,1.,nPtbin,pTmin,pTmax) ;
  68. mHistoList.Add(mhAlpha) ;
  69. mhChi2 = new TH2F("hChi2","#chi^{2}",100,0.,50.,nPtbin,pTmin,pTmax) ;
  70. mHistoList.Add(mhChi2) ;
  71. mhDist = new TH2F("hDist","track DCA",100,0.,10.,nPtbin,pTmin,pTmax) ;
  72. mHistoList.Add(mhDist) ;
  73. hmMassEE= new TH2F("mEE","m_{ee}",100,0.,0.3,nPtbin,pTmin,pTmax) ;
  74. mHistoList.Add(hmMassEE) ;
  75. mhCosPsi= new TH2F("cosPsi","cos(#psi)",100,0.,TMath::Pi(),nPtbin,pTmin,pTmax) ;
  76. mHistoList.Add(mhCosPsi) ;
  77. mhArmPo = new TH2F("Armenteros","Armenteros",100,-1,1,100,0,0.3);
  78. mHistoList.Add(mhArmPo) ;
  79. mhConvSp = new TH2F("ConvSp","Conv Sp",nPtbin,pTmin,pTmax,100,-1.5,1.5);
  80. mHistoList.Add(mhConvSp) ;
  81. mhAsym = new TH2F("Asymetry","Asymetry",200,0,1,nPtbin,pTmin,pTmax);
  82. mHistoList.Add(mhAsym) ;
  83. if(isMC){
  84. mhProbElTrue = new TH2F("hProbElTrue","Electron probability, true electrons",100,0.,1.,nPtbin,pTmin,pTmax) ;
  85. mHistoList.Add(mhProbElTrue) ;
  86. mhdEdxTrue = new TH2F("hdEdxTrue","dEdx",100,-10,10.,nPtbin,pTmin,pTmax) ;
  87. mHistoList.Add(mhdEdxTrue) ;
  88. mhConvMapTrue = new TH3F("hConvMapTrue","Conversion map (r,phi,z)",100,0.,280.,100,0.,TMath::Pi(),100,-200.,200.) ;
  89. mHistoList.Add(mhConvMapTrue) ;
  90. mhAlphaTrue = new TH2F("hAlphaTrue","#alpha distribution",100,0.,1.,nPtbin,pTmin,pTmax) ;
  91. mHistoList.Add(mhAlphaTrue) ;
  92. mhChi2True = new TH2F("hChi2True","#chi^{2}",100,0.,50.,nPtbin,pTmin,pTmax) ;
  93. mHistoList.Add(mhChi2True) ;
  94. mhDistTrue = new TH2F("hDistTrue","track DCA",100,0.,10.,nPtbin,pTmin,pTmax) ;
  95. mHistoList.Add(mhDistTrue) ;
  96. hmMassEETrue= new TH2F("mEETrue","m_{ee}",100,0.,0.3,nPtbin,pTmin,pTmax) ;
  97. mHistoList.Add(hmMassEETrue) ;
  98. mhCosPsiTrue= new TH2F("cosPsiTrue","cos(#psi)",100,0.,TMath::Pi(),nPtbin,pTmin,pTmax) ;
  99. mHistoList.Add(mhCosPsiTrue) ;
  100. mhArmPoTrue = new TH2F("ArmenterosTrue","Armenteros",100,-1,1,100,0,0.3);
  101. mHistoList.Add(mhArmPoTrue) ;
  102. mhAsymTrue = new TH2F("AsymetryTrue","Asymetry",200,0,1,nPtbin,pTmin,pTmax);
  103. mHistoList.Add(mhAsymTrue) ;
  104. mhConvSpTrue = new TH2F("ConvSpTrue","Conv Sp",nPtbin,pTmin,pTmax,100,-1.5,1.5);
  105. mHistoList.Add(mhConvSpTrue) ;
  106. }
  107. //Cluster selection
  108. mhCluCutEff = new TH2F("hCluCutEff","cluster cut efficiency",10,0.,10.,nPtbin,pTmin,pTmax) ;
  109. mHistoList.Add(mhCluCutEff) ;
  110. // Inv mass histos
  111. const int nMbins= 200;
  112. const float mMax= 1.;
  113. for(int cen=0; cen<mHistoCentBins; cen++){
  114. mhRealCalo[cen] = new TH2F(Form("hRealCalo_cen%d",cen),Form("Real inv mass, calorimeter"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  115. mHistoList.Add(mhRealCalo[cen]) ;
  116. mhMixedCalo[cen] = new TH2F(Form("hMixedCalo_cen%d",cen),Form("Mixed inv mass, calorimeter"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  117. mHistoList.Add(mhMixedCalo[cen]) ;
  118. mhRealHybrid[cen] = new TH2F(Form("hRealHybrid_cen%d",cen),Form("Real inv mass, hybrid"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  119. mHistoList.Add(mhRealHybrid[cen]) ;
  120. mhMixedHybrid[cen] = new TH2F(Form("hMixedHybrid_cen%d",cen),Form("Mixed inv mass, hybrid"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  121. mHistoList.Add(mhMixedHybrid[cen]) ;
  122. mhRealConv[cen] = new TH2F(Form("hRealConv_cen%d",cen),Form("Real inv mass, conversion"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  123. mHistoList.Add(mhRealConv[cen]) ;
  124. mhMixedConv[cen] = new TH2F(Form("hMixedConversion_cen%d",cen),Form("Mixed inv mass, conversion"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  125. mHistoList.Add(mhMixedConv[cen]) ;
  126. if(isMC){
  127. mhRealCaloTrue[cen] = new TH2F(Form("hRealCaloTrue_cen%d",cen),Form("Real inv mass, calorimeter"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  128. mHistoList.Add(mhRealCaloTrue[cen]) ;
  129. mhRealHybridTrue[cen] = new TH2F(Form("hRealHybridTrue_cen%d",cen),Form("Real inv mass, hybrid"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  130. mHistoList.Add(mhRealHybridTrue[cen]) ;
  131. mhRealConvTrue[cen] = new TH2F(Form("hRealConvTrue_cen%d",cen),Form("Real inv mass, conversion"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  132. mHistoList.Add(mhRealConvTrue[cen]) ;
  133. mhRealCaloTrueEl[cen] = new TH2F(Form("hRealCaloTrueEl_cen%d",cen),Form("Real inv mass, calorimeter"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  134. mHistoList.Add(mhRealCaloTrueEl[cen]) ;
  135. mhRealHybridTrueEl[cen] = new TH2F(Form("hRealHybridTrueEl_cen%d",cen),Form("Real inv mass, hybrid"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  136. mHistoList.Add(mhRealHybridTrueEl[cen]) ;
  137. mhRealConvTrueEl[cen] = new TH2F(Form("hRealConvTrueEl_cen%d",cen),Form("Real inv mass, conversion"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  138. mHistoList.Add(mhRealConvTrueEl[cen]) ;
  139. mhRealCaloTrueAll[cen] = new TH2F(Form("hRealCaloTrueAll_cen%d",cen),Form("Real inv mass, calorimeter"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  140. mHistoList.Add(mhRealCaloTrueAll[cen]) ;
  141. mhRealHybridTrueAll[cen] = new TH2F(Form("hRealHybridTrueAll_cen%d",cen),Form("Real inv mass, hybrid"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  142. mHistoList.Add(mhRealHybridTrueAll[cen]) ;
  143. mhRealConvTrueAll[cen] = new TH2F(Form("hRealConvTrueAll_cen%d",cen),Form("Real inv mass, conversion"),nMbins,0.,mMax,nPtbin,pTmin,pTmax) ;
  144. mHistoList.Add(mhRealConvTrueAll[cen]) ;
  145. }
  146. }
  147. if(isMC){
  148. //spectra of primary pi0.eta,...
  149. for(int cen=0; cen<mHistoCentBins; cen++){
  150. hPrimPi0[cen] = new TH2F(Form("PrimaryPi0_cen%d",cen),"Centrality",nPtbin,pTmin,pTmax,100,-2.,2.) ;
  151. mHistoList.Add(hPrimPi0[cen]) ;
  152. }
  153. }
  154. }
  155. //--------------------------------------
  156. void MpdConvPi0::processData(){
  157. int n = mChain->GetEntries();
  158. cout << "Processing " << n << " events " << endl ;
  159. for(int iEvent=0; iEvent<n; iEvent++){
  160. mChain->GetEvent(iEvent) ;
  161. if(!isInitialized){
  162. //Read geometry field etc
  163. mChain->GetFile()->Get("FairGeoParSet");
  164. mAna = new FairRunAna();
  165. //To propagate tracks
  166. mKF = MpdKalmanFilter::Instance() ;
  167. mKF->Init();
  168. mKHit.SetType(MpdKalmanHit::kFixedR);
  169. mPID = new MpdPid(mParams.mPIDsigM, mParams.mPIDsigE, mParams.mPIDenergy, mParams.mPIDkoeff, mParams.mPIDgenerator, mParams.mPIDtracking, mParams.mPIDparticles);
  170. isInitialized = true ;
  171. }
  172. if(!selectEvent()){ ///
  173. continue;
  174. }
  175. if(isMC){
  176. for(int i=0; i<mMCTracks->GetEntriesFast();i++){
  177. MpdMCTrack* pr= (static_cast<MpdMCTrack*>(mMCTracks->At(i))) ;
  178. if(pr->GetPdgCode()==111){
  179. if(pr->GetStartX()*pr->GetStartX()+pr->GetStartY()*pr->GetStartY()<1.){
  180. TVector3 momentum;
  181. pr->GetMomentum(momentum);
  182. hPrimPi0[mCenBin]->Fill(momentum.Pt(), momentum.Y()) ;
  183. }
  184. }
  185. }
  186. }
  187. selectConversion();
  188. selectClusters();
  189. processHistograms() ;
  190. }
  191. }
  192. void MpdConvPi0::endAnalysis(){
  193. //write collected histos to file
  194. cout << "Writing output to file " << mOutFile << endl ;
  195. TFile fout(mOutFile.data(),"recreate") ;
  196. TIter next(&mHistoList);
  197. TH1 * obj ;
  198. while ((obj = (TH1*)next())){
  199. obj->Write();
  200. }
  201. // fout.WriteObjectAny(&mStorage, "std::vector<V0>", "V0s");
  202. fout.Close() ;
  203. }
  204. //--------------------------------------
  205. bool MpdConvPi0::selectEvent(){
  206. mhEvents->Fill(0.5) ;
  207. // Vertex z coordinate
  208. MpdVertex *vertex = (MpdVertex*) mVertexes->First();
  209. vertex->Position(mPrimaryVertex);
  210. mhVertex->Fill(mPrimaryVertex.Z()) ;
  211. if(fabs(mPrimaryVertex.Z())>mParams.mZvtxCut){
  212. return false ;
  213. }
  214. mZvtxBin = 0.5*(mPrimaryVertex.Z() / mParams.mZvtxCut +1 ) * nMixEventZ ;
  215. if(mZvtxBin<0)mZvtxBin=0;
  216. if(mZvtxBin>=nMixEventZ)mZvtxBin=nMixEventZ-1;
  217. mhEvents->Fill(1.5) ;
  218. //Centrality
  219. // mhCentrality->Fill(cen) ;
  220. mCenBin=0;
  221. mhEvents->Fill(2.5) ;
  222. //ZCD vs TPC (pileup?)
  223. mhEvents->Fill(3.5) ;
  224. //Eventplane TODO
  225. mRPBin=0 ;
  226. mhEvents->Fill(4.5) ;
  227. return true ;
  228. }
  229. //--------------------------------------
  230. void MpdConvPi0::selectConversion(){
  231. //Select V0 in this event
  232. mV0.clear() ;
  233. mMpdGlobalTracks = mMPDEvent->GetGlobalTracks();
  234. int ntr = mMpdGlobalTracks->GetEntriesFast() ;
  235. MpdPhoton v ;
  236. for (long int i = 0; i < ntr-1; i++){
  237. MpdTrack *mpdtrack1 = (MpdTrack*) mMpdGlobalTracks->UncheckedAt(i);
  238. MpdTpcKalmanTrack *tr1 = (MpdTpcKalmanTrack*) mKalmanTracks->UncheckedAt(i);
  239. if(!selectTrack(mpdtrack1)){
  240. continue ;
  241. }
  242. for (long int j = i+1; j < ntr; j++){
  243. MpdTrack *mpdtrack2 = (MpdTrack*) mMpdGlobalTracks->UncheckedAt(j);
  244. MpdTpcKalmanTrack *tr2 = (MpdTpcKalmanTrack*) mKalmanTracks->UncheckedAt(j);
  245. if(!selectTrack(mpdtrack2)){
  246. continue ;
  247. }
  248. if(createSelectV0(mpdtrack1,tr1, mpdtrack2,tr2, v)){
  249. mV0.emplace_back(v.X(),v.Y(),v.Z(),v.T());
  250. mV0.back().setPrimary(v.primary()) ;
  251. mV0.back().setTr1(i) ;
  252. mV0.back().setTr2(j) ;
  253. }
  254. }
  255. }
  256. }
  257. //--------------------------------------
  258. void MpdConvPi0::selectClusters(){
  259. //Select EMC clusters in event
  260. const Float_t par0[2] = {-7.02851e-005, -7.76476e-002};
  261. const Float_t par1[2] = {-4.45930e-005, -1.01164e-002};
  262. mClusters.clear() ;
  263. int n = mEMCClusters->GetEntriesFast() ;
  264. for (int i = n; i--; ){
  265. MpdEmcClusterKI * clu = (MpdEmcClusterKI*) mEMCClusters->At(i);
  266. float e = Nonlinearity(clu->GetE()) ;
  267. mhCluCutEff->Fill(0.,e) ;
  268. if(e < mParams.mCluEmin){
  269. continue ;
  270. }
  271. if(clu->GetMultiplicity()<mParams.mCluMult){
  272. continue ;
  273. }
  274. mhCluCutEff->Fill(1.,e) ;
  275. double dx = clu->GetX() - mPrimaryVertex.X() ;
  276. double dy = clu->GetY() - mPrimaryVertex.Y() ;
  277. double dz = clu->GetZ() - mPrimaryVertex.Z() ;
  278. double r = TMath::Sqrt(dx*dx + dy*dy + dz*dz);
  279. double time = clu->GetTime() - r/29979245800.*1.e+9; //Time in ns
  280. if(fabs(tofCut(time,e))>mParams.mCluTof){
  281. continue ;
  282. }
  283. mhCluCutEff->Fill(2.,e) ;
  284. float l1,l2 ; //Dispersion axis
  285. clu->GetLambdas(l1,l2) ;
  286. //correct for z
  287. float izMax = TMath::Abs(32.*clu->GetZ()) ;
  288. l1=l1*1.6/(1.6+0.0002*izMax*izMax) ;
  289. l2=l2*3.2/(3.2+0.000023*izMax*izMax*izMax) ;
  290. // if(e>mParams.mCluDispEmin && lambdaCut(l1,l2,e) > mParams.mCluDisp){
  291. // continue ;
  292. // }
  293. mhCluCutEff->Fill(3.,e) ;
  294. float pp0 = par0[0] + par0[1]*mPrimaryVertex.Z();
  295. float pp1 = par1[0] + par1[1]*mPrimaryVertex.Z();
  296. float z_shift1 = pp0 + pp1*log(e);
  297. if(distCPV(clu->GetDPhi(),clu->GetDZ()+z_shift1,e) < mParams.mCluCPV){
  298. continue ;
  299. }
  300. mhCluCutEff->Fill(4.,e) ;
  301. mClusters.emplace_back(dx/r*e,dy/r*e,dz/r*e,e) ;
  302. mClusters.back().setTr1(i) ;
  303. if(clu->GetNumberOfTracks()>0){
  304. int trackId;
  305. float edep;
  306. clu->GetMCTrack(0, trackId, edep) ;
  307. mClusters.back().setPrimary(trackId) ;
  308. }
  309. }
  310. }
  311. void MpdConvPi0::processHistograms(){
  312. //Fill Real, Mixed distributions and update mixed array
  313. //Real
  314. int nClu = mClusters.size() ;
  315. int nV0 = mV0.size() ;
  316. for(int i=0; i<nClu-1; i++){
  317. for(int j=i+1; j<nClu; j++){
  318. TLorentzVector sum = mClusters[i] + mClusters[j] ;
  319. mhRealCalo[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  320. long int ip = IsSameParent(mClusters[i].primary(),mClusters[j].primary());
  321. if(ip>=0){
  322. mhRealCaloTrueAll[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  323. if(static_cast<MpdMCTrack*>(mMCTracks->At(ip))->GetPdgCode()==111){
  324. mhRealCaloTrue[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  325. }
  326. if(TMath::Abs(static_cast<MpdMCTrack*>(mMCTracks->At(ip))->GetPdgCode())==11 ||
  327. static_cast<MpdMCTrack*>(mMCTracks->At(ip))->GetPdgCode()==22 ){
  328. mhRealCaloTrueEl[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  329. }
  330. }
  331. }
  332. }
  333. for(int i=0; i<nClu; i++){
  334. for(int j=0; j<nV0; j++){
  335. if(TestHybrid(mClusters[i],mV0[j])) {
  336. TLorentzVector sum = mClusters[i] + mV0[j] ;
  337. mhRealHybrid[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  338. long int ip = IsSameParent(mClusters[i].primary(),mV0[j].primary());
  339. if(ip>=0){
  340. mhRealHybridTrueAll[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  341. if(static_cast<MpdMCTrack*>(mMCTracks->At(ip))->GetPdgCode()==111){
  342. mhRealHybridTrue[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  343. }
  344. if(TMath::Abs(static_cast<MpdMCTrack*>(mMCTracks->At(ip))->GetPdgCode())==11 ||
  345. static_cast<MpdMCTrack*>(mMCTracks->At(ip))->GetPdgCode()==22 ){
  346. mhRealHybridTrueEl[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  347. }
  348. }
  349. }
  350. }
  351. }
  352. for(int i=0; i<nV0-1; i++){
  353. for(int j=i+1; j<nV0; j++){
  354. TLorentzVector sum = mV0[i] + mV0[j] ;
  355. mhRealConv[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  356. long int ip = IsSameParent(mV0[i].primary(),mV0[j].primary());
  357. if(ip>=0){
  358. mhRealConvTrueAll[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  359. if(static_cast<MpdMCTrack*>(mMCTracks->At(ip))->GetPdgCode()==111){
  360. mhRealConvTrue[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  361. }
  362. if(TMath::Abs(static_cast<MpdMCTrack*>(mMCTracks->At(ip))->GetPdgCode())==11 ||
  363. static_cast<MpdMCTrack*>(mMCTracks->At(ip))->GetPdgCode()==22 ){
  364. mhRealConvTrueEl[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  365. }
  366. }
  367. }
  368. }
  369. //Mixed
  370. //calculate bin from zVertex-centrality-reaction plane
  371. int mixBin = mZvtxBin*nMixEventCent*nMixEventRP + mCenBin*nMixEventRP + mRPBin ;
  372. for(auto &vm : mMixClu[mixBin]){
  373. for(auto &v : mClusters){
  374. TLorentzVector sum = v + vm ;
  375. mhMixedCalo[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  376. }
  377. }
  378. for(auto &vm : mMixV0[mixBin]){
  379. for(auto &v : mClusters){
  380. TLorentzVector sum = v + vm ;
  381. mhMixedHybrid[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  382. }
  383. }
  384. for(auto &vm : mMixClu[mixBin]){
  385. for(auto &v : mV0){
  386. TLorentzVector sum = v + vm ;
  387. mhMixedHybrid[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  388. }
  389. }
  390. for(auto &vm : mMixV0[mixBin]){
  391. for(auto &v : mV0){
  392. TLorentzVector sum = v + vm ;
  393. mhMixedConv[mCenBin]->Fill(sum.M(), sum.Pt()) ;
  394. }
  395. }
  396. //Append new particles to queue and remove those at the beginning
  397. for(auto &v : mV0){
  398. mMixV0[mixBin].emplace_back(v) ;
  399. }
  400. while(mMixV0[mixBin].size()>(UInt_t)mMaxMixSize){
  401. mMixV0[mixBin].pop_front();
  402. }
  403. for(auto &v : mClusters){
  404. mMixClu[mCenBin].emplace_back(v) ;
  405. }
  406. while(mMixClu[mixBin].size()>(UInt_t)mMaxMixSize){
  407. mMixClu[mixBin].pop_front();
  408. }
  409. }
  410. bool MpdConvPi0::selectTrack(MpdTrack *mpdtrack){
  411. mhNhits->Fill(mpdtrack->GetNofHits()) ;
  412. float pt = TMath::Abs(mpdtrack->GetPt()) ;
  413. mhCutEff->Fill(0.,pt) ;
  414. if (mpdtrack->GetNofHits() < mParams.mNofHitsCut ) return false ; //nhits > 10
  415. mhCutEff->Fill(1.,pt) ;
  416. mhTracks->Fill(pt,mpdtrack->GetEta()) ;
  417. if (fabs(mpdtrack->GetEta()) > mParams.mEtaCut ) return false ; //|eta| < 1.0
  418. if (pt < mParams.mPtminCut) return false ; //pT > 50 MeV/c
  419. mhCutEff->Fill(2.,pt) ;
  420. int charge;
  421. if (mpdtrack->GetPt() < 0) charge = 1;
  422. else charge = -1;
  423. bool isGoodPID ;
  424. if (mpdtrack->GetTofFlag() == 2 || mpdtrack->GetTofFlag() == 6){
  425. isGoodPID = mPID -> FillProbs(pt*TMath::CosH(mpdtrack->GetEta()),mpdtrack->GetdEdXTPC(), mpdtrack->GetTofMass2(), charge);
  426. }
  427. else{
  428. isGoodPID = mPID -> FillProbs(pt*TMath::CosH(mpdtrack->GetEta()), mpdtrack->GetdEdXTPC(), charge);
  429. }
  430. mhProbEl->Fill(mPID->GetProbEl(),fabs(mpdtrack->GetPt()));
  431. bool isElectron = false ;
  432. if(isMC){ //same for true electron tracks
  433. long int prim1 = mpdtrack->GetID() ;
  434. if(prim1>=0){
  435. isElectron = abs((static_cast<MpdMCTrack*>(mMCTracks->At(prim1)))->GetPdgCode()) == 11 ;
  436. }
  437. }
  438. if(isElectron){
  439. mhProbElTrue->Fill(mPID -> GetProbEl(),pt);
  440. }
  441. if ( isGoodPID && mPID -> GetProbEl() < mParams.mProbElCut ){
  442. return false;
  443. }
  444. mhCutEff->Fill(3.,pt) ;
  445. float dEdx=dEdx_sigma(mpdtrack->GetdEdXTPC(), sqrt(pow(pt,2) + pow(mpdtrack->GetPz(),2))) ;
  446. mhdEdx->Fill(dEdx,pt) ;
  447. if(isElectron){ //same for true electrontracks
  448. mhdEdxTrue->Fill(dEdx,pt);
  449. }
  450. if ( (fabs(dEdx) < mParams.mdEdxSigmaCut ) &&
  451. (fabs(Beta_sigma(mpdtrack->GetTofBeta(), sqrt(pow(pt,2) + pow(mpdtrack->GetPz(),2)))) < mParams.mBetaSigmaCut &&
  452. (mpdtrack->GetTofFlag() == 2 || mpdtrack->GetTofFlag() == 6)) ){
  453. mhCutEff->Fill(4.,pt) ;
  454. return true ;
  455. }
  456. else{
  457. return false ;
  458. }
  459. return false ;
  460. }
  461. bool MpdConvPi0::createSelectV0(MpdTrack *tr1, MpdTpcKalmanTrack *ktr1, MpdTrack *tr2, MpdTpcKalmanTrack *ktr2, MpdPhoton &v ){
  462. //Construct and check V0
  463. //Use opposite charge tracks
  464. int charge1, charge2;
  465. if (tr1->GetPt() < 0) charge1 = 1;
  466. else charge1 = -1 ;
  467. if (tr2->GetPt() < 0) charge2 = 1;
  468. else charge2 = -1 ;
  469. //reject same sign pairs
  470. if(charge1 * charge2 >0) return false ;
  471. //Will be used for extrapolation
  472. MpdTpcKalmanTrack trCorK1(*ktr1);
  473. MpdHelix helix1 = MakeHelix(trCorK1);
  474. MpdParticle el1(trCorK1, 0);
  475. if ( charge1 > 0 ) el1.SetPdg(-11);
  476. if ( charge1 < 0 ) el1.SetPdg(11);
  477. el1.SetMass();
  478. MpdTpcKalmanTrack trCorK2(*ktr2);
  479. MpdHelix helix2 = MakeHelix(trCorK2);
  480. MpdParticle el2(trCorK2, 0);
  481. if ( charge2 > 0 ) el2.SetPdg(-11);
  482. if ( charge2 < 0 ) el2.SetPdg(11);
  483. el2.SetMass();
  484. //pair
  485. mPartK.clear();
  486. mPartK.emplace_back(&el1);
  487. mPartK.emplace_back(&el2);
  488. MpdParticle gamEE;
  489. float chi2 = TMath::Abs(gamEE.BuildMother(mPartK));
  490. float pt = gamEE.Pt() ;
  491. mhChi2->Fill(chi2,pt) ;
  492. mhCutEff->Fill(10.,pt) ;
  493. if(pt<0.005){ //to avoid fpe
  494. return false;
  495. }
  496. mhCutEff->Fill(11.,pt) ;
  497. bool isTrue = false ; //is true conv pair?
  498. long int commonParentId = -1;
  499. if(isMC){ //same for true electrontracks
  500. long int prim1 = tr1->GetID() ;
  501. long int prim2 = tr2->GetID() ;
  502. commonParentId = IsSameParent(prim1,prim2) ;
  503. if(commonParentId>=0){ //there is common parent
  504. isTrue = (static_cast<MpdMCTrack*>(mMCTracks->At(commonParentId))->GetPdgCode() ==22 ) ;
  505. }
  506. }
  507. if(isTrue){
  508. mhChi2True->Fill(chi2,pt) ;
  509. }
  510. if(chi2>mParams.mChi2Cut){
  511. return false ;
  512. }
  513. mhCutEff->Fill(12.,pt) ;
  514. TVector3 v0(gamEE.Getx()(0,0), gamEE.Getx()(1,0), gamEE.Getx()(2,0));
  515. v0 -= mPrimaryVertex;
  516. //float decay = v0.Mag();
  517. mhConvMap->Fill(gamEE.Getx()(0,0), gamEE.Getx()(1,0), gamEE.Getx()(2,0));
  518. if(isTrue){
  519. mhConvMapTrue->Fill(gamEE.Getx()(0,0), gamEE.Getx()(1,0), gamEE.Getx()(2,0));
  520. }
  521. float rConv = TMath::Sqrt(pow(gamEE.Getx()(0,0),2) + pow(gamEE.Getx()(1,0),2)) ;
  522. if( rConv < mParams.mMinR2Cut || rConv > mParams.mMaxR2Cut ){
  523. return false ;
  524. }
  525. mhCutEff->Fill(13.,pt) ;
  526. float angle; // disth,
  527. angle = v0.Angle(gamEE.Momentum3());
  528. mhAlpha->Fill(angle,pt) ;
  529. if(isTrue){ //same for true electrontracks
  530. mhAlphaTrue->Fill(angle,pt) ;
  531. }
  532. if( angle > mParams.mAlphaCut ){
  533. return false ;
  534. }
  535. mhCutEff->Fill(14.,pt) ;
  536. // if( ePos->R() <= ((TMath::Abs(ePos->Vz()) * fLineCutZRSlope) - fLineCutZValue)){
  537. // return kFALSE; // line cut to exclude regions where we do not reconstruct
  538. // } else if ( fEtaCutMin != -0.1 && ePos->R() >= ((TMath::Abs(ePos->Vz()) * fLineCutZRSlopeMin) - fLineCutZValueMin)){
  539. // return kFALSE;
  540. // }
  541. std::pair<float,float> paths = helix1.pathLengths(helix2);
  542. TVector3 p1 = helix1.at(paths.first);
  543. TVector3 p2 = helix2.at(paths.second);
  544. p1 -= p2;
  545. float dist = p1.Mag(); // Closest distance between daughters
  546. mhDist->Fill(dist,pt) ;
  547. if(isTrue){ //same for true electrontracks
  548. mhDistTrue->Fill(dist,pt) ;
  549. }
  550. if(dist>mParams.mDistCut){
  551. return false ;
  552. }
  553. mhCutEff->Fill(15.,pt) ;
  554. hmMassEE->Fill(gamEE.GetMass(),pt) ;
  555. if(isTrue){ //same for true electrontracks
  556. hmMassEETrue->Fill(gamEE.GetMass(),pt) ;
  557. }
  558. if(gamEE.GetMass()>mParams.mMassCut){
  559. return false ;
  560. }
  561. mhCutEff->Fill(16.,pt) ;
  562. // Pair_chi_1[n_ks] = el1.Chi2Vertex(vertex);
  563. // Pair_chi_2[n_ks] = el2.Chi2Vertex(vertex);
  564. //A-P cut
  565. // Gamma selection based on QT from Armenteros
  566. //propagate trCorK1,trCorK2 to conversion point
  567. MpdKalmanHit hitTmp;
  568. hitTmp.SetType(MpdKalmanHit::kFixedR);
  569. hitTmp.SetPos(trCorK1.GetPos());
  570. trCorK1.SetParamNew(*trCorK1.GetParam());
  571. trCorK1.SetPos(trCorK1.GetPosNew());
  572. trCorK1.ReSetWeight();
  573. // TMatrixDSym w = *trCorK1.GetWeight(); // save current weight matrix
  574. mKHit.SetPos(rConv) ;
  575. if (!mKF->PropagateToHit(&trCorK1, &mKHit, kFALSE, kFALSE)) {
  576. return false;
  577. }
  578. trCorK1.SetDirection(MpdKalmanTrack::kInward);
  579. TVector3 m1 = trCorK1.Momentum3();
  580. hitTmp.SetPos(trCorK2.GetPos());
  581. trCorK2.SetParamNew(*trCorK2.GetParam());
  582. trCorK2.SetPos(trCorK2.GetPosNew());
  583. trCorK2.ReSetWeight();
  584. TMatrixDSym w = *trCorK1.GetWeight(); // save current weight matrix
  585. mKHit.SetPos(rConv) ;
  586. if (!mKF->PropagateToHit(&trCorK2, &mKHit, kFALSE, kFALSE)) {
  587. return false;
  588. }
  589. trCorK2.SetDirection(MpdKalmanTrack::kInward);
  590. TVector3 m2 = trCorK2.Momentum3();
  591. float qt,alpha ;
  592. ArmenterosPodolanski(m1, m2, qt, alpha ) ;
  593. mhArmPo->Fill(alpha,qt) ;
  594. if(isTrue){
  595. mhArmPoTrue->Fill(alpha,qt) ;
  596. }
  597. if(!ArmenterosQtCut(qt, alpha, gamEE)){
  598. // return false;
  599. }
  600. mhCutEff->Fill(17.,pt) ;
  601. //Asymmetry cut
  602. float asym1 = m1.Mag()/gamEE.Momentum() ;
  603. float asym2 = m2.Mag()/gamEE.Momentum() ;
  604. mhAsym->Fill(asym1,pt) ;
  605. mhAsym->Fill(asym2,pt) ;
  606. if(isTrue){
  607. mhAsymTrue->Fill(asym1,pt) ;
  608. mhAsymTrue->Fill(asym2,pt) ;
  609. }
  610. if(!(AsymmetryCut(asym1,pt) && AsymmetryCut(asym2,pt))){
  611. return kFALSE;
  612. }
  613. mhCutEff->Fill(18.,pt) ;
  614. float cospsi = CosPsiPair(m1,m2) ;
  615. mhCosPsi->Fill(cospsi,pt) ;
  616. if(isTrue){ //same for true electrontracks
  617. mhCosPsiTrue->Fill(cospsi,pt) ;
  618. }
  619. if(cospsi<mParams.mCosPsiCut) {
  620. return kFALSE;
  621. }
  622. mhCutEff->Fill(19.,pt) ;
  623. // if(TMath::Abs(photonAOD->GetDCAzToPrimVtx()) > fDCAZPrimVtxCut) { //DCA Z cut of photon to primary vertex
  624. // return kFALSE;
  625. // }
  626. mhCutEff->Fill(20.,pt) ;
  627. // if(fHistoInvMassafter)fHistoInvMassafter->Fill(photon->GetMass());
  628. // if(fHistoArmenterosafter)fHistoArmenterosafter->Fill(photon->GetArmenterosAlpha(),photon->GetArmenterosQt());
  629. // if(fHistoPsiPairDeltaPhiafter)fHistoPsiPairDeltaPhiafter->Fill(deltaPhi,photon->GetPsiPair());
  630. // if(fHistoKappaafter)fHistoKappaafter->Fill(photon->GetPhotonPt(), GetKappaTPC(photon, event));
  631. // if(fHistoAsymmetryafter){
  632. // if(photon->GetPhotonP()!=0 && electronCandidate->P()!=0)fHistoAsymmetryafter->Fill(photon->GetPhotonP(),electronCandidate->P()/photon->GetPhotonP());
  633. // }
  634. mStorage.emplace_back(isTrue, pt,chi2, gamEE.GetMass(),rConv,angle,dist, qt, alpha,asym1,cospsi);
  635. v.SetXYZT((gamEE.Pt())*TMath::Cos(gamEE.Phi()),(gamEE.Pt())*TMath::Sin(gamEE.Phi()),
  636. TMath::Sign(TMath::Sqrt(gamEE.Momentum()*gamEE.Momentum() - gamEE.Pt()*gamEE.Pt()),TMath::Cos(gamEE.Theta())), gamEE.Momentum()) ;
  637. v.setPrimary(commonParentId) ;
  638. mhConvSp->Fill(v.Pt(),v.Eta()) ;
  639. if(isTrue){
  640. mhConvSpTrue->Fill(v.Pt(),v.Eta()) ;
  641. }
  642. return true ;
  643. }
  644. ///________________________________________________________________________
  645. bool MpdConvPi0::TestHybrid(MpdPhoton &c, MpdPhoton &v0) const {
  646. double dphi=999.,dz=999.;
  647. //Test if cluster match with any track from V0
  648. MpdEmcClusterKI * clu = (MpdEmcClusterKI*) mEMCClusters->At(c.getTr1());
  649. double xEMC = clu->GetX() ;
  650. double yEMC = clu->GetY() ;
  651. double zEMC = clu->GetZ() ;
  652. //int itr1 = v0.getTr1() ;
  653. //int itr2 = v0.getTr2() ;
  654. MpdTpcKalmanTrack *tr1 = (MpdTpcKalmanTrack*) mKalmanTracks->UncheckedAt(v0.getTr1());
  655. MpdTpcKalmanTrack tr1tmp(*tr1);
  656. tr1tmp.SetParam(*tr1tmp.GetParamAtHit());
  657. tr1tmp.SetParamNew(*tr1tmp.GetParamAtHit());
  658. tr1tmp.SetWeight(*tr1tmp.GetWeightAtHit());
  659. tr1tmp.SetPos(tr1tmp.GetPosAtHit());
  660. tr1tmp.SetPosNew(tr1tmp.GetPos());
  661. tr1tmp.SetLength(tr1tmp.GetLengAtHit());
  662. // Propagate to EMC cluser radius
  663. dphi=999.;
  664. dz=999.;
  665. MpdKalmanHit hEnd;
  666. hEnd.SetType(MpdKalmanHit::kFixedR);
  667. double rClu = MpdEmcGeoUtils::GetInstance()->Rperp(zEMC) ;
  668. hEnd.SetPos(rClu);
  669. MpdKalmanFilter* pKF = MpdKalmanFilter::Instance("KF", "KF");
  670. if (pKF->PropagateToHit(&tr1tmp, &hEnd, kTRUE)) {
  671. double phi = tr1tmp.GetParamNew(0) / tr1tmp.GetPosNew();
  672. double z = tr1tmp.GetParamNew(1);
  673. double r = tr1tmp.GetPosNew();
  674. double x = r * TMath::Cos(phi);
  675. double y = r * TMath::Sin(phi);
  676. dphi= TMath::Sqrt((x-xEMC)*(x-xEMC)+(y-yEMC)*(y-yEMC)) ;
  677. dz = TMath::Abs(z-zEMC) ;
  678. }
  679. MpdTpcKalmanTrack *tr2 = (MpdTpcKalmanTrack*) mKalmanTracks->UncheckedAt(v0.getTr2());
  680. MpdTpcKalmanTrack tr2tmp(*tr2);
  681. tr2tmp.SetParam(*tr2tmp.GetParamAtHit());
  682. tr2tmp.SetParamNew(*tr2tmp.GetParamAtHit());
  683. tr2tmp.SetWeight(*tr2tmp.GetWeightAtHit());
  684. tr2tmp.SetPos(tr2tmp.GetPosAtHit());
  685. tr2tmp.SetPosNew(tr2tmp.GetPos());
  686. tr2tmp.SetLength(tr2tmp.GetLengAtHit());
  687. if (pKF->PropagateToHit(&tr2tmp, &hEnd, kTRUE)) {
  688. double phi = tr2tmp.GetParamNew(0) / tr2tmp.GetPosNew();
  689. double z = tr2tmp.GetParamNew(1);
  690. double r = tr2tmp.GetPosNew();
  691. double x = r * TMath::Cos(phi);
  692. double y = r * TMath::Sin(phi);
  693. double ddphi= TMath::Sqrt((x-xEMC)*(x-xEMC)+(y-yEMC)*(y-yEMC)) ;
  694. double ddz = TMath::Abs(z-zEMC);
  695. if(ddphi*ddphi+ddz*ddz <dphi*dphi+dz*dz){
  696. dphi=ddphi;
  697. dz=ddz ;
  698. }
  699. }
  700. return (dphi*dphi/(25.*25.) + dz*dz/(9.*9.) ) > 1. ;
  701. }
  702. long int MpdConvPi0::IsSameParent(long int prim1, long int prim2)const{
  703. //Looks through parents and finds if there was commont pi0 among ancestors
  704. if(!isMC)
  705. return -1 ; //can not say anything
  706. while(prim1!=-1){
  707. long int pr2 = prim2;
  708. while(pr2!=-1){
  709. if(prim1==pr2){
  710. return prim1 ;
  711. }
  712. pr2= (static_cast<MpdMCTrack*>(mMCTracks->At(pr2)))->GetMotherId() ;
  713. }
  714. prim1=(static_cast<MpdMCTrack*>(mMCTracks->At(prim1)))->GetMotherId() ;
  715. }
  716. return -1 ;
  717. }
  718. MpdHelix MpdConvPi0::MakeHelix(const MpdKalmanTrack &tr) const
  719. {
  720. float r = tr.GetPosNew();
  721. float phi = tr.GetParam(0) / r;
  722. float x = r * TMath::Cos(phi);
  723. float y = r * TMath::Sin(phi);
  724. float dip = tr.GetParam(3);
  725. float cur = 0.3 * 0.01 * 5 / 10; // 5 kG
  726. cur *= TMath::Abs (tr.GetParam(4));
  727. TVector3 o(x, y, tr.GetParam(1));
  728. Int_t h = (Int_t) TMath::Sign(1.1,tr.GetParam(4));
  729. MpdHelix helix(cur, dip, tr.GetParam(2)-TMath::PiOver2()*h, o, h);
  730. return helix;
  731. }
  732. float MpdConvPi0::dEdx_sigma(float dEdx, float mom) const
  733. {
  734. //To be moved to centralized class
  735. if (mom < 0.05) mom = 0.05;
  736. float mean[7] = { 9.793192e+002, -5.234570e-003, -3.178321e+000, -4.987832e-002, 3.617478e-002, -1.021387e-001, 9.169614e+002 };
  737. float width[5] = { -1.589388e+003, 1.834372e+003, 4.125626e-003, 9.376418e-001, -1.466546e-001 };
  738. float mean_exp, width_exp;
  739. mean_exp = mean[0]/mom/mom * (mean[1]*log(mom*mom) - mean[2]*mom*mom - mean[3]*mom - mean[4] - mean[5]*mom*mom*mom) + mean[6];
  740. width_exp = width[0] + width[1]*pow(mom,width[2]) + width[3]/pow(mom-width[4],3);
  741. return (dEdx - mean_exp)/width_exp;
  742. }
  743. float MpdConvPi0::Beta_sigma(float beta, float mom) const
  744. {
  745. //To be moved to centralized class
  746. if (mom < 0.05) mom = 0.05;
  747. float mean[7] = { 3.150000e+003, -4.833115e-008, 1.688117e+000, -7.840445e-007, 3.034956e-007, -3.852622e-007, 5.318573e+003 };
  748. float width[5] = { 5.854497e-003, 6.078866e-003, -1.174312e-001, 3.039271e-006, -8.370411e-002 };
  749. float mean_exp, width_exp;
  750. mean_exp = mean[0]/mom/mom * (mean[1]*log(mom*mom) - mean[2]*mom*mom - mean[3]*mom - mean[4] - mean[5]*mom*mom*mom) + mean[6]-0.001;
  751. width_exp = width[0] + width[1]*pow(mom,width[2]) + width[3]/pow(mom-width[4],4);
  752. return (beta - mean_exp)/width_exp;
  753. }
  754. void MpdConvPi0::ArmenterosPodolanski(TVector3& m1, TVector3& m2, float &qt, float &alpha ) const
  755. {
  756. alpha = 0., qt = 0.;
  757. TVector3 s=m1+m2;
  758. float pn = m1.Mag() ;
  759. float pln = m1.Dot(s) ;
  760. float plp = m2.Dot(s) ;
  761. if( pn == 0.0) return;
  762. alpha = (plp-pln)/(plp+pln);
  763. float sm = s.Mag() ;
  764. if(sm>0){
  765. qt = m1.Cross(s).Mag()/sm;
  766. }
  767. }
  768. //________________________________________________________________________
  769. bool MpdConvPi0::ArmenterosQtCut(float qt, float alpha, MpdParticle & part) const { // Armenteros Qt Cut
  770. // if(mParams.mDo2DQt){
  771. // if(mParams.mDoQtGammaSelection==1){
  772. // if ( !(TMath::Power(photon->GetArmenterosAlpha()/mParams.mMaxPhotonAsymmetry,2)+TMath::Power(photon->GetArmenterosQt()/mParams.mQtMax,2) < 1) ){
  773. // return false;
  774. // }
  775. // } else if(mParams.mDoQtGammaSelection==2){
  776. // float qtMaxPtDep = mParams.mQtPtMax*photon->GetPhotonPt();
  777. // if (qtMaxPtDep > mParams.mQtMax)
  778. // qtMaxPtDep = mParams.mQtMax;
  779. // if ( !(TMath::Power(photon->GetArmenterosAlpha()/mParams.mMaxPhotonAsymmetry,2)+TMath::Power(photon->GetArmenterosQt()/qtMaxPtDep,2) < 1) ){
  780. // return false;
  781. // }
  782. // }
  783. // } else {
  784. // if(mParams.mDoQtGammaSelection==1){
  785. // if(photon->GetArmenterosQt()>mParams.mQtMax){
  786. // return false;
  787. // }
  788. // } else if(mParams.mDoQtGammaSelection==2){
  789. // Float_t qtMaxPtDep = mParams.mQtPtMax*photon->GetPhotonPt();
  790. // if (qtMaxPtDep > mParams.mQtMax)
  791. // qtMaxPtDep = mParams.mQtMax;
  792. // if(photon->GetArmenterosQt()>qtMaxPtDep){
  793. // return false;
  794. // }
  795. // }
  796. // }
  797. return true;
  798. }
  799. ///________________________________________________________________________
  800. bool MpdConvPi0::AsymmetryCut(float asym, float pt) const {
  801. // Cut on Energy Asymmetry
  802. // for(Int_t ii=0;ii<2;ii++){
  803. // AliVTrack *track=GetTrack(event,photon->GetTrackLabel(ii));
  804. // if(fDoPhotonPDependentAsymCut){
  805. // float trackNegAsy=0;
  806. // if (photon->GetPhotonP()!=0.){
  807. // trackNegAsy= track->P()/photon->GetPhotonP();
  808. // }
  809. // if( trackNegAsy > fFAsymmetryCut->Eval(photon->GetPhotonP()) || trackNegAsy < 1.-fFAsymmetryCut->Eval(photon->GetPhotonP()) ){
  810. // return kFALSE;
  811. // }
  812. // } else {
  813. // if( track->P() > fMinPPhotonAsymmetryCut ){
  814. // float trackNegAsy=0;
  815. // if (photon->GetPhotonP()!=0.){
  816. // trackNegAsy= track->P()/photon->GetPhotonP();
  817. // }
  818. // if( trackNegAsy<fMinPhotonAsymmetry ||trackNegAsy>(1.- fMinPhotonAsymmetry)){
  819. // return kFALSE;
  820. // }
  821. // }
  822. // }
  823. // }
  824. return true ;
  825. }
  826. ///________________________________________________________________________
  827. float MpdConvPi0::CosPsiPair(TVector3 &p1, TVector3 &p2) const {
  828. // float p1[3] = {tr1->GetPx(),tr1->GetPy(),tr1->GetPz()};
  829. // float p2[3] = {tr2->GetPx(),tr2->GetPy(),tr2->GetPz()};
  830. // float u[3] = {p1[0]+p2[0],p1[1]+p2[1],p1[2]+p2[2]};
  831. TVector3 u = p1 + p2 ;
  832. // float normp1 = sqrt( (p1[0]*p1[0]) + (p1[1]*p1[1]) + (p1[2]*p1[2]) );
  833. // float normp2 = sqrt( (p2[0]*p2[0]) + (p2[1]*p2[1]) + (p2[2]*p2[2]) );
  834. // float normu = sqrt( (u[0]*u[0]) + (u[1]*u[1]) + (u[2]*u[2]) );
  835. // for(int i=3; i--;){
  836. // p1[i] /= normp1;
  837. // p2[i] /= normp2;
  838. // u[i] /= normu;
  839. // }
  840. TVector3 v = p1.Cross(p2) ;
  841. TVector3 w = u.Cross(v) ;
  842. TVector3 z(0,0,1.) ;
  843. TVector3 wc = u.Cross(z) ;
  844. return wc.Angle(w) ;
  845. }
  846. float MpdConvPi0::distCPV(float dphi, float dz, float E) const {
  847. float sigmaPhi = 3.66601-4.63964e-01/E+2.08779e-01/E/E ;
  848. float sigmaZ = 2.58409-1.87502e-01/E+2.40143e-01/E/E ;
  849. dphi=dphi/sigmaPhi ;
  850. dz=dz/sigmaZ ;
  851. return sqrt(dphi*dphi + dz*dz) ;
  852. }
  853. float MpdConvPi0::lambdaCut(float l1,float l2,float E) const {
  854. float longM = 4.28333 ;
  855. float shortM= 1.88168-5.06456e-01*exp(-E/3.83640e-01) ;
  856. float longS = 1.05616-2.12212e-01*exp(-E/5.46530e-01) ;
  857. float shortS= 7.58640e-01-3.97720e-01*exp(-E/3.18150e-01) ;
  858. float c = -1.0+5.42460e-01*exp(-E/3.22982e-01) ;
  859. return (l1-longM)*(l1-longM)/(longS*longS*2.)
  860. +(l2-shortM)*(l2-shortM)/(shortS*shortS*2.)
  861. +c*(l1-longM)*(l2-shortM)/(longS*shortS*2.);
  862. }
  863. float MpdConvPi0::tofCut(float time,float E) const {
  864. //return distance of time from expected photon arraival in sigma (with sign)
  865. float sigma = 1.86166*TMath::Exp(-E/0.0259728)+0.347552 ; //resolution in ns
  866. return time/sigma ;
  867. }
  868. float MpdConvPi0::Nonlinearity(float oldE) const {
  869. float x = TMath::Min(oldE,2.5f) ;
  870. return 2.9411765*oldE/(0.97630219 + 7.194380e-002*x - 4.491255e-002*x*x +8.362250e-003*x*x*x);
  871. }