]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGLF/FORWARD/analysis2/AliFMDEventInspector.cxx
7b493afcffc4ccbb626a04d033daa2cabbb02046
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / AliFMDEventInspector.cxx
1 // 
2 // This class inspects the event 
3 //
4 // Input:
5 //   - AliESDFMD object possibly corrected for sharing
6 //
7 // Output:
8 //   - A histogram of v_z of events with triggers. 
9 //   - A histogram of v_z of events with vertex and triggers 
10 //   - A histogram of trigger counters 
11 // 
12 // Note, that these are added to the master output list 
13 //
14 // Corrections used: 
15 //   - None
16 //
17 #include "AliFMDEventInspector.h"
18 #include "AliLog.h"
19 #include "AliESDEvent.h"
20 #include "AliMultiplicity.h"
21 #include "AliAnalysisManager.h"
22 #include "AliMCEventHandler.h"
23 #include "AliInputEventHandler.h"
24 #include "AliTriggerAnalysis.h"
25 #include "AliPhysicsSelection.h"
26 #include "AliOADBPhysicsSelection.h"
27 #include "AliAODForwardMult.h"
28 #include "AliForwardUtil.h"
29 #include "AliCentrality.h"
30 #include <TH1.h>
31 #include <TList.h>
32 #include <TDirectory.h>
33 #include <TROOT.h>
34 #include <TParameter.h>
35 #include <iostream>
36 #include <iomanip>
37 #include "AliMCEvent.h"
38 #include "AliHeader.h"
39 #include "AliGenEventHeader.h"
40 #include "AliCollisionGeometry.h"
41
42 //====================================================================
43 AliFMDEventInspector::AliFMDEventInspector()
44   : TNamed(),
45     fHEventsTr(0), 
46     fHEventsTrVtx(0),
47     fHEventsAccepted(0),
48     fHEventsAcceptedXY(0),
49     fHTriggers(0),
50     fHType(0),
51     fHWords(0),
52     fHCent(0),
53     fHCentVsQual(0),
54     fLowFluxCut(1000),
55     fMaxVzErr(0.2),
56     fList(0),
57     fEnergy(0),
58     fField(999), 
59     fCollisionSystem(kUnknown),
60     fDebug(0),
61     fCentAxis(0),
62     fVtxAxis(10,-10,10),
63     fUseFirstPhysicsVertex(true),
64     fUseV0AND(false),
65     fMinPileupContrib(3), 
66     fMinPileupDistance(0.8),
67     fUseDisplacedVertices(false),
68     fDisplacedVertex()
69 {
70   // 
71   // Constructor 
72   //
73 }
74
75 //____________________________________________________________________
76 AliFMDEventInspector::AliFMDEventInspector(const char* name)
77   : TNamed("fmdEventInspector", name),
78     fHEventsTr(0), 
79     fHEventsTrVtx(0), 
80     fHEventsAccepted(0),
81     fHEventsAcceptedXY(0),
82     fHTriggers(0),
83     fHType(0),
84     fHWords(0),
85     fHCent(0),
86     fHCentVsQual(0),
87     fLowFluxCut(1000),
88     fMaxVzErr(0.2),
89     fList(0),
90     fEnergy(0),
91     fField(999), 
92     fCollisionSystem(kUnknown),
93     fDebug(0),
94     fCentAxis(0),
95     fVtxAxis(10,-10,10),
96     fUseFirstPhysicsVertex(true),
97     fUseV0AND(false),
98     fMinPileupContrib(3), 
99     fMinPileupDistance(0.8),
100     fUseDisplacedVertices(false),
101     fDisplacedVertex()
102 {
103   // 
104   // Constructor 
105   // 
106   // Parameters:
107   //   name Name of object
108   //
109 }
110
111 //____________________________________________________________________
112 AliFMDEventInspector::AliFMDEventInspector(const AliFMDEventInspector& o)
113   : TNamed(o), 
114     fHEventsTr(o.fHEventsTr), 
115     fHEventsTrVtx(o.fHEventsTrVtx), 
116     fHEventsAccepted(o.fHEventsAccepted),
117     fHEventsAcceptedXY(o.fHEventsAcceptedXY),
118     fHTriggers(o.fHTriggers),
119     fHType(o.fHType),
120     fHWords(o.fHWords),
121     fHCent(o.fHCent),
122     fHCentVsQual(o.fHCentVsQual),
123     fLowFluxCut(o.fLowFluxCut),
124     fMaxVzErr(o.fMaxVzErr),
125     fList(o.fList),
126     fEnergy(o.fEnergy),
127     fField(o.fField), 
128     fCollisionSystem(o.fCollisionSystem),
129     fDebug(0),
130     fCentAxis(0),
131     fVtxAxis(o.fVtxAxis),
132     fUseFirstPhysicsVertex(o.fUseFirstPhysicsVertex),
133     fUseV0AND(o.fUseV0AND),
134     fMinPileupContrib(o.fMinPileupContrib), 
135     fMinPileupDistance(o.fMinPileupDistance),
136     fUseDisplacedVertices(o.fUseDisplacedVertices),
137     fDisplacedVertex(o.fDisplacedVertex)
138 {
139   // 
140   // Copy constructor 
141   // 
142   // Parameters:
143   //   o Object to copy from 
144   //
145 }
146
147 //____________________________________________________________________
148 AliFMDEventInspector::~AliFMDEventInspector()
149 {
150   // 
151   // Destructor 
152   //
153   if (fList)         delete fList;
154 }
155 //____________________________________________________________________
156 AliFMDEventInspector&
157 AliFMDEventInspector::operator=(const AliFMDEventInspector& o)
158 {
159   // 
160   // Assignement operator
161   // 
162   // Parameters:
163   //   o Object to assign from 
164   // 
165   // Return:
166   //    Reference to this object
167   //
168   if (&o == this) return *this; 
169   TNamed::operator=(o);
170   fHEventsTr         = o.fHEventsTr;
171   fHEventsTrVtx      = o.fHEventsTrVtx;
172   fHEventsAccepted   = o.fHEventsAccepted;
173   fHEventsAcceptedXY = o.fHEventsAcceptedXY;
174   fHTriggers         = o.fHTriggers;
175   fHType             = o.fHType;
176   fHWords            = o.fHWords;
177   fHCent             = o.fHCent;
178   fHCentVsQual       = o.fHCentVsQual;
179   fLowFluxCut        = o.fLowFluxCut;
180   fMaxVzErr          = o.fMaxVzErr;
181   fDebug             = o.fDebug;
182   fList              = (o.fList ? new TList : 0);
183   fEnergy            = o.fEnergy;
184   fField             = o.fField;
185   fCollisionSystem   = o.fCollisionSystem;
186   fVtxAxis.Set(o.fVtxAxis.GetNbins(), o.fVtxAxis.GetXmin(), 
187                o.fVtxAxis.GetXmax());
188   
189   fUseFirstPhysicsVertex = o.fUseFirstPhysicsVertex;
190   fUseV0AND              = o.fUseV0AND;
191   fMinPileupContrib      = o.fMinPileupContrib;
192   fMinPileupDistance     = o.fMinPileupDistance;
193   fUseDisplacedVertices  = o.fUseDisplacedVertices;
194   fDisplacedVertex       = o.fDisplacedVertex;
195   if (fList) { 
196     fList->SetName(GetName());
197     if (fHEventsTr)    fList->Add(fHEventsTr);
198     if (fHEventsTrVtx) fList->Add(fHEventsTrVtx);
199     if (fHTriggers)    fList->Add(fHTriggers);
200     if (fHType)        fList->Add(fHType);
201     if (fHWords)       fList->Add(fHWords);
202     if (fHCent)        fList->Add(fHCent);
203     if (fHCentVsQual)  fList->Add(fHCentVsQual);
204   }
205   return *this;
206 }
207
208 //____________________________________________________________________
209 Bool_t
210 AliFMDEventInspector::FetchHistograms(const TList* d, 
211                                       TH1I*& hEventsTr, 
212                                       TH1I*& hEventsTrVtx, 
213                                       TH1I*& hTriggers) const
214 {
215   // 
216   // Fetch our histograms from the passed list 
217   // 
218   // Parameters:
219   //   d             Input
220   //   hEventsTr     On return, pointer to histogram, or null
221   //   hEventsTrVtx  On return, pointer to histogram, or null
222   //   hTriggers     On return, pointer to histogram, or null
223   // 
224   // Return:
225   //    true on success, false otherwise 
226   //
227   hEventsTr    = 0;
228   hEventsTrVtx = 0;
229   hTriggers    = 0;
230   TList* dd    = dynamic_cast<TList*>(d->FindObject(GetName()));
231   if (!dd) return kFALSE;
232   
233   hEventsTr    = dynamic_cast<TH1I*>(dd->FindObject("nEventsTr"));
234   hEventsTrVtx = dynamic_cast<TH1I*>(dd->FindObject("nEventsTrVtx"));
235   hTriggers    = dynamic_cast<TH1I*>(dd->FindObject("triggers"));
236
237   if (!hEventsTr || !hEventsTrVtx || !hTriggers) return kFALSE;
238   return kTRUE;
239 }
240 //____________________________________________________________________
241 void
242 AliFMDEventInspector::Init(const TAxis& vtxAxis)
243 {
244   // 
245   // Initialize the object 
246   // 
247   // Parameters:
248   //   vtxAxis Vertex axis in use 
249   //
250   
251   // -1.5 -0.5 0.5 1.5 ... 89.5 ... 100.5
252   // ----- 92 number --------- ---- 1 ---
253   TArrayD limits(93);
254   for (Int_t i = 0; i < 92; i++) limits[i] = -1.5 + i;
255   limits[92] = 100.5;
256
257   fVtxAxis.Set(vtxAxis.GetNbins(), vtxAxis.GetXmin(), vtxAxis.GetXmax());
258   
259   fCentAxis  = new TAxis(limits.GetSize()-1, limits.GetArray());
260   fHEventsTr = new TH1I("nEventsTr", "Number of events w/trigger", 
261                         4*vtxAxis.GetNbins(), 
262                         2*vtxAxis.GetXmin(), 
263                         2*vtxAxis.GetXmax());
264   fHEventsTr->SetXTitle("v_{z} [cm]");
265   fHEventsTr->SetYTitle("# of events");
266   fHEventsTr->SetFillColor(kRed+1);
267   fHEventsTr->SetFillStyle(3001);
268   fHEventsTr->SetDirectory(0);
269   // fHEventsTr->Sumw2();
270   fList->Add(fHEventsTr);
271
272   fHEventsTrVtx = static_cast<TH1I*>(fHEventsTr->Clone("nEventsTrVtx"));
273   fHEventsTrVtx->SetTitle("Number of events w/trigger and vertex"); 
274   fHEventsTrVtx->SetFillColor(kBlue+1);
275   fHEventsTrVtx->SetDirectory(0);
276   // fHEventsTrVtx->Sumw2();
277   fList->Add(fHEventsTrVtx);
278
279   fHEventsAccepted = new TH1I("nEventsAccepted", 
280                               "Number of events  w/trigger and vertex in range",
281                               2*vtxAxis.GetNbins(), 
282                               2*vtxAxis.GetXmin(), 
283                               2*vtxAxis.GetXmax());
284   fHEventsAccepted->SetXTitle("v_{z} [cm]");
285   fHEventsAccepted->SetYTitle("# of events");
286   fHEventsAccepted->SetFillColor(kGreen+1);
287   fHEventsAccepted->SetFillStyle(3001);
288   fHEventsAccepted->SetDirectory(0);
289   // fHEventsAccepted->Sumw2();
290   fList->Add(fHEventsAccepted);
291                               
292   fHEventsAcceptedXY = new TH2D("nEventsAcceptedXY", 
293                               "XY vertex w/trigger and Z vertex in range",
294                                 1000,-1,1,1000,-1,1);
295   
296   fHEventsAcceptedXY->SetXTitle("v_{x} [cm]");
297   fHEventsAcceptedXY->SetYTitle("v_{y} [cm]");
298   fHEventsAcceptedXY->SetDirectory(0);
299   // fHEventsAccepted->Sumw2();
300   fList->Add(fHEventsAcceptedXY);
301
302   
303   fHTriggers = new TH1I("triggers", "Triggers", kOffline+1, 0, kOffline+1);
304   fHTriggers->SetFillColor(kRed+1);
305   fHTriggers->SetFillStyle(3001);
306   fHTriggers->SetStats(0);
307   fHTriggers->SetDirectory(0);
308   fHTriggers->GetXaxis()->SetBinLabel(kInel   +1,"INEL");
309   fHTriggers->GetXaxis()->SetBinLabel(kInelGt0+1,"INEL>0");
310   fHTriggers->GetXaxis()->SetBinLabel(kNSD    +1,"NSD");
311   fHTriggers->GetXaxis()->SetBinLabel(kV0AND  +1,"VOAND");
312   fHTriggers->GetXaxis()->SetBinLabel(kEmpty  +1,"Empty");
313   fHTriggers->GetXaxis()->SetBinLabel(kA      +1,"A");
314   fHTriggers->GetXaxis()->SetBinLabel(kB      +1,"B");
315   fHTriggers->GetXaxis()->SetBinLabel(kC      +1,"C");
316   fHTriggers->GetXaxis()->SetBinLabel(kE      +1,"E");
317   fHTriggers->GetXaxis()->SetBinLabel(kPileUp +1,"Pileup");
318   fHTriggers->GetXaxis()->SetBinLabel(kMCNSD  +1,"NSD_{MC}");
319   fHTriggers->GetXaxis()->SetBinLabel(kOffline+1,"Offline");
320   fList->Add(fHTriggers);
321
322   fHType = new TH1I("type", Form("Event type (cut: SPD mult>%d)", 
323                                  fLowFluxCut), 2, -.5, 1.5);
324   fHType->SetFillColor(kRed+1);
325   fHType->SetFillStyle(3001);
326   fHType->SetStats(0);
327   fHType->SetDirectory(0);
328   fHType->GetXaxis()->SetBinLabel(1,"Low-flux");
329   fHType->GetXaxis()->SetBinLabel(2,"High-flux");
330   fList->Add(fHType);
331
332 #if 0 
333   // This histogram disabled as it causes problems in the merge 
334   fHWords = new TH1I("words", "Trigger words seen", 1, 0, 0); 
335   fHWords->SetFillColor(kBlue+1);
336   fHWords->SetFillStyle(3001);
337   fHWords->SetStats(0);
338   fHWords->SetDirectory(0);
339   fHWords->SetBit(TH1::kCanRebin);
340   fList->Add(fHWords);
341 #endif
342
343   fHCent = new TH1F("cent", "Centrality", limits.GetSize()-1,limits.GetArray());
344   fHCent->SetFillColor(kBlue+1);
345   fHCent->SetFillStyle(3001);
346   fHCent->SetStats(0);
347   fHCent->SetDirectory(0);
348   fHCent->SetXTitle("Centrality [%]");
349   fHCent->SetYTitle("Events");
350   fList->Add(fHCent);
351
352   fHCentVsQual = new TH2F("centVsQuality", "Quality vs Centrality", 
353                           5, 0, 5, limits.GetSize()-1, limits.GetArray());
354   fHCentVsQual->SetXTitle("Quality");
355   fHCentVsQual->SetYTitle("Centrality [%]");
356   fHCentVsQual->SetZTitle("Events");
357   fHCentVsQual->GetXaxis()->SetBinLabel(1, "OK");
358   fHCentVsQual->GetXaxis()->SetBinLabel(2, "Outside v_{z} cut");
359   fHCentVsQual->GetXaxis()->SetBinLabel(3, "V0 vs SPD outlier");
360   fHCentVsQual->GetXaxis()->SetBinLabel(4, "V0 vs TPC outlier");
361   fHCentVsQual->GetXaxis()->SetBinLabel(5, "V0 vs ZDC outlier");
362   fList->Add(fHCentVsQual);
363 }
364
365 //____________________________________________________________________
366 void
367 AliFMDEventInspector::StoreInformation(Int_t runNo)
368 {
369   // Write TNamed objects to output list containing information about
370   // the running conditions 
371   if (!fList) return;
372
373   TNamed* sys = new TNamed("sys", "");
374   TNamed* sNN = new TNamed("sNN", "");
375   TNamed* fld = new TNamed("field", "");
376   TNamed* run = new TNamed("runNo", Form("%d", runNo));
377   TNamed* low = new TNamed("lowFlux", Form("%d", fLowFluxCut));
378   TNamed* fpv = new TNamed("fpVtx", Form("%s", fUseFirstPhysicsVertex ? "true" : "false"));
379   TNamed* v0a = new TNamed("v0and", Form("%s", fUseV0AND ? "true" : "false"));
380   TNamed* nCp = new TNamed("nPileup", Form("%d", fMinPileupContrib));
381   sys->SetTitle(AliForwardUtil::CollisionSystemString(fCollisionSystem));
382   sNN->SetTitle(AliForwardUtil::CenterOfMassEnergyString(fEnergy));
383   fld->SetTitle(AliForwardUtil::MagneticFieldString(fField));
384   sys->SetUniqueID(fCollisionSystem);
385   sNN->SetUniqueID(fEnergy);
386   fld->SetUniqueID(fField);
387   run->SetUniqueID(runNo);
388   low->SetUniqueID(fLowFluxCut);
389   fpv->SetUniqueID(fUseFirstPhysicsVertex ? 1 : 0);
390   v0a->SetUniqueID(fUseV0AND ? 1  : 0);
391   nCp->SetUniqueID(fMinPileupContrib);
392
393   TParameter<Double_t>* dP = new TParameter<Double_t>("dPileup", fMinPileupDistance);
394   fList->Add(sys);
395   fList->Add(sNN);
396   fList->Add(fld);
397   fList->Add(run);                              
398   fList->Add(low);
399   fList->Add(fpv);
400   fList->Add(v0a);
401   fList->Add(nCp);
402   fList->Add(dP);
403   
404
405 }
406
407 //____________________________________________________________________
408 void
409 AliFMDEventInspector::DefineOutput(TList* dir)
410 {
411   // 
412   // Define the output histograms.  These are put in a sub list of the
413   // passed list.   The histograms are merged before the parent task calls 
414   // AliAnalysisTaskSE::Terminate 
415   // 
416   //   dir Directory to add to 
417   //
418   fList = new TList;
419   fList->SetName(GetName());
420   dir->Add(fList);
421 }
422
423 //____________________________________________________________________
424 UInt_t
425 AliFMDEventInspector::Process(const AliESDEvent* event, 
426                               UInt_t&            triggers,
427                               Bool_t&            lowFlux,
428                               UShort_t&          ivz, 
429                               Double_t&          vz,
430                               Double_t&          cent,
431                               UShort_t&          nClusters)
432 {
433   // 
434   // Process the event 
435   // 
436   // Parameters:
437   //   event     Input event 
438   //   triggers  On return, the triggers fired 
439   //   lowFlux   On return, true if the event is considered a low-flux 
440   //                  event (according to the setting of fLowFluxCut) 
441   //   ivz       On return, the found vertex bin (1-based).  A zero
442   //                  means outside of the defined vertex range
443   //   vz        On return, the z position of the interaction
444   //   cent      On return, the centrality - if not available < 0
445   // 
446   // Return:
447   //    0 (or kOk) on success, otherwise a bit mask of error codes 
448   //
449
450   // --- Check that we have an event ---------------------------------
451   if (!event) { 
452     AliWarning("No ESD event found for input event");
453     return kNoEvent;
454   }
455
456   // --- Read trigger information from the ESD and store in AOD object
457   if (!ReadTriggers(event, triggers, nClusters)) { 
458     if (fDebug > 2) {
459       AliWarning("Failed to read triggers from ESD"); }
460     return kNoTriggers;
461   }
462
463   // --- Check if this is a high-flux event --------------------------
464   const AliMultiplicity* testmult = event->GetMultiplicity();
465   if (!testmult) {
466     if (fDebug > 3) {
467       AliWarning("No central multiplicity object found"); }
468   }
469   else 
470     lowFlux = testmult->GetNumberOfTracklets() < fLowFluxCut;
471
472   fHType->Fill(lowFlux ? 0 : 1);
473   
474   // --- Read centrality information 
475   cent          = -10;
476   UShort_t qual = 0;
477   if (!ReadCentrality(event, cent, qual)) {
478     if (fDebug > 3) 
479       AliWarning("Failed to get centrality");
480   }
481   fHCent->Fill(cent);
482   if (qual == 0) fHCentVsQual->Fill(0., cent);
483   else { 
484     for (UShort_t i = 0; i < 4; i++) 
485       if (qual & (1 << i)) fHCentVsQual->Fill(Double_t(i+1), cent);
486   }
487
488   // --- Get the vertex information ----------------------------------
489   
490   Double_t vx = 0;
491   Double_t vy = 0;
492   vz          = 0;
493   
494   Bool_t vzOk = ReadVertex(event, vz,vx,vy);
495
496   fHEventsTr->Fill(vz);
497   if (!vzOk) { 
498     if (fDebug > 3) {
499       AliWarning("Failed to read vertex from ESD"); }
500     return kNoVertex;
501   }
502   fHEventsTrVtx->Fill(vz);
503   
504   // --- Get the vertex bin ------------------------------------------
505   ivz = fVtxAxis.FindBin(vz);
506   if (ivz <= 0 || ivz > fVtxAxis.GetNbins()) { 
507     if (fDebug > 3) {
508       AliWarning(Form("Vertex @ %f outside of range [%f,%f]", 
509                       vz, fVtxAxis.GetXmin(), fVtxAxis.GetXmax())); 
510     }
511     ivz = 0;
512     return kBadVertex;
513   }
514   fHEventsAccepted->Fill(vz);
515   fHEventsAcceptedXY->Fill(vx,vy);
516   
517   // --- Check the FMD ESD data --------------------------------------
518   if (!event->GetFMDData()) { 
519     if (fDebug > 3) {
520       AliWarning("No FMD data found in ESD"); }
521     return kNoFMD;
522   }
523
524   
525   return kOk;
526 }
527
528 //____________________________________________________________________
529 Bool_t
530 AliFMDEventInspector::ReadCentrality(const AliESDEvent* esd, 
531                                      Double_t& cent, 
532                                      UShort_t& qual) const
533 {
534   // 
535   // Read centrality from event 
536   // 
537   // Parameters:
538   //    esd  Event 
539   //    cent On return, the centrality or negative if not found
540   // 
541   // Return:
542   //    False on error, true otherwise 
543   //
544   cent = -1;
545   qual = 0;
546   AliCentrality* centObj = const_cast<AliESDEvent*>(esd)->GetCentrality();
547   if (!centObj)  return true;
548 AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
549   Bool_t isMC = am->GetMCtruthEventHandler() != 0;
550   
551   //std::cout<<fUseDisplacedVertices<<"  "<<isMC<<std::endl;
552   if(fUseDisplacedVertices && !isMC) {
553     Double_t zvtx = fDisplacedVertex.CheckDisplacedVertex(esd);
554     qual          = 1;
555     if(TMath::Abs(zvtx) < 999) {
556       cent = fDisplacedVertex.CalculateDisplacedVertexCent(esd); //centObj->GetCentralityPercentileUnchecked("ZEMvsZDC");  
557       qual = 0;
558     }
559   }
560   else if(fUseDisplacedVertices && isMC) {
561     
562     
563     AliMCEventHandler* mchandler = static_cast<AliMCEventHandler*>(am->GetMCtruthEventHandler());
564     AliMCEvent* mcevent          = mchandler->MCEvent();
565     
566     AliHeader*               header          = mcevent->Header();
567     AliGenEventHeader*       genHeader       = header->GenEventHeader();
568     AliCollisionGeometry*    colGeometry     = 
569       dynamic_cast<AliCollisionGeometry*>(genHeader);
570     Double_t b              = -1;
571     if (colGeometry)  
572       b     = colGeometry->ImpactParameter();
573     std::cout<<"Hallo!!  "<<b<<std::endl;
574     cent = -1;
575     if(b<3.5 && b >0) cent = 2.5; //0-5%
576     if(b>3.5 && b<4.95) cent = 7.5; //5-10%
577     if(b>4.95 && b<6.98) cent = 15; //10-20%
578     if(b>6.98 && b<8.55) cent = 25; //20-30%
579     if(b>8.55 && b<9.88) cent = 35; //30-40%
580     if(b>9.88 && b<11.04) cent = 45; //40-50%
581     if(b>11.04) cent = 55; //50-60%
582     //cent = 10;
583     qual = 0;
584   }
585   else {
586     cent = centObj->GetCentralityPercentile("V0M");  
587     qual = centObj->GetQuality();
588   }
589   
590   // AliInfo(Form("Got centrality object %p with quality %d", 
591   //              centObj, centObj->GetQuality()));
592   // centObj->Print();
593   //cent = centObj->GetCentralityPercentile("V0M");  
594   //cent = centObj->GetCentralityPercentile("ZEMvsZDC");  
595   //qual = centObj->GetQuality();
596
597   return true;
598 }
599
600 //____________________________________________________________________
601 Bool_t
602 AliFMDEventInspector::ReadTriggers(const AliESDEvent* esd, UInt_t& triggers,
603                                    UShort_t& nClusters)
604 {
605   // 
606   // Read the trigger information from the ESD event 
607   // 
608   // Parameters:
609   //   esd        ESD event 
610   //   triggers   On return, contains the trigger bits 
611   // 
612   // Return:
613   //    @c true on success, @c false otherwise 
614   //
615   triggers = 0;
616
617   // Get the analysis manager - should always be there 
618   AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
619   if (!am) { 
620     AliWarning("No analysis manager defined!");
621     return kFALSE;
622   }
623
624   // Get the input handler - should always be there 
625   AliInputEventHandler* ih = 
626     static_cast<AliInputEventHandler*>(am->GetInputEventHandler());
627   if (!ih) { 
628     AliWarning("No input handler");
629     return kFALSE;
630   }
631   AliPhysicsSelection* ps = 
632     static_cast<AliPhysicsSelection*>(ih->GetEventSelection());
633   if (!ps) {
634     AliWarning("No physics selection");
635     return kFALSE;
636   }
637   AliOADBPhysicsSelection* oadb = 
638     const_cast<AliOADBPhysicsSelection*>(ps->GetOADBPhysicsSelection());
639   if (!oadb) {
640     AliWarning("No OADB physics selection object");
641     return kFALSE;
642   }
643
644   // Check if this is a collision candidate (MB)
645   // Note, that we should use the value cached in the input 
646   // handler rather than calling IsCollisionCandiate directly 
647   // on the AliPhysicsSelection obejct.  If we called the latter
648   // then the AliPhysicsSelection object would overcount by a 
649   // factor of 2! :-(
650   Bool_t offline  = ih->IsEventSelected() ;
651   Bool_t fastonly = (ih->IsEventSelected() & AliVEvent::kFastOnly);
652   TString trigStr = esd->GetFiredTriggerClasses();
653   
654   //If we have the MC input handler,  this must be MC
655   Bool_t isMC = am->GetMCtruthEventHandler() != 0;
656   
657   if(fUseDisplacedVertices && isMC) {
658     AliMCEventHandler* mchandler = static_cast<AliMCEventHandler*>(am->GetMCtruthEventHandler());
659     AliMCEvent* mcevent          = mchandler->MCEvent();
660     AliHeader* header            = mcevent->Header();
661     AliGenEventHeader* genHeader = header->GenEventHeader();
662     TArrayF vertex;
663     genHeader->PrimaryVertex(vertex);
664     
665     Double_t zvtx = vertex.At(2);
666     if(TMath::Abs(zvtx) > 35)
667       offline = true;
668     else offline = false;
669   }
670   
671   if(fUseDisplacedVertices && !isMC) {
672     Double_t zvtx = fDisplacedVertex.CheckDisplacedVertex(esd);
673     if(TMath::Abs(zvtx) < 999) offline = true;
674     else offline = false;
675     
676   }
677   // For the 2.76 TeV p+p run, the FMD ran in the slow partition 
678   // so it received no triggers from the fast partition. Therefore
679   // the fast triggers are removed here but not for MC where all 
680   // triggers are fast.
681   if(TMath::Abs(fEnergy - 2750.) < 20 && 
682      fCollisionSystem == AliForwardUtil::kPP &&
683      !isMC)
684     if (fastonly) offline = false;
685   nClusters = 0;
686   
687   // MUON triggers are not strictly minimum bias (MB) so they are removed (HHD)
688   
689   if(offline && trigStr.Contains("CMUS1")) offline = false;
690     
691   if (offline) {
692     triggers |= AliAODForwardMult::kOffline;
693     triggers |= AliAODForwardMult::kInel;
694     fHTriggers->Fill(kOffline+0.5);
695
696     // If this is inel, see if we have a tracklet 
697     const AliMultiplicity* spdmult = esd->GetMultiplicity();
698     if (!spdmult) {
699       AliWarning("No SPD multiplicity");
700     }
701     else { 
702       // Check if we have one or more tracklets 
703       // in the range -1 < eta < 1 to set the INEL>0 
704       // trigger flag. 
705       // 
706       // Also count tracklets as a single cluster 
707       Int_t n = spdmult->GetNumberOfTracklets();
708       for (Int_t j = 0; j < n; j++) { 
709         if(TMath::Abs(spdmult->GetEta(j)) < 1) { 
710           triggers |= AliAODForwardMult::kInelGt0;
711           nClusters++;
712         }
713       }
714       n = spdmult->GetNumberOfSingleClusters();
715       for (Int_t j = 0; j < n; j++) { 
716         Double_t eta = -TMath::Log(TMath::Tan(spdmult->GetThetaSingle(j)/2.));
717         if (TMath::Abs(eta) < 1) nClusters++;
718       }
719     }
720     if (nClusters > 0) triggers |= AliAODForwardMult::kNClusterGt0;
721   }
722   
723   // Analyse some trigger stuff 
724   AliTriggerAnalysis ta;
725   if (ta.IsOfflineTriggerFired(esd, AliTriggerAnalysis::kV0AND)) {
726     triggers |= AliAODForwardMult::kV0AND;
727     if (fUseV0AND) 
728       triggers |= AliAODForwardMult::kNSD;
729   }
730   if (ta.IsOfflineTriggerFired(esd, AliTriggerAnalysis::kNSD1)) 
731     triggers |= AliAODForwardMult::kNSD;
732   
733   // Check for multiple vertices (pile-up) with at least 3
734   // contributors and at least 0.8cm from the primary vertex
735   Bool_t pileup = kFALSE;
736   if(fCollisionSystem == AliForwardUtil::kPP)
737     pileup =  esd->IsPileupFromSPD(fMinPileupContrib,fMinPileupDistance);
738   if (pileup) {
739     triggers |= AliAODForwardMult::kPileUp;
740     fHTriggers->Fill(kPileUp+.5);
741   }
742   
743   // Get trigger stuff 
744   
745   //TString trigStr = esd->GetFiredTriggerClasses();
746   // AliWarning(Form("Fired trigger classes: %s", trigStr.Data()));
747   if (fHWords) fHWords->Fill(trigStr.Data(), 1);
748 #if 0
749   if (trigStr.Contains("MB1") || trigStr.Contains("MBBG3"))
750     triggers |= AliAOODForwardMult::kB;
751   if (trigStr.Contains("COTA")) 
752     triggers |= AliAODForwardMult::kA;
753   if (trigStr.Contains("COTC")) 
754     triggers |= AliAODForwardMult::kC;
755 #endif
756   if (trigStr.Contains("CBEAMB-ABCE-NOPF-ALL")) {
757     triggers |= AliAODForwardMult::kEmpty;
758     fHTriggers->Fill(kEmpty+.5);
759   }
760 #if 0 
761   // Check for B triggers
762   if (trigStr.Contains("CINT1B-ABCE-NOPF-ALL")   ||   // Early pp
763       trigStr.Contains("CINT1-B-NOPF-ALLNOTRD")  ||   // Late pp 
764       trigStr.Contains("CINT1-B-NOPF-FASTNOTRD") ||   // Late pp
765       //trigStr.Contains("CMUS1-B-NOPF-MUON")      ||   // Late pp -- HHD 160811
766       trigStr.Contains("CSMBB-ABCE-NOPF-ALL")    ||   // pp
767       trigStr.Contains("CMBACS2-B-NOPF-ALL")     ||   // PbPb
768       // trigStr.Contains("C0SMH-B-NOPF-ALL")    ||   // PbPb - high mult
769       trigStr.Contains("CMBS2A-B-NOPF-ALL")      ||   // PbPb
770       trigStr.Contains("CMBS2C-B-NOPF-ALL")      ||   // PbPb
771       trigStr.Contains("CMBAC-B-NOPF-ALL")       ||   // PbPb
772       // trigStr.Contains("C0SMH-B-NOPF-ALL")    ||   // PbPb - high mult
773       trigStr.Contains("CMBACS2-B-NOPF-ALLNOTRD")     // PbPb
774       // trigStr.Contains("C0SMH-B-NOPF-ALLNOTRD")    // PbPb - high mult
775       ) {
776     Bool_t bTrigger = kTRUE;
777     if ( trigStr.Contains("CINT1-B-NOPF-FASTNOTRD") && 
778          !trigStr.Contains("CINT1-B-NOPF-ALLNOTRD") && 
779          TMath::Abs(fEnergy - 2750.) < 20 && 
780          fCollisionSystem == AliForwardUtil::kPP)
781       bTrigger = kFALSE;
782     if(bTrigger) {
783       triggers |= AliAODForwardMult::kB;
784       fHTriggers->Fill(kB+.5);
785     }
786   }
787   
788   // Check for A triggers
789   if (trigStr.Contains("CINT1A-ABCE-NOPF-ALL")    ||   // Early pp
790       trigStr.Contains("CINT1-AC-NOPF-ALLNOTRD")  ||   // Late pp
791       trigStr.Contains("CINT1-AC-NOPF-FASTNOTRD") ||   // Late pp
792       (trigStr.Contains("CSMBA-ABCE-NOPF-ALL") && 
793        !(triggers & AliAODForwardMult::kB))       ||   // pp
794       trigStr.Contains("CMBACS2-A-NOPF-ALL")      ||   // PbPb
795       // trigStr.Contains("C0SMH-A-NOPF-ALL")     ||   // PbPb - high mult
796       trigStr.Contains("CMBS2A-A-NOPF-ALL")       ||   // PbPb
797       trigStr.Contains("CMBS2C-A-NOPF-ALL")       ||   // PbPb
798       trigStr.Contains("CMBAC-A-NOPF-ALL")        ||   // PbPb
799       // trigStr.Contains("C0SMH-A-NOPF-ALL")     ||   // PbPb - high mult
800       trigStr.Contains("CMBACS2-A-NOPF-ALLNOTRD")     // PbPb
801       // trigStr.Contains("C0SMH-A-NOPF-ALLNOTRD")    // PbPb - high mult
802       ) {
803     triggers |= AliAODForwardMult::kA;
804     fHTriggers->Fill(kA+.5);
805   }
806
807   // Check for C triggers
808   if (trigStr.Contains("CINT1C-ABCE-NOPF-ALL")   ||  // Early pp
809       (trigStr.Contains("CSMBC-ABCE-NOPF-ALL") && 
810        !(triggers & AliAODForwardMult::kB))      ||   // pp
811       trigStr.Contains("CMBACS2-C-NOPF-ALL")     ||   // PbPb
812       // trigStr.Contains("C0SMH-B-NOPF-ALL")    ||   // PbPb - high mult
813       trigStr.Contains("CMBS2A-C-NOPF-ALL")      ||   // PbPb
814       trigStr.Contains("CMBS2C-C-NOPF-ALL")      ||   // PbPb
815       trigStr.Contains("CMBAC-C-NOPF-ALL")       ||   // PbPb
816       // trigStr.Contains("C0SMH-B-NOPF-ALL")    ||   // PbPb - high mult
817       trigStr.Contains("CMBACS2-C-NOPF-ALLNOTRD")     // PbPb
818       // trigStr.Contains("C0SMH-B-NOPF-ALLNOTRD")    // PbPb - high mult
819       ) {
820     triggers |= AliAODForwardMult::kC;
821     fHTriggers->Fill(kC+.5);
822   }
823
824   // Check for E triggers 
825   if (trigStr.Contains("CINT1-E-NOPF-ALL")       ||   // Early pp 
826       trigStr.Contains("CINT1-E-NOPF-ALLNOTRD")  ||   // Late pp 
827       trigStr.Contains("CINT1-E-NOPF-FASTNOTRD") ||   // Late pp 
828       trigStr.Contains("CMBACS2-E-NOPF-ALL")     ||   // PbPb
829       // trigStr.Contains("C0SMH-B-NOPF-ALL")    ||   // PbPb - high mult
830       trigStr.Contains("CMBS2A-E-NOPF-ALL")      ||   // PbPb
831       trigStr.Contains("CMBS2C-E-NOPF-ALL")      ||   // PbPb
832       trigStr.Contains("CMBAC-E-NOPF-ALL")       ||   // PbPb
833       // trigStr.Contains("C0SMH-B-NOPF-ALL")    ||   // PbPb - high mult
834       trigStr.Contains("CMBACS2-E-NOPF-ALLNOTRD")     // PbPb
835       // trigStr.Contains("C0SMH-B-NOPF-ALLNOTRD")    // PbPb - high mult
836       ) {
837     triggers |= AliAODForwardMult::kE;
838     fHTriggers->Fill(kE+.5);
839   }
840 #endif
841
842   const TList* collTriggClasses = ps->GetCollisionTriggerClasses();
843   const TList* bgTriggClasses = ps->GetBGTriggerClasses();
844
845   TIter nextColl(collTriggClasses);
846   TObjString* oadbString = 0;
847   TObjArray* tokens = 0;
848   while ((oadbString = static_cast<TObjString*>(nextColl()))) {
849     tokens = oadbString->String().Tokenize(" ");
850     for (Int_t i = 0; i < tokens->GetEntries(); i++) {
851       TString string = (((TObjString*)tokens->At(i))->String());
852       if (string[0] != '+') continue;
853       string.Remove(0,1);
854       if (trigStr.Contains(string.Data())) {
855         TString beamSide = oadb->GetBeamSide(oadbString->String().Data());
856         if (beamSide.EqualTo("B")) {
857           triggers |= AliAODForwardMult::kB;
858           fHTriggers->Fill(kB+.5);
859         }
860       }
861     }
862   }
863   TIter nextBG(bgTriggClasses);
864   while ((oadbString = static_cast<TObjString*>(nextBG()))) {
865     tokens = oadbString->String().Tokenize(" ");
866     for (Int_t i = 0; i < tokens->GetEntries(); i++) {
867       TString string = (((TObjString*)tokens->At(i))->String());
868       if (string[0] != '+') continue;
869       string.Remove(0,1);
870       if (trigStr.Contains(string.Data())) {
871         TString beamSide = oadb->GetBeamSide(oadbString->String().Data());
872         if (beamSide.Contains("A")) {
873           triggers |= AliAODForwardMult::kA;
874           fHTriggers->Fill(kA+.5);
875         }
876         if (beamSide.Contains("C")) {
877           triggers |= AliAODForwardMult::kC;
878           fHTriggers->Fill(kC+.5);
879         }
880         if (beamSide.Contains("E")) {
881           triggers |= AliAODForwardMult::kE;
882           fHTriggers->Fill(kE+.5);
883         }
884       }
885     }
886   }
887
888   // Now check - if we have a collision - for offline triggers and
889   // fill histogram.
890   if (triggers & AliAODForwardMult::kB) {
891     if (triggers & AliAODForwardMult::kInel) 
892       fHTriggers->Fill(kInel);
893     
894     if (triggers & AliAODForwardMult::kInelGt0)
895       fHTriggers->Fill(kInelGt0+.5);
896     
897     if (triggers & AliAODForwardMult::kNSD)
898       fHTriggers->Fill(kNSD+.5);
899
900     if (triggers & AliAODForwardMult::kV0AND)
901       fHTriggers->Fill(kV0AND+.5);
902   }
903   
904   return kTRUE;
905 }
906 //____________________________________________________________________
907 Bool_t
908 AliFMDEventInspector::ReadVertex(const AliESDEvent* esd, 
909                                  Double_t& vz, 
910                                  Double_t& vx, 
911                                  Double_t& vy)
912 {
913   // 
914   // Read the vertex information from the ESD event 
915   // 
916   // Parameters:
917   //   esd  ESD event 
918   //   vz   On return, the vertex Z position 
919   // 
920   // Return:
921   //    @c true on success, @c false otherwise 
922   //
923   vz = 0;
924   vx = 1024;
925   vy = 1024;
926   
927   AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
928   Bool_t isMC = am->GetMCtruthEventHandler() != 0;
929   if(fUseDisplacedVertices && isMC) {
930     
931     AliMCEventHandler* mchandler = static_cast<AliMCEventHandler*>(am->GetMCtruthEventHandler());
932     AliMCEvent* mcevent          = mchandler->MCEvent();
933     AliHeader* header            = mcevent->Header();
934     AliGenEventHeader* genHeader = header->GenEventHeader();
935     TArrayF vertex;
936     genHeader->PrimaryVertex(vertex);
937
938     Double_t zvtx = vertex.At(2);
939     Double_t ratio = zvtx/37.5;
940     if(ratio > 0) ratio = ratio + 0.5;
941     if(ratio < 0) ratio = ratio - 0.5;
942     Int_t ratioInt = (Int_t)ratio;
943     zvtx = 37.5*((Double_t)ratioInt);
944     if(TMath::Abs(zvtx) < 999) {
945       vz = zvtx;
946       return true;
947     }
948     else return false;
949     
950   }
951   if(fUseDisplacedVertices && !isMC) {
952     Double_t zvtx = fDisplacedVertex.CheckDisplacedVertex(esd);
953     
954     if(TMath::Abs(zvtx) < 999) {
955       vz = zvtx;
956       return true;
957     }
958     else return false;
959   }
960
961   if(fUseFirstPhysicsVertex) {
962     // This is the code used by the 1st physics people 
963     const AliESDVertex* vertex    = esd->GetPrimaryVertex();
964     if (!vertex  || !vertex->GetStatus()) {
965       if (fDebug > 2) {
966         AliWarning(Form("No primary vertex (%p) or bad status %d", 
967                         vertex, (vertex ? vertex->GetStatus() : -1)));
968       }
969       return false;
970     }
971     const AliESDVertex* vertexSPD = esd->GetPrimaryVertexSPD();
972     if (!vertexSPD || !vertexSPD->GetStatus()) {
973       if (fDebug > 2) {
974         AliWarning(Form("No primary SPD vertex (%p) or bad status %d", 
975                         vertexSPD, (vertexSPD ? vertexSPD->GetStatus() : -1)));
976       }
977       return false;
978     }
979     
980     // if vertex is from SPD vertexZ, require more stringent cuts 
981     if (vertex->IsFromVertexerZ()) { 
982       if (vertex->GetDispersion() > fMaxVzErr || 
983           vertex->GetZRes() > 1.25 * fMaxVzErr) {
984         if (fDebug > 2) {
985           AliWarning(Form("Dispersion %f > %f or resolution %f > %f",
986                           vertex->GetDispersion(), fMaxVzErr,
987                           vertex->GetZRes(), 1.25 * fMaxVzErr)); 
988         }
989         return false;
990       }
991     }
992     vz = vertex->GetZ();
993     
994     if(!vertex->IsFromVertexerZ()) {
995       vx = vertex->GetX();
996       vy = vertex->GetY();
997     }
998     return true;
999   }
1000   else { //Use standard SPD vertex (perhaps preferable for Pb+Pb)
1001    
1002     // Get the vertex 
1003     const AliESDVertex* vertex = esd->GetPrimaryVertexSPD();
1004     if (!vertex) { 
1005       if (fDebug > 2) {
1006         AliWarning("No SPD vertex found in ESD"); }
1007       return kFALSE;
1008     }
1009     
1010     // Check that enough tracklets contributed 
1011     if(vertex->GetNContributors() <= 0) {
1012       if (fDebug > 2) {
1013         AliWarning(Form("Number of contributors to vertex is %d<=0",
1014                         vertex->GetNContributors())); }
1015       vz = 0;
1016       return kFALSE;
1017     } 
1018     // Check that the uncertainty isn't too large 
1019     if (vertex->GetZRes() > fMaxVzErr) { 
1020       if (fDebug > 2) {
1021         AliWarning(Form("Uncertaintity in Z of vertex is too large %f > %f", 
1022                       vertex->GetZRes(), fMaxVzErr)); }
1023       return kFALSE;
1024     }
1025     
1026     // Get the z coordiante 
1027     vz = vertex->GetZ();
1028     const AliESDVertex* vertexXY = esd->GetPrimaryVertex();
1029     
1030     if(!vertexXY->IsFromVertexerZ()) {
1031       vx = vertexXY->GetX();
1032       vy = vertexXY->GetY();
1033     }
1034     return kTRUE;
1035   } 
1036 }
1037   
1038 //____________________________________________________________________
1039 Bool_t
1040 AliFMDEventInspector::ReadRunDetails(const AliESDEvent* esd)
1041 {
1042   // 
1043   // Read the collision system, collision energy, and L3 field setting
1044   // from the ESD
1045   // 
1046   // Parameters:
1047   //   esd ESD to get information from 
1048   // 
1049   // Return:
1050   //    true on success, false 
1051   //
1052   // AliInfo(Form("Parameters from 1st ESD event: cms=%s, sNN=%f, field=%f",
1053   //           esd->GetBeamType(), 2*esd->GetBeamEnergy(), 
1054   //           esd->GetMagneticField()));
1055   fCollisionSystem = 
1056     AliForwardUtil::ParseCollisionSystem(esd->GetBeamType());
1057   fEnergy          = 
1058     AliForwardUtil::ParseCenterOfMassEnergy(fCollisionSystem,   
1059                                             2 * esd->GetBeamEnergy());
1060   fField           = 
1061     AliForwardUtil::ParseMagneticField(esd->GetMagneticField());
1062
1063   StoreInformation(esd->GetRunNumber());
1064   if (fCollisionSystem   == AliForwardUtil::kUnknown || 
1065       fEnergy            <= 0                        || 
1066       TMath::Abs(fField) >  10) 
1067     return kFALSE;
1068
1069   return kTRUE;
1070 }
1071
1072 //____________________________________________________________________
1073 void
1074 AliFMDEventInspector::Print(Option_t*) const
1075 {
1076   // 
1077   // Print information
1078   // 
1079   //   option Not used 
1080   //
1081   char ind[gROOT->GetDirLevel()+1];
1082   for (Int_t i = 0; i < gROOT->GetDirLevel(); i++) ind[i] = ' ';
1083   ind[gROOT->GetDirLevel()] = '\0';
1084   TString sNN(AliForwardUtil::CenterOfMassEnergyString(fEnergy));
1085   sNN.Strip(TString::kBoth, '0');
1086   sNN.ReplaceAll("GeV", " GeV");
1087   TString field(AliForwardUtil::MagneticFieldString(fField));
1088   field.ReplaceAll("p",  "+");
1089   field.ReplaceAll("m",  "-");
1090   field.ReplaceAll("kG", " kG");
1091   
1092   std::cout << ind << ClassName() << ": " << GetName() << '\n'
1093             << ind << " Vertex bins:            " << fVtxAxis.GetNbins() << '\n'
1094             << ind << " Vertex range:           [" << fVtxAxis.GetXmin() 
1095             << "," << fVtxAxis.GetXmax() << "]\n"
1096             << ind << " Low flux cut:           " << fLowFluxCut << '\n'
1097             << ind << " Max(delta v_z):         " << fMaxVzErr << " cm\n"
1098             << ind << " Min(nContrib_pileup):   " << fMinPileupContrib << '\n'
1099             << ind << " Min(v-pileup):          " << fMinPileupDistance << '\n'
1100             << ind << " System:                 " 
1101             << AliForwardUtil::CollisionSystemString(fCollisionSystem) << '\n'
1102             << ind << " CMS energy per nucleon: " << sNN << '\n'
1103             << ind << " Field:                  " <<  field << '\n';
1104   if (!fCentAxis) { std::cout << std::flush; return; }
1105   Int_t nBin = fCentAxis->GetNbins();
1106   std::cout << ind << " Centrality axis:        " << nBin << " bins"
1107             << std::flush;
1108   for (Int_t i = 0; i < nBin; i++) { 
1109     if ((i % 10) == 0) std::cout << '\n' << ind << "  ";
1110     std::cout << std::setw(5) << fCentAxis->GetBinLowEdge(i+1) << '-';
1111   }
1112   std::cout << std::setw(5) << fCentAxis->GetBinUpEdge(nBin) << std::endl;
1113 }
1114
1115   
1116 //
1117 // EOF
1118 //
1119