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