]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWG/muondep/AliAnalysisTriggerScalers.cxx
from Carlos Eugenio Perez Lara:
[u/mrichter/AliRoot.git] / PWG / muondep / AliAnalysisTriggerScalers.cxx
CommitLineData
2f331ac9 1/**************************************************************************
2* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3* *
4* Author: The ALICE Off-line Project. *
5* Contributors are mentioned in the code where appropriate. *
6* *
7* Permission to use, copy, modify and distribute this software and its *
8* documentation strictly for non-commercial purposes is hereby granted *
9* without fee, provided that the above copyright notice appears in all *
10* copies and that both the copyright notice and this permission notice *
11* appear in the supporting documentation. The authors make no claims *
12* about the suitability of this software for any purpose. It is *
13* provided "as is" without express or implied warranty. *
14**************************************************************************/
15
16// $Id$
17
e538121a 18//
19// AliAnalysisTriggerScalers : utility class to play with OCDB scalers.
20//
21// Can use it to e.g. :
22//
23// - get the integrated luminosity for a given period
24// (see IntegratedLuminosity method)
58b19963 25//
e538121a 26// - plot the trigger rates (see PlotTriggerEvolution)
27//
58b19963 28// Please note that this class is doing an OCDB "scan" (for as many run
29// as you put in the SetRunList method), so it can be really long
30// if you're using the raw:// OCDB. If you're planning on using this
31// class for anything more than a brief test, you'd better think
32// or making a local copy of the OCDB objects required by this class :
33//
34// GRP/CTP/Config
35// GRP/CTP/Scalers
36//
37// and also (to get the fill and period ranges, mainly for drawing)
38//
39// GRP/GRP/Data
40// GRP/GRP/LHCData
41//
42//
43// Please note also that this class evolved from a set a quick macros to
44// follow the luminosity and trigger rates during data taking to this stage.
45//
46// Now (Feb 2013) would probably be a good time to regroup a bit, think about it and
47// make it more general, more robust and just less "had-hoc"...
48//
49// Ideas for improvement :
50//
51// - make sure the "what" parameter mean the same thing in all methods
52// and so can take the same values in all methods
53//
54// - get the lumi trigger name and cross-section from e.g. OADB instead of
55// hard-coding them ?
56//
57// - organize the class so that the CTP Scalers and Config can be fetched
58// from elsewhere (e.g. from a run based container available in some
59// distant future in the ESDs/AODs ?)
60//
61// - robustify the PAC fraction computation
62//
63//
e538121a 64// L. Aphecetche (Subatech)
65//
66
2f331ac9 67#include "AliAnalysisTriggerScalers.h"
68#include "AliCDBEntry.h"
69#include "AliCDBManager.h"
70#include "AliGRPObject.h"
71#include "AliLog.h"
72#include "AliTimeStamp.h"
73#include "AliTriggerBCMask.h"
74#include "AliTriggerClass.h"
75#include "AliTriggerCluster.h"
76#include "AliTriggerConfiguration.h"
77#include "AliTriggerDescriptor.h"
78#include "AliTriggerInput.h"
79#include "AliTriggerRunScalers.h"
80#include "AliTriggerScalers.h"
81#include "AliTriggerScalersESD.h"
82#include "AliTriggerScalersRecord.h"
83#include "Riostream.h"
84#include "TDatime.h"
85#include "TError.h"
86#include "TGraph.h"
acbe06d5 87#include "TGraphErrors.h"
c665b011 88#include "TH2.h"
2f331ac9 89#include "TObjArray.h"
90#include "TObjString.h"
91#include <set>
92#include <map>
93#include "TStyle.h"
94#include "AliLHCData.h"
95#include "TMath.h"
96#include "TAxis.h"
e538121a 97#include "TBox.h"
2f331ac9 98#include "TCanvas.h"
e538121a 99#include "TText.h"
2f331ac9 100
101ClassImp(AliAnalysisTriggerScalers)
102
103namespace {
104
105 //______________________________________________________________________________
106 UChar_t GetIndex(ULong64_t mask)
107 {
108 for ( Int_t i = 0; i < 64; ++i )
109 {
110 if ( mask & ( 1ull << i ) ) return i+1;
111 }
112 return 0;
113 }
114
115
116 //______________________________________________________________________________
117 Double_t Mu(Double_t L0B, Double_t Nb)
118 {
119 /// L0B = trigger rate before any veto
120 /// Nb = number of crossing bunches
121
122 Double_t p0 = 1-L0B/(Nb*11245.0); // proba to get *no* collision per bunch crossing
123
124 return -TMath::Log(p0);
125 }
126
127 //______________________________________________________________________________
128 TCanvas* NewCanvas(const char* name)
129 {
130 TCanvas* c = new TCanvas(name,name);
131 c->SetLeftMargin(0.15);
132 return c;
133 }
134
135 //______________________________________________________________________________
136 void TimeAxis(TGraph* g)
137 {
138// g->GetXaxis()->SetTimeDisplay(1);
139// g->GetXaxis()->SetTimeFormat("%d/%m %H:%M%F2010-12-31 24:00:00");
140// g->GetXaxis()->SetNdivisions(505);
141 g->GetYaxis()->SetTitleOffset(1.5);
142
143 g->GetXaxis()->SetTimeDisplay(1);
144 // g->GetXaxis()->SetTimeFormat("%d/%m %H:%M%F2010-12-31 24:00:00");
145 g->GetXaxis()->SetTimeFormat("%d/%m %H:%M");
146 g->GetXaxis()->SetTimeOffset(0,"gmt");
147 g->GetXaxis()->SetNdivisions(505);
148
149 }
150
151}
152
153//_____________________________________________________________________________
58b19963 154AliAnalysisTriggerScalers::AliAnalysisTriggerScalers(Int_t runNumber, const char* ocdbPath) : fRunList(), fOCDBPath(ocdbPath), fShouldCorrectForPileUp(kTRUE), fCrossSectionUnit("UB")
2f331ac9 155{
156 // ctor using a single run number
157 SetRunList(runNumber);
158}
159
e538121a 160//_____________________________________________________________________________
58b19963 161AliAnalysisTriggerScalers::AliAnalysisTriggerScalers(const std::vector<int>& runs, const char* ocdbPath) : fRunList(), fOCDBPath(ocdbPath), fShouldCorrectForPileUp(kTRUE), fCrossSectionUnit("UB")
e538121a 162{
163 // ctor using a vector of run numbers
164 SetRunList(runs);
165}
166
167//_____________________________________________________________________________
58b19963 168AliAnalysisTriggerScalers::AliAnalysisTriggerScalers(const std::set<int>& runs, const char* ocdbPath) : fRunList(), fOCDBPath(ocdbPath), fShouldCorrectForPileUp(kTRUE), fCrossSectionUnit("UB")
e538121a 169{
170 // ctor using a set of run numbers
171 SetRunList(runs);
172}
173
2f331ac9 174//_____________________________________________________________________________
58b19963 175AliAnalysisTriggerScalers::AliAnalysisTriggerScalers(const char* runlist, const char* ocdbPath) : fRunList(), fOCDBPath(ocdbPath), fShouldCorrectForPileUp(kTRUE), fCrossSectionUnit("UB")
2f331ac9 176{
177 // ctor from a run list (txt file)
178 SetRunList(runlist);
179}
180
181//_____________________________________________________________________________
182AliAnalysisTriggerScalers::~AliAnalysisTriggerScalers()
183{
e538121a 184 // dtor
2f331ac9 185}
186
58b19963 187//______________________________________________________________________________
188Bool_t AliAnalysisTriggerScalers::CheckRecord(const AliTriggerScalersRecord& record,
189 UInt_t index,
190 UInt_t refb,
191 UInt_t refa,
192 UInt_t timelapse) const
193{
194 /// Check if a trigger scaler record should be kept for our
195 /// luminosity computations
196
197 const AliTriggerScalers* scaler = record.GetTriggerScalersForClass(index);
198
199 UInt_t a = scaler->GetLOCA() - refa;
200 UInt_t b = scaler->GetLOCB() - refb;
201
202 Bool_t ok(kTRUE);
203
204 if ( b <= 2 || ( a <= 2 ) || timelapse <= 9 ) // empirical cuts
205 {
206 ok = kFALSE;
207 }
208
209 return ok;
210}
211
212
e538121a 213//______________________________________________________________________________
214void AliAnalysisTriggerScalers::DrawFill(Int_t run1, Int_t run2, double ymin, double ymax, const char* label)
215{
216 // Draw a yellow box to indicate a run range
217
218 AliDebugClass(1,Form("RUN1 %09d RUN2 %09d YMIN %e YMAX %e %s",
219 run1,run2,ymin,ymax,label));
220 TBox* b = new TBox(run1*1.0,ymin,run2*1.0,ymax);
221 b->SetFillColor(5);
222 b->Draw();
58b19963 223 TText* text = new TText((run1+run2)/2.0,ymin + (ymax-ymin)*0.85,label);
e538121a 224 text->SetTextSize(0.025);
225 text->SetTextFont(42);
226 text->SetTextAlign(23);
227 text->SetTextAngle(45);
228 text->Draw();
229}
230
231//_____________________________________________________________________________
232void AliAnalysisTriggerScalers::DrawFills(Double_t ymin, Double_t ymax)
233{
234 /// Draw the fill ranges corresponding to the list of runs
235 /// Note that this method will scan the OCDB to get the run -> fill number relationship,
236 /// so it's better in this case to use a local copy of the OCDB if you have one. Otherwise
237 /// it will be long.
238 ///
239 std::map<int, std::pair<int,int> > fills;
240
241 GetFillBoundaries(fills);
242
243 std::map<int, std::pair<int,int> >::const_iterator it;
244
245 for ( it = fills.begin(); it != fills.end(); ++it )
246 {
247 const std::pair<int,int>& p = it->second;
248 TString fillnumber;
249 fillnumber.Form("%d",it->first);
250 DrawFill(p.first,p.second,ymin,ymax,fillnumber.Data());
251 }
252}
253
58b19963 254//_____________________________________________________________________________
255void AliAnalysisTriggerScalers::GetCTPObjects(Int_t runNumber,
256 AliTriggerConfiguration*& tc,
257 AliTriggerRunScalers*& trs,
258 AliLHCData*& lhc) const
259{
260 /// For a given run, get the CTP objects we need to do our work
261 ///
262 /// FIXME: this is the method that should probably be virtualized so
263 /// we can get those objects from either OCDB or run based container in AODs/ESDs
264
265 tc = static_cast<AliTriggerConfiguration*>(GetOCDBObject("GRP/CTP/Config",runNumber));
266 trs = static_cast<AliTriggerRunScalers*>(GetOCDBObject("GRP/CTP/Scalers",runNumber));
267 lhc = static_cast<AliLHCData*>(GetOCDBObject("GRP/GRP/LHCData",runNumber));
268}
269
e538121a 270//_____________________________________________________________________________
271void AliAnalysisTriggerScalers::GetFillBoundaries(std::map<int, std::pair<int,int> >& fills)
272{
273 /// Given a list of runs get the fills they are in
274
275 fills.clear();
276
277 for ( std::vector<int>::const_iterator it = fRunList.begin(); it != fRunList.end(); ++it )
278 {
279 int runnumber = *it;
280
281 int fill = GetFillNumberFromRunNumber(runnumber);
282
283 if (fills.count(fill))
284 {
285 std::pair<int,int>& p = fills[fill];
286 p.first = TMath::Min(runnumber,p.first);
287 p.second = TMath::Max(runnumber,p.second);
288 }
289 else
290 {
291 fills[fill] = make_pair<int,int>(runnumber,runnumber);
292 }
293 }
294}
295
296
c665b011 297//______________________________________________________________________________
298Int_t AliAnalysisTriggerScalers::GetFillNumberFromRunNumber(Int_t runNumber)
299{
300 /// Get the fill number of a run
301
302 AliLHCData* lhcData = static_cast<AliLHCData*>(GetOCDBObject("GRP/GRP/LHCData",runNumber));
303 if (lhcData)
304 {
305 Int_t fillNumber = lhcData->GetFillNumber();
306 if ( fillNumber == 0 && runNumber == 189694)
307 {
308 // manual hack because GRP info incorrect for this run ?
309 fillNumber = 3135;
310 }
311
312 return fillNumber;
313 }
314 return -1;
315}
316
2f331ac9 317//______________________________________________________________________________
58b19963 318TObject* AliAnalysisTriggerScalers::GetOCDBObject(const char* path, Int_t runNumber) const
2f331ac9 319{
e538121a 320 // Helper method to get an object from the OCDB
321
2f331ac9 322 if ( !AliCDBManager::Instance()->IsDefaultStorageSet() )
323 {
324 AliCDBManager::Instance()->SetDefaultStorage(fOCDBPath.Data());
325 }
326
327 AliCDBManager::Instance()->SetRun(runNumber);
328
329 gErrorIgnoreLevel=kWarning; // to avoid all the TAlienFile::Open messages...
330
331 AliCDBEntry* e = AliCDBManager::Instance()->Get(path);
332 return e ? e->GetObject() : 0x0;
333}
334
335
58b19963 336//______________________________________________________________________________
337TString AliAnalysisTriggerScalers::GetLHCPeriodFromRunNumber(Int_t runNumber) const
338{
339 /// Get a list of LHC periods from a list of run numbers
340
341 AliGRPObject* grp = static_cast<AliGRPObject*>(GetOCDBObject("GRP/GRP/Data",runNumber));
342
343 if (!grp) return "";
344
345 return grp->GetLHCPeriod();
346}
347
348//_____________________________________________________________________________
349void
350AliAnalysisTriggerScalers::GetLuminosityTriggerAndCrossSection(Int_t runNumber,
351 TString& lumiTriggerClassName,
352 Double_t& lumiTriggerCrossSection,
353 Double_t& lumiTriggerCrossSectionError) const
354{
355 /// For one given run, get the trigger class name to be used as the luminometer,
356 /// and its corresponding cross-section
357 ///
358 /// FIXME: all is hard-coded for now... (use OADB for this ?)
359
360 lumiTriggerClassName="";
361 lumiTriggerCrossSection=0.0;
362 lumiTriggerCrossSectionError=0.0; // FIXME
363
364 TString period = GetLHCPeriodFromRunNumber(runNumber);
365
366 if ( period.BeginsWith("LHC11") )
367 {
368 AliError("Not implemented yet");
369 }
370 else if ( period.BeginsWith("LHC12") )
371 {
372 if ( period == "LHC12h" || period == "LHC12i" )
373 {
374 // pp 8 TeV main-satellites
375 lumiTriggerClassName = "C0TVX-S-NOPF-ALLNOTRD";
376 lumiTriggerCrossSection = 28.0; // FIXME: not from a vdM yet
377 }
378 else
379 {
380 AliError("Not implemented yet");
381 }
382 }
383 else if ( period.BeginsWith("LHC13") )
384 {
385 if ( period == "LHC13g" )
386 {
387 // pp 2.76 TeV
388 lumiTriggerClassName = "C0TVX-B-NOPF-ALLNOTRD";
389 lumiTriggerCrossSection = 18.0; // FIXME: not from a vdM yet
390 }
391 else
392 {
393 // p-Pb or Pb-p 5.02 TeV
394 lumiTriggerClassName = "C0TVX-B-NOPF-ALLNOTRD";
395 lumiTriggerCrossSection = 0.755*2000; // FIXME: not from a vdM yet
396 }
397 }
398 else
399 {
400 AliError("Not implemented yet");
401 }
402
403 float csMult(1.0);
404
405 if ( fCrossSectionUnit=="PB" )
406 {
407 csMult=1E9;
408 }
409 else if (fCrossSectionUnit=="NB")
410 {
411 csMult=1E6;
412 }
413 else if ( fCrossSectionUnit=="UB" )
414 {
415 csMult=1E3;
416 }
417 else if ( fCrossSectionUnit=="MB" )
418 {
419 csMult=1.0;
420 }
421
422 lumiTriggerCrossSection *= csMult;
423 lumiTriggerCrossSectionError *= csMult;
424}
425
426//_____________________________________________________________________________
427void AliAnalysisTriggerScalers::GetLHCPeriodBoundaries(std::map<std::string, std::pair<int,int> >& periods)
428{
429 /// Given a list of runs get the fills they are in
430
431 periods.clear();
432
433 for ( std::vector<int>::const_iterator it = fRunList.begin(); it != fRunList.end(); ++it )
434 {
435 int runnumber = *it;
436
437 std::string period = GetLHCPeriodFromRunNumber(runnumber).Data();
438
439 if (periods.count(period))
440 {
441 std::pair<int,int>& p = periods[period];
442 p.first = TMath::Min(runnumber,p.first);
443 p.second = TMath::Max(runnumber,p.second);
444 }
445 else
446 {
447 periods[period] = make_pair<int,int>(runnumber,runnumber);
448 }
449 }
450}
451
452
2f331ac9 453//______________________________________________________________________________
454Int_t AliAnalysisTriggerScalers::GetTriggerInput(Int_t runNumber, const char* inputname)
455{
e538121a 456 /// Get one trigger input for a given run
2f331ac9 457 AliTriggerConfiguration* tc = static_cast<AliTriggerConfiguration*>(GetOCDBObject("GRP/CTP/Config",runNumber));
458 if (!tc) return -1;
459
460 const TObjArray& inputs = tc->GetInputs();
461
462 AliTriggerInput* ti = static_cast<AliTriggerInput*>(inputs.FindObject(inputname));
463
464 if (!ti) return -1;
465
466 return ti->GetSignature();
467}
468
e538121a 469//______________________________________________________________________________
470Float_t
471AliAnalysisTriggerScalers::GetPauseAndConfigCorrection(Int_t runNumber, const char* triggerClassName)
472{
473 /// Tries to estimate the duration of the Pause and Configure phase(s) in a given run
474 /// Probably not really accurate for the moment though.
475
476 ULong64_t total(0);
477 ULong64_t nopac(0);
478
479 AliTriggerConfiguration* tc = static_cast<AliTriggerConfiguration*>(GetOCDBObject("GRP/CTP/Config",runNumber));
480
481 AliTriggerRunScalers* trs = static_cast<AliTriggerRunScalers*>(GetOCDBObject("GRP/CTP/Scalers",runNumber));
482 const TObjArray* scalers = trs->GetScalersRecords();
483
484 TIter next(scalers);
485 AliTriggerScalersRecord* record;
486 UInt_t reft(0);
487 UInt_t refl0b(0);
488 UInt_t refl0a(0);
489 Bool_t first(kTRUE);
490
491 Int_t classIndex = tc->GetClassIndexFromName(triggerClassName);
492
493 while ( ( record = static_cast<AliTriggerScalersRecord*>(next()) ) )
494 {
495 const AliTriggerScalers* scaler = record->GetTriggerScalersForClass(classIndex);
496
497 const AliTimeStamp* ats = record->GetTimeStamp();
498
499 UInt_t seconds = ats->GetSeconds();// - TTimeStamp::GetZoneOffset();
500
501 TTimeStamp ts(seconds,ats->GetMicroSecs());
502
503 UInt_t l0b = scaler->GetLOCB() - refl0b;
504 UInt_t l0a = scaler->GetLOCA() - refl0a;
505 UInt_t timelapse = seconds - reft;
506
507 if ( l0b <=2 || timelapse < 9 ) continue;
508
509 reft = seconds;
510 refl0b = scaler->GetLOCB();
511 refl0a = scaler->GetLOCA();
512
513 if ( first )
514 {
515 first = kFALSE;
516 continue;
517 }
518
519 total += l0b;
520
521 if ( l0a > 0 )
522 {
523 nopac += l0b;
524 }
525 }
526
527 return total > 0 ? nopac*1.0/total : 0.0;
528}
529
2f331ac9 530//______________________________________________________________________________
531AliAnalysisTriggerScalerItem*
532AliAnalysisTriggerScalers::GetTriggerScaler(Int_t runNumber, const char* level, const char* triggerClassName)
533{
534 // Get the scaler for a given trigger class and a given trigger level.
535 // Returned object must be deleted by the user.
536
537 AliTriggerConfiguration* tc = static_cast<AliTriggerConfiguration*>(GetOCDBObject("GRP/CTP/Config",runNumber));
538 AliTriggerRunScalers* trs = static_cast<AliTriggerRunScalers*>(GetOCDBObject("GRP/CTP/Scalers",runNumber));
539 AliGRPObject* grp = static_cast<AliGRPObject*>(GetOCDBObject("GRP/GRP/Data",runNumber));
540
541 TString diCurrent(Form("L3:%5.0f;DIP:%5.0f [L3:%d;DIP:%d]",
542 grp->GetL3Current((AliGRPObject::Stats)0),
543 grp->GetDipoleCurrent((AliGRPObject::Stats)0),
544 grp->GetL3Polarity(),
545 grp->GetDipolePolarity()));
546
547 if (!tc || !trs || !grp) return 0x0;
548
2f331ac9 549 const TObjArray& trClasses = tc->GetClasses();
550
551 const TObjArray* scalers = trs->GetScalersRecords();
552 const AliTriggerScalersRecord* begin = (AliTriggerScalersRecord*)(scalers->First());
553 const AliTriggerScalersRecord* end = (AliTriggerScalersRecord*)(scalers->Last());
e538121a 554
555 time_t duration = (end->GetTimeStamp()->GetBunchCross() - begin->GetTimeStamp()->GetBunchCross())*AliTimeStamp::fNanosecPerBC*1E-9;
2f331ac9 556
557 AliTriggerClass* triggerClass = static_cast<AliTriggerClass*>(trClasses.FindObject(triggerClassName));
558 if (!triggerClass)
559 {
560 return 0x0;
561 }
562 UChar_t index = GetIndex(triggerClass->GetMask());
563
564 ULong64_t value(0);
565
566 const AliTriggerScalers* sbegin = begin->GetTriggerScalersForClass(index);
567 const AliTriggerScalers* send = end->GetTriggerScalersForClass(index);
568
569 TString swhat(level);
570 swhat.ToUpper();
571
572 if ( swhat.BeginsWith("L0A") )
573 {
574 value = send->GetLOCA() - sbegin->GetLOCA();
575 }
576 else if ( swhat.BeginsWith("L0B") )
577 {
578 value = send->GetLOCB() - sbegin->GetLOCB();
579 }
e538121a 580 else if ( swhat.BeginsWith("L1A") )
2f331ac9 581 {
582 value = send->GetL1CA() - sbegin->GetL1CA();
583 }
e538121a 584 else if ( swhat.BeginsWith("L1B") )
2f331ac9 585 {
586 value = send->GetL1CB() - sbegin->GetL1CB();
587 }
e538121a 588 else if ( swhat.BeginsWith("L2A") )
2f331ac9 589 {
590 value = send->GetL2CA() - sbegin->GetL2CA();
591 }
e538121a 592 else if ( swhat.BeginsWith("L2B") )
2f331ac9 593 {
594 value = send->GetL2CB() - sbegin->GetL2CB();
595 }
2f331ac9 596 Int_t ds(1);
597
598 // FIXME: get the downscaling factor here for all cases (only BC1 supported here so far)
599 if ( TString(triggerClassName).Contains("_B1") )
600 {
601 ds = GetTriggerInput(runNumber,"BC1");
602 if (!ds) ds=1;
603 }
604
605 swhat.ReplaceAll("RATE","");
606
607 return new AliAnalysisTriggerScalerItem(runNumber,swhat.Data(),diCurrent.Data(),triggerClass->GetName(),value,triggerClass->GetBCMask(),ds,duration);
608}
609
58b19963 610//______________________________________________________________________________
611TGraph*
612AliAnalysisTriggerScalers::IntegratedLuminosityGraph(const char* triggerClassName, const char* triggerClassNameForPACEstimate)
613{
614 // Get the integrated luminosity graph for one trigger
615
616 if ( fRunList.empty() )
617 {
618 AliError("Cannot work without a run list");
619 return 0x0;
620 }
621
622 Double_t offset(0.0);
623
624 std::vector<double> vx;
625 std::vector<double> vy;
626
627 Double_t x,y;
628
629 for ( std::vector<int>::size_type i = 0; i < fRunList.size(); ++i )
630 {
631 TGraph* g = IntegratedLuminosityGraph(fRunList[i],triggerClassName,triggerClassNameForPACEstimate);
632
633 if (!g) continue;
634
635 for ( Int_t j = 0 ; j < g->GetN(); ++j )
636 {
637 g->GetPoint(j,x,y);
638 vx.push_back(x);
639 vy.push_back(y+offset);
640 }
641
642 offset += y;
643
644 delete g;
645 }
646
647 TGraph* g = new TGraph(vx.size(),&vx[0],&vy[0]);
648
649 TimeAxis(g);
650
651 return g;
652}
653
654//______________________________________________________________________________
655TGraph*
656AliAnalysisTriggerScalers::IntegratedLuminosityGraph(Int_t runNumber, const char* triggerClassName, const char* triggerClassNameForPACEstimate)
657{
658 // Get the integrated luminosity graph for one trigger for the given run
659 //
660 // the triggerClassNameForPACEstimate is only used if triggerClassName is,
661 // for the given run, the same as the luminometer trigger class name,
662 // and should be the trigger class with the higher and non-zero L0A rate (except during PACs)
663 //
664
665 AliTriggerConfiguration* tc(0x0);
666 AliTriggerRunScalers* trs(0x0);
667 AliLHCData* lhc(0x0);
668
669 GetCTPObjects(runNumber,tc,trs,lhc);
670
671 if (!tc || !trs || !lhc)
672 {
673 return 0x0;
674 }
675
676 const TObjArray* scalerRecords= trs->GetScalersRecords();
677 const TObjArray& triggerClasses = tc->GetClasses();
678
679 TString lumiTriggerClassName;
680 Double_t lumiTriggerCrossSection(0.0);
681 Double_t lumiTriggerCrossSectionError(0.0);
682
683 GetLuminosityTriggerAndCrossSection(runNumber,lumiTriggerClassName,lumiTriggerCrossSection,lumiTriggerCrossSectionError);
684
685 AliTriggerClass* lumiTriggerClass = static_cast<AliTriggerClass*>(triggerClasses.FindObject(lumiTriggerClassName));
686
687 if (!lumiTriggerClass)
688 {
689 AliError(Form("Could not find lumiTriggerClass=%s",lumiTriggerClassName.Data()));
690 return 0x0;
691 }
692
693 if (lumiTriggerCrossSection==0.0)
694 {
695 AliError(Form("Could not get cross-section for lumiTriggerClass=%s",lumiTriggerClassName.Data()));
696 return 0x0;
697 }
698
699 AliTriggerClass* triggerClass = static_cast<AliTriggerClass*>(triggerClasses.FindObject(triggerClassName));
700
701 if (!triggerClass)
702 {
703 AliError(Form("Could not find triggerClass=%s",triggerClassName));
704 return 0x0;
705 }
706
707 Int_t nbcx = NumberOfInteractingBunches(*lhc);
708
709 if (nbcx <= 0 && ShouldCorrectForPileUp())
710 {
711 AliError("Could not get the number of bunches, so won't be able to correct for pile-up");
712 }
713
714 TIter nextScaler(scalerRecords);
715 AliTriggerScalersRecord* record;
716 UInt_t reft(0);
717
718 UInt_t refl0b[] = { 0, 0 };
719 UInt_t refl0a[] = { 0, 0 };
720
721 UInt_t l0b[] = { 0, 0 };
722 UInt_t l0a[] = { 0, 0 };
723
724 Bool_t first(kTRUE);
725
726 UChar_t classIndices[2];
727
728 // class 0 = class for luminomiter
729 // class 1 = class for livetime estimate
730 // or for PAC estimate if triggerClassNameForPACEstimate
731 // is given and triggerClass is the same as the lumi class
732
733 classIndices[0] = GetIndex(lumiTriggerClass->GetMask());
734 classIndices[1] = GetIndex(triggerClass->GetMask());
735
736 Bool_t sameClass = ( classIndices[0] == classIndices[1] );
737 Bool_t pacRemoval(kFALSE);
738
739 if ( sameClass && strlen(triggerClassNameForPACEstimate) > 0 )
740 {
741 AliTriggerClass* triggerClassForPACEstimate = static_cast<AliTriggerClass*>(triggerClasses.FindObject(triggerClassNameForPACEstimate));
742 if (!triggerClassForPACEstimate)
743 {
744 AliError(Form("Could not find triggerClassForPACEstimate=%s. Will not correct for PAC durations",triggerClassNameForPACEstimate));
745 return 0x0;
746 }
747 classIndices[1] = GetIndex(triggerClassForPACEstimate->GetMask());
748 sameClass = ( classIndices[0] == classIndices[1] );
749 if (!sameClass)
750 {
751 pacRemoval=kTRUE;
752 }
753 }
754
755 ULong64_t counter(0);
756
757 std::vector<Double_t> vseconds;
758 std::vector<Double_t> vlivetime;
759 std::vector<Double_t> vlumi;
760
761 while ( ( record = static_cast<AliTriggerScalersRecord*>(nextScaler()) ) )
762 {
763 const AliTimeStamp* ats = record->GetTimeStamp();
764
765 UInt_t seconds = ats->GetSeconds();// - TTimeStamp::GetZoneOffset();
766
767 TTimeStamp ts(seconds,ats->GetMicroSecs());
768
769 UInt_t timelapse = seconds - reft;
770
771 Bool_t ok = sameClass || CheckRecord(*record,classIndices[1],refl0b[1],refl0a[1],timelapse);
772
773 if (ok) reft = seconds;
774
775 for ( Int_t i = 0; i < 2; ++i )
776 {
777 const AliTriggerScalers* scaler = record->GetTriggerScalersForClass(classIndices[i]);
778
779 if (ok)
780 {
781 l0b[i] = scaler->GetLOCB() - refl0b[i];
782 }
783 else
784 {
785 l0b[i] = 0;
786 }
787 l0a[i] = scaler->GetLOCA() - refl0a[i];
788
789 refl0b[i] = scaler->GetLOCB();
790 refl0a[i] = scaler->GetLOCA();
791 }
792
793 if ( first )
794 {
795 first = kFALSE;
796 continue;
797 }
798
799 if ( ShouldCorrectForPileUp() && nbcx > 0 && l0b[0] > 0 )
800 {
801 Double_t mu = Mu(l0b[0]/timelapse,nbcx);
802 Double_t factor = mu/(1-TMath::Exp(-mu));
803
804 l0b[0] *= factor;
805 }
806
807 vseconds.push_back(seconds);
808
809 Double_t lt(1.0);
810
811 if ( ok && !sameClass && !pacRemoval )
812 {
813 lt = (l0a[1]*1.0)/l0b[1];
814 }
815
816 counter += l0b[0]*lt;
817
818 vlumi.push_back( counter / lumiTriggerCrossSection );
819
820 }
821
822 if ( vseconds.empty() ) return 0x0;
823
824 TGraph* g = new TGraph(vseconds.size(),&vseconds[0],&vlumi[0]);
825
826 TimeAxis(g);
827
828 return g;
829}
830
2f331ac9 831//______________________________________________________________________________
c665b011 832void AliAnalysisTriggerScalers::IntegratedLuminosity(const char* triggerList,
833 const char* lumiTrigger,
834 Double_t lumiCrossSection,
835 const char* csvOutputFile,
e538121a 836 const char sep,
837 const char* csUnit)
2f331ac9 838{
c665b011 839 // Compute the luminosity for a set of triggers
840
e538121a 841 // for T0 based lumi (end of pp 2012), use lumiTrigger = C0TVX-S-NOPF-ALLNOTRD and lumiCrossSection = 28 mb (and csUnit="nb")
c665b011 842 //
e538121a 843 // for T0 based lumi (pPb 2013), use lumiTrigger = C0TVX-B-NOPF-ALLNOTRD
58b19963 844 // and lumiCrossSection = 0.755*2000 mb (and csUnit="mub")
845
846 // for T0 based lumi (pp 2.76 TeV 2013), use lumiTrigger = C0TVX-B-NOPF-ALLNOTRD
847 // and lumiCrossSection = 18 mb (and csUnit="nb")
2f331ac9 848
849 double intLumi(0);
850
c665b011 851 std::map<std::string,float> lumiPerTrigger;
852 std::map<int, std::map<std::string,float> > lumiPerFillPerTrigger;
853
854 std::map<std::string,time_t> durationPerTrigger;
855
856 TString sTriggerList(triggerList);
857
858 if ( sTriggerList.Length()==0 )
859 {
58b19963 860 if ( lumiCrossSection < 30 && lumiCrossSection > 20 )
e538121a 861 {
862 // assuming it's pp 2012
863 sTriggerList = "CMUL8-S-NOPF-ALLNOTRD,CMUL7-S-NOPF-ALLNOTRD,CMUL8-S-NOPF-MUON,CMUL7-S-NOPF-MUON";
2f331ac9 864
c665b011 865 // for C0MUL-SC-NOPF-MUON must use C0TVX-SC as lumiTrigger (with same cross-section as C0TVX=28mb)
e538121a 866 }
58b19963 867 else if ( lumiCrossSection < 30 )
868 {
869 // assuming it's pp 2013
870 sTriggerList = "CMSL7-B-NOPF-MUON,CMSH7-B-NOPF-MUON,CMUL7-B-NOPF-MUON,CMSL7-B-NOPF-ALLNOTRD,CMSH7-B-NOPF-ALLNOTRD,CMUL7-B-NOPF-ALLNOTRD";
871 }
e538121a 872 else
873 {
874 sTriggerList = "CMSL7-B-NOPF-MUON,CMSH7-B-NOPF-MUON,CMUL7-B-NOPF-MUON,CMSL7-B-NOPF-ALLNOTRD,CMSH7-B-NOPF-ALLNOTRD,CMUL7-B-NOPF-ALLNOTRD";
875 }
c665b011 876 }
877
878 TObjArray* triggerArray = sTriggerList.Tokenize(",");
879 triggerArray->SetOwner(kTRUE);
880
881 std::ofstream* out(0x0);
882
883 if ( TString(csvOutputFile).Length() > 0 )
884 {
885 out = new std::ofstream(gSystem->ExpandPathName(csvOutputFile));
886 if (!out || out->bad())
887 {
888 delete out;
889 out = 0x0;
890 }
891 }
2f331ac9 892
c665b011 893 TIter nextTrigger(triggerArray);
894 TObjString* trigger;
2f331ac9 895
c665b011 896 if (out)
897 {
898 (*out) << "Fill number" << sep;
899
900 nextTrigger.Reset();
901
902 std::map<std::string,float>::const_iterator it;
903
904 while ( ( trigger = static_cast<TObjString*>(nextTrigger())))
2f331ac9 905 {
c665b011 906 lumiPerTrigger[trigger->String().Data()] = 0;
907 }
908
909 for ( it = lumiPerTrigger.begin(); it != lumiPerTrigger.end(); ++it )
910 {
911 (*out) << "lumi from " << it->first.c_str() << sep;
912 }
2f331ac9 913
c665b011 914 (*out) << "comments" << sep;
915
916 for ( it = lumiPerTrigger.begin(); it != lumiPerTrigger.end(); ++it )
917 {
918 (*out) << "recorded " << it->first.c_str() << " (integrated)" << sep;
919 }
2f331ac9 920
e538121a 921 (*out) << Form("LHC delivered (%s^-1) per fill ",csUnit)
922 << sep << Form("LHC delivered (%s^-1 integrated)",csUnit) << sep;
c665b011 923 (*out) << "lumi tot muon" << sep << "eff (%)" << sep;
924 (*out) << std::endl;
925
926 nextTrigger.Reset();
927 }
928
929 Int_t currentFillNumber(-1);
930 Int_t fillNumber(0);
931
e538121a 932 float csMult(1.0);
933 TString scsUnit(csUnit);
934 scsUnit.ToUpper();
935
936 if ( scsUnit=="PB" )
937 {
938 csMult=1E9;
939 }
940 else if (scsUnit=="NB")
941 {
942 csMult=1E6;
943 }
944 else if ( scsUnit=="UB" )
945 {
946 csMult=1E3;
947 }
948 else if ( scsUnit=="MB" )
949 {
950 csMult=1.0;
951 }
952 else
953 {
954 AliError(Form("Don't know how to deal with cross-section unit=%s",csUnit));
955 return;
956 }
957
958
c665b011 959 for ( std::vector<int>::size_type i = 0; i < fRunList.size(); ++i )
960 {
961 Int_t runNumber = fRunList[i];
962 Bool_t atLeastOneTriggerFound(kFALSE);
963
964 // find out which trigger classes to use
965
966 AliTriggerConfiguration* tc = static_cast<AliTriggerConfiguration*>(GetOCDBObject("GRP/CTP/Config",runNumber));
967 const TObjArray& trClasses = tc->GetClasses();
968
969 if (out)
970 {
971 fillNumber = GetFillNumberFromRunNumber(runNumber);
972 if ( fillNumber == 0 )
973 {
974 AliError(Form("Got fillNumber = 0 for run %09d !",runNumber));
975 }
2f331ac9 976
c665b011 977 if ( fillNumber != currentFillNumber )
2f331ac9 978 {
c665b011 979 std::map<std::string,float>::const_iterator it;
2f331ac9 980
c665b011 981 for ( it = lumiPerTrigger.begin(); it != lumiPerTrigger.end(); ++it )
2f331ac9 982 {
c665b011 983 lumiPerFillPerTrigger[fillNumber][it->first.c_str()] = 0;
2f331ac9 984 }
c665b011 985 currentFillNumber = fillNumber;
986 }
987 }
2f331ac9 988
e538121a 989 AliTriggerRunScalers* trs = static_cast<AliTriggerRunScalers*>(GetOCDBObject("GRP/CTP/Scalers",runNumber));
990 const TObjArray* scalers = trs->GetScalersRecords();
991 const AliTriggerScalersRecord* begin = (AliTriggerScalersRecord*)(scalers->First());
992 const AliTriggerScalersRecord* end = (AliTriggerScalersRecord*)(scalers->Last());
c665b011 993
e538121a 994 time_t duration = (end->GetTimeStamp()->GetBunchCross() - begin->GetTimeStamp()->GetBunchCross())*AliTimeStamp::fNanosecPerBC*1E-9;
995
c665b011 996 nextTrigger.Reset();
2f331ac9 997
e538121a 998 TString lumiTriggerClassName(lumiTrigger);
999 float lumiSigma = lumiCrossSection*csMult; //in csUnit
1000 AliAnalysisTriggerScalerItem* lumiB = GetTriggerScaler(runNumber,"L0B",lumiTriggerClassName.Data());
1001
58b19963 1002 if (!lumiB)
1003 {
1004 AliError(Form("Did not find lumiTrigger %s for run %09d",lumiTriggerClassName.Data(),runNumber));
1005 }
1006
e538121a 1007 Float_t pacCorrection(1.0);
1008
c665b011 1009 while ( ( trigger = static_cast<TObjString*>(nextTrigger()) ) )
1010 {
c665b011 1011 TString muTriggerClassName(trigger->String());
1012 Int_t n(0);
c665b011 1013
1014 if ( !trClasses.FindObject(muTriggerClassName.Data() ) )
1015 {
1016 continue;
1017 }
1018
1019 if ( muTriggerClassName.Contains("CMUL8") ) ++n;
1020 if ( muTriggerClassName.Contains("CMUL7") ) ++n;
1021
1022 if ( n>1 )
1023 {
1024 AliError(Form("More than 1 relevant trigger class found for run %09d ! Check that !",runNumber));
1025 trClasses.Print();
1026 continue;
1027 }
1028
c665b011 1029 AliAnalysisTriggerScalerItem* muonA = GetTriggerScaler(runNumber,"L0A",muTriggerClassName.Data());
1030 AliAnalysisTriggerScalerItem* muonB = GetTriggerScaler(runNumber,"L0B",muTriggerClassName.Data());
1031
58b19963 1032 if (!muonA || !muonB) continue;
c665b011 1033
1034 atLeastOneTriggerFound = kTRUE;
1035
1036 Float_t ratio(0);
1037
1038 if ( muonB->ValueCorrectedForDownscale() > 0 )
1039 {
1040 ratio = muonA->ValueCorrectedForDownscale()/muonB->ValueCorrectedForDownscale();
1041 }
1042
1043 ratio *= lumiB->ValueCorrectedForDownscale()/lumiSigma;
1044
1045 if ( muTriggerClassName.BeginsWith("CMUL"))
1046 {
1047 intLumi += ratio;
2f331ac9 1048 }
c665b011 1049
e538121a 1050 if ( muTriggerClassName.Contains("CMSH") )
1051 {
1052 pacCorrection = GetPauseAndConfigCorrection(runNumber,muTriggerClassName.Data());
1053 }
1054
c665b011 1055 lumiPerTrigger[muTriggerClassName.Data()] += ratio;
1056 durationPerTrigger[muTriggerClassName.Data()] += duration;
1057 lumiPerFillPerTrigger[currentFillNumber][muTriggerClassName.Data()] += ratio;
e538121a 1058
c665b011 1059 }
1060
e538121a 1061 lumiPerTrigger[lumiTriggerClassName.Data()] += lumiB->ValueCorrectedForDownscale()/lumiSigma;
1062 durationPerTrigger[lumiTriggerClassName.Data()] += duration;
1063 lumiPerFillPerTrigger[currentFillNumber][lumiTriggerClassName.Data()] += lumiB->ValueCorrectedForDownscale()/lumiSigma;
1064
1065 TString lumiPACCorrected(Form("%s(-PAC)",lumiTriggerClassName.Data()));
1066
1067 lumiPerTrigger[lumiPACCorrected.Data()] += pacCorrection*lumiB->ValueCorrectedForDownscale()/lumiSigma;
1068 durationPerTrigger[lumiPACCorrected.Data()] += duration;
1069 lumiPerFillPerTrigger[currentFillNumber][lumiPACCorrected.Data()] += pacCorrection*lumiB->ValueCorrectedForDownscale()/lumiSigma;
1070
c665b011 1071 if (!atLeastOneTriggerFound && sTriggerList.Contains("CMUL") )
1072 {
1073 AliError(Form("Found no relevant trigger for run %09d",runNumber));
2f331ac9 1074 }
c665b011 1075 }
1076
e538121a 1077 AliInfo(Form("Integrated lumi %7.4f %s^-1",intLumi,csUnit));
c665b011 1078
1079 std::map<std::string,float>::const_iterator it;
1080
1081 for ( it = lumiPerTrigger.begin(); it != lumiPerTrigger.end(); ++it )
1082 {
e538121a 1083 AliInfo(Form("Trigger %30s Lumi %10.4f %s^-1 duration %10ld s",it->first.c_str(),it->second,csUnit,durationPerTrigger[it->first]));
c665b011 1084 }
2f331ac9 1085
c665b011 1086 if (out)
1087 {
1088 std::map<int, std::map<std::string, float> >::const_iterator fit;
2f331ac9 1089
c665b011 1090 lumiPerTrigger.clear();
2f331ac9 1091
c665b011 1092 for ( fit = lumiPerFillPerTrigger.begin(); fit != lumiPerFillPerTrigger.end(); ++fit )
2f331ac9 1093 {
c665b011 1094 int fill = fit->first;
1095 std::map<std::string,float>::const_iterator tit;
1096 (*out) << fill << sep;
1097
1098 for ( tit = fit->second.begin(); tit != fit->second.end(); ++tit )
1099 {
1100 (*out) << Form("%e",tit->second) << sep;
1101 }
1102
1103 (*out) << sep; // comment (empty)
1104
1105 for ( tit = fit->second.begin(); tit != fit->second.end(); ++tit )
1106 {
1107 lumiPerTrigger[tit->first] += tit->second;
1108
1109 (*out) << Form("%e",lumiPerTrigger[tit->first]) << sep;
1110 }
1111 (*out) << sep << "0" << sep << "0" << sep << "0" << sep << "0" << sep << std::endl; // LHC per fill, LHC integrated, lumi tot muon , efficiency
2f331ac9 1112 }
c665b011 1113 }
09d5920f 1114 //
1115 delete triggerArray;
2f331ac9 1116}
1117
58b19963 1118//______________________________________________________________________________
1119TGraph* AliAnalysisTriggerScalers::MakeGraph(const std::vector<int>& vx,
1120 const std::vector<int>& vex,
1121 const std::vector<double>& vy,
1122 const std::vector<double>& vey)
1123{
1124 /// Build a graph from a set of stl vectors
1125
1126 if ( ! ( vx.size() == vex.size() && vx.size() == vy.size() && vx.size() == vey.size() ) )
1127 {
1128 std::cerr << "incompatible sizes" << std::endl;
1129 return 0x0;
1130 }
1131
1132 double* x = new double[vx.size()];
1133 double* ex = new double[vx.size()];
1134 double* y = new double[vx.size()];
1135 double* ey = new double[vx.size()];
1136
1137 for ( size_t i = 0; i < vx.size(); ++i )
1138 {
1139 x[i] = vx[i];
1140 ex[i] = vex[i];
1141 y[i] = vy[i];
1142 ey[i] = vey[i];
1143 }
1144
1145 TGraph* g = new TGraphErrors(vx.size(),x,y,ex,ey);
1146
1147 TimeAxis(g);
1148
1149 delete[] x;
1150 delete[] y;
1151 delete[] ex;
1152 delete[] ey;
1153
1154 return g;
1155}
1156
1157//______________________________________________________________________________
1158Int_t AliAnalysisTriggerScalers::NumberOfInteractingBunches(const AliLHCData& lhc) const
1159{
1160 /// Extract the number of colliding bunches from the LHC data
1161
1162 Int_t numberOfInteractingBunches(0);
1163 Int_t numberOfInteractingBunchesMeasured(0);
1164 Int_t nIBM2(0);
1165
1166 int beam1(0);
1167 int beam2(1);
1168
1169 AliLHCDipValI* val = lhc.GetBunchConfigDeclared(beam1,0);
1170
1171 for ( Int_t i = 0; i < val->GetSizeTotal(); ++i )
1172 {
1173 if ( val->GetValue(i) < 0 ) ++numberOfInteractingBunches;
1174 }
1175
1176 AliLHCDipValI* valm = lhc.GetBunchConfigMeasured(beam1,0);
1177
1178 for ( Int_t i = 0; i < valm->GetSizeTotal(); ++i )
1179 {
1180 if ( valm->GetValue(i) < 0 ) ++numberOfInteractingBunchesMeasured;
1181 }
1182
1183 valm = lhc.GetBunchConfigMeasured(beam2,0);
1184
1185 for ( Int_t i = 0; i < valm->GetSizeTotal(); ++i )
1186 {
1187 if ( valm->GetValue(i) <= 0 ) ++nIBM2;
1188 }
1189
1190 if ( numberOfInteractingBunches != numberOfInteractingBunchesMeasured ||
1191 numberOfInteractingBunches != nIBM2 )
1192 {
1193 AliWarning(Form("Got some different number of interacting bunches here ! NumberOfInteractingBunches=%3d NumberOfInteractingBunchesMeasured=%3d NIBM2=%3d",
1194 numberOfInteractingBunches,numberOfInteractingBunchesMeasured,nIBM2));
1195 }
1196
1197 return numberOfInteractingBunches;
1198}
1199
1200
1201//______________________________________________________________________________
1202TGraph* AliAnalysisTriggerScalers::PlotTrigger(const char* triggerClassName,
1203 const char* what)
1204{
1205 // Plot one of the scalers (L0A,L0B,L0AOVERB,etc...) of a given triggerClass
1206 // Get one value per run.
1207
1208 std::vector<Float_t> x;
1209 std::vector<Float_t> y;
1210
1211 double integral(0);
1212 double mean(0);
1213
1214 for ( std::vector<int>::size_type i = 0; i < fRunList.size(); ++i )
1215 {
1216 Int_t runNumber = fRunList[i];
1217
1218 AliAnalysisTriggerScalerItem* s = GetTriggerScaler(runNumber,what,triggerClassName);
1219
1220 if (!s) continue;
1221
1222 x.push_back(runNumber);
1223
1224 Double_t value = s->ValueCorrectedForDownscale();
1225
1226 if ( TString(what).Contains("RATE") )
1227 {
1228 value = s->Rate();
1229 }
1230
1231 integral += value;
1232 mean += value;
1233
1234 y.push_back(value);
1235 }
1236
1237 if ( fRunList.size() ) {
1238 mean /= fRunList.size();
1239 }
1240
1241 AliInfo(Form("Integral %e mean %e",integral,mean));
1242
1243 return new TGraph(x.size(),&x[0],&y[0]);
1244}
1245
2f331ac9 1246//______________________________________________________________________________
1247TGraph* AliAnalysisTriggerScalers::PlotTriggerEvolution(const char* triggerClassName,
1248 const char* what,
1249 bool draw,
e538121a 1250 double* mean,
1251 bool removeZeros)
2f331ac9 1252{
1253 /// Make a graph of "what" for a given trigger class.
1254 ///
1255 /// What can be :
1256 ///
1257 /// - L0B (level 0 before any veto applied)
1258 /// - L0A (level 0 after all vetoes)
1259 /// - L0AOVERB (L0A/L0B)
1260 /// - mu ( = -TMath::Log( 1 - P(0) ) where P(0) is the proba to have zero collisions in a bunch crossing)
1261 /// - pileupfactor = mu/(1-exp(-mu)) : the factor to apply to correct the cint1b count rate
1262 /// - vsnb = L0B/(NumberOfInteractingBunches*11245)
1263
c665b011 1264 TString swhat(what);
1265 swhat.ToUpper();
58b19963 1266
c665b011 1267 if ( swhat.Contains(";"))
1268 {
1269 swhat.ReplaceAll(";",",");
1270 AliWarningClass("; is not a valid separator, replaced it with ,");
1271 }
1272
1273 int color(1);
1274 int marker(20);
58b19963 1275
c665b011 1276 TObjArray* a = swhat.Tokenize(",");
1277 if (a->GetEntries()>1)
1278 {
1279 TObjArray graphs;
1280 TIter next(a);
1281 TObjString* str(0x0);
1282 Double_t ymin(TMath::Limits<Double_t>::Max());
1283 Double_t ymax(0);
1284 Double_t xmin(TMath::Limits<Double_t>::Max());
1285 Double_t xmax(0);
1286 TGraph* g(0x0);
1287
1288 while ( ( str = static_cast<TObjString*>(next())) )
1289 {
e538121a 1290 g = PlotTriggerEvolution(triggerClassName,str->String().Data(),false,0x0,removeZeros);
c665b011 1291 graphs.Add(g);
1292 for ( Int_t i = 0; i < g->GetN(); ++i )
1293 {
1294 ymin = TMath::Min(ymin,g->GetY()[i]);
1295 ymax = TMath::Max(ymax,g->GetY()[i]);
1296 }
1297 xmin = TMath::Min(xmin,g->GetX()[0]);
1298 xmax = TMath::Max(xmax,g->GetX()[g->GetN()-1]);
1299 }
1300
1301 gStyle->SetOptTitle(0);
1302
1303 AliInfoClass(Form("x %e ; %e y %e ; %e",xmin,xmax,ymin,ymax));
1304 TH2* h = new TH2F("h",triggerClassName,100,xmin,xmax,100,ymin,ymax);
1305 h->SetStats(kFALSE);
1306 h->GetXaxis()->SetTimeDisplay(1);
1307 h->GetXaxis()->SetTimeFormat("%d/%m %H:%M");
1308 h->GetXaxis()->SetTimeOffset(0,"gmt");
1309 h->GetXaxis()->SetNdivisions(505);
1310 h->Draw();
58b19963 1311
c665b011 1312 TIter nextGraph(&graphs);
1313
1314 while ( ( g = static_cast<TGraph*>(nextGraph())) )
1315 {
1316 AliInfoClass(g->GetTitle());
1317 g->Draw("lp");
1318 g->SetLineColor(color);
1319 g->SetMarkerColor(color);
1320 g->SetMarkerStyle(marker);
1321 ++color;
1322 ++marker;
1323 }
09d5920f 1324 delete a;
c665b011 1325 return 0x0;
1326 }
09d5920f 1327 delete a;
58b19963 1328
2f331ac9 1329 std::vector<int> vx;
1330 std::vector<int> vex;
1331 std::vector<double> vy;
1332 std::vector<double> vey;
1333
2f331ac9 1334
1335 if (mean) *mean=0;
1336 double nvalues(0);
1337
2f331ac9 1338 for ( std::vector<int>::size_type iRun = 0; iRun < fRunList.size(); ++iRun )
1339 {
1340 Int_t runNumber = fRunList[iRun];
1341
58b19963 1342 AliTriggerConfiguration* tc(0x0);
1343 AliTriggerRunScalers* trs(0x0);
1344 AliLHCData* lhc(0x0);
2f331ac9 1345
58b19963 1346 GetCTPObjects(runNumber,tc,trs,lhc);
2f331ac9 1347
58b19963 1348 Int_t numberOfInteractingBunches = NumberOfInteractingBunches(*lhc);
2f331ac9 1349
1350 const TObjArray* scalers = trs->GetScalersRecords();
1351
1352 const TObjArray& trClasses = tc->GetClasses();
1353 TIter next(&trClasses);
1354 AliTriggerClass* triggerClass;
1355
1356 while ( ( triggerClass = static_cast<AliTriggerClass*>(next()) ) )
1357 {
1358 UChar_t index = GetIndex(triggerClass->GetMask());
1359
1360 if ( !TString(triggerClass->GetName()).Contains(triggerClassName) ) continue;
1361
1362 TIter nextScaler(scalers);
1363 AliTriggerScalersRecord* record;
1364 UInt_t reft(0);
1365 UInt_t refl0b(0);
1366 UInt_t refl1b(0);
1367 UInt_t refl2b(0);
1368 UInt_t refl0a(0);
1369 UInt_t refl1a(0);
1370 UInt_t refl2a(0);
1371 Bool_t first(kTRUE);
1372
1373 while ( ( record = static_cast<AliTriggerScalersRecord*>(nextScaler()) ) )
1374 {
1375 const AliTriggerScalers* scaler = record->GetTriggerScalersForClass(index);
1376
e538121a 1377
2f331ac9 1378 const AliTimeStamp* ats = record->GetTimeStamp();
1379
1380 UInt_t seconds = ats->GetSeconds();// - TTimeStamp::GetZoneOffset();
1381
1382 TTimeStamp ts(seconds,ats->GetMicroSecs());
1383
1384 UInt_t l0b = scaler->GetLOCB() - refl0b;
1385 UInt_t l0a = scaler->GetLOCA() - refl0a;
1386 UInt_t l1b = scaler->GetL1CB() - refl1b;
1387 UInt_t l1a = scaler->GetL1CA() - refl1a;
1388 UInt_t l2b = scaler->GetL2CB() - refl2b;
1389 UInt_t l2a = scaler->GetL2CA() - refl2a;
1390 UInt_t timelapse = seconds - reft;
58b19963 1391
2f331ac9 1392 if ( l0b <= 2 || ( l0a <= 2 && l0a != 0 ) || timelapse <= 9 ) continue;
1393
1394 reft = seconds;
1395 refl0b = scaler->GetLOCB();
1396 refl0a = scaler->GetLOCA();
1397 refl1b = scaler->GetL1CB();
1398 refl1a = scaler->GetL1CA();
1399 refl2b = scaler->GetL2CB();
1400 refl2a = scaler->GetL2CA();
1401
1402 if ( first )
1403 {
1404 first = kFALSE;
1405 continue;
1406 }
1407
1408 double value(1.0);
e538121a 1409 double error(0.0);
2f331ac9 1410
1411 if (swhat.Contains("L0AOVERB") )
1412 {
1413 value = l0a*1.0/l0b;
b2f6b613 1414 if ( l0a > 0 )
1415 {
1416 error = value*TMath::Sqrt(1.0/l0b+1.0/l0a);
1417 }
1418 else
1419 {
1420 error = 0.0;
1421 }
2f331ac9 1422 }
1423 else if ( swhat.Contains("L0B") )
1424 {
1425 value = l0b;
1426 }
1427 else if (swhat.Contains("L0A") )
1428 {
1429 value = l0a;
1430 }
1431 else if ( swhat.Contains("L1B") )
1432 {
1433 value = l1b;
1434 }
1435 else if (swhat.Contains("L1A") )
1436 {
1437 value = l1a;
1438 }
1439 else if ( swhat.Contains("L2B") )
1440 {
1441 value = l2b;
1442 }
1443 else if (swhat.Contains("L2A") )
1444 {
1445 value = l2a;
1446 }
1447 else if ( swhat.Contains("MU") )
1448 {
e538121a 1449 value = Mu(l0b/timelapse,numberOfInteractingBunches);
58b19963 1450 error = 0.0; // FIXME
2f331ac9 1451 }
1452 else if ( swhat.Contains("PILEUPFACTOR") )
1453 {
e538121a 1454 Double_t mu = Mu(l0b/timelapse,numberOfInteractingBunches);
2f331ac9 1455 value = mu/(1-TMath::Exp(-mu));
58b19963 1456 error = -1.0; // FIXME
2f331ac9 1457 }
1458 else if ( swhat.Contains("VSNB") )
1459 {
e538121a 1460 value = l0b/(11245.0*numberOfInteractingBunches);
58b19963 1461 error = -1.0; // FIXME
2f331ac9 1462 }
1463 else
1464 {
1465 value = timelapse;
1466 AliInfo(Form("Unknown what %s",what));
1467 }
1468
1469 if ( ! swhat.Contains("OVER") && ! swhat.Contains("RATIO") &&
c665b011 1470 ! swhat.Contains("MU") && ! swhat.Contains("PILEUPFACTOR") &&
1471 ! swhat.Contains("RAW") )
2f331ac9 1472 {
1473 value /= timelapse;
1474 }
1475
1476 if ( !TMath::Finite(value) ) continue;
1477
58b19963 1478 if ( !swhat.Contains("L0AOVERB") && error > 0 )
e538121a 1479 {
1480 error = value >0 ? 1.0/TMath::Sqrt(value) : 0.0;
1481 }
58b19963 1482
e538121a 1483 if (removeZeros && TMath::Abs(value) < 1E-6 )
1484 {
58b19963 1485 continue;
e538121a 1486 }
2f331ac9 1487 if (mean)
1488 {
1489 (*mean) += value;
e538121a 1490 nvalues += 1.0;
2f331ac9 1491 }
1492
1493 vx.push_back(seconds);
e538121a 1494 vex.push_back(1.0);
2f331ac9 1495
1496 vy.push_back(value);
1497
e538121a 1498 vey.push_back(error);
2f331ac9 1499
1500 }
e538121a 1501
2f331ac9 1502 }
1503
2f331ac9 1504 }
58b19963 1505
e538121a 1506 if (mean && nvalues)
1507 {
1508 (*mean) /= nvalues;
1509 }
1510
c665b011 1511 if ( vx.empty() ) return 0;
2f331ac9 1512
1513 TGraph* g = MakeGraph(vx,vex,vy,vey);
1514 TString title(Form("TriggerEvolution%s-%s",triggerClassName,swhat.Data()));
1515
1516 g->SetName(title.Data());
1517 g->SetTitle(title.Data());
1518
1519 g->GetYaxis()->SetTitle(title.Data());
1520
1521 if (draw)
1522 {
e538121a 1523 TCanvas* c = NewCanvas(g->GetName());
c665b011 1524 g->SetLineColor(color);
1525 g->SetMarkerColor(color);
1526 g->SetMarkerStyle(marker);
1527 g->Draw("ALP");
e538121a 1528 c->SaveAs(Form("%s.png",title.Data()));
2f331ac9 1529 }
1530
1531
1532 return g;
1533}
1534
2f331ac9 1535//______________________________________________________________________________
1536TGraph* AliAnalysisTriggerScalers::PlotTriggerRatio(const char* triggerClassName1,
1537 const char* what1,
1538 const char* triggerClassName2,
1539 const char* what2)
1540{
e538121a 1541 // Plot the ratio of two scalers.
1542 // Get one value per run.
1543
2f331ac9 1544 std::vector<Float_t> x;
1545 std::vector<Float_t> y;
1546
1547 for ( std::vector<int>::size_type i = 0; i < fRunList.size(); ++i )
1548 {
1549 Int_t runNumber = fRunList[i];
1550
1551 AliAnalysisTriggerScalerItem* s1 = GetTriggerScaler(runNumber,what1,triggerClassName1);
1552 AliAnalysisTriggerScalerItem* s2 = GetTriggerScaler(runNumber,what2,triggerClassName2);
1553
1554 if (!s1 || !s2) continue;
1555
1556 x.push_back(runNumber);
1557
1558 Float_t ratio(0);
1559
1560 if ( s2->ValueCorrectedForDownscale() > 0 )
1561 {
1562 ratio = s1->ValueCorrectedForDownscale()/s2->ValueCorrectedForDownscale();
1563 }
1564
1565 y.push_back(ratio);
1566
58b19963 1567 AliDebug(1,Form("RUN %09d %20s (%s) %12llu (%5d) %20s (%s) %12llu (%5d) R %7.2f",
2f331ac9 1568 runNumber,
1569 triggerClassName1,what1,
1570 s1->Value(),s1->DownscalingFactor(),
1571 triggerClassName2,what2,
1572 s2->Value(),s2->DownscalingFactor(),
1573 ratio));
2f331ac9 1574 }
1575
1576 return new TGraph(x.size(),&x[0],&y[0]);
1577}
1578
58b19963 1579//______________________________________________________________________________
1580TGraph* AliAnalysisTriggerScalers::PlotTriggerRatioEvolution(const char* triggerClassName1,
1581 const char* what1,
1582 const char* triggerClassName2,
1583 const char* what2)
1584{
1585 /// Plots the evolution of one trigger ratio
1586
1587 TGraph* g1 = PlotTriggerEvolution(triggerClassName1,what1,kFALSE);
1588 TGraph* g2 = PlotTriggerEvolution(triggerClassName2,what2,kFALSE);
1589
1590 if (!g1 || !g2) return 0x0;
1591
1592 if ( g1->GetN() != g2->GetN() )
1593 {
1594 AliError("Oups. Did not get the same number of points for the 2 graphs ?!");
1595 return 0x0;
1596 }
1597
1598 Double_t x1,x2;
1599 Double_t y1,y2;
1600 Double_t x1err,x2err;
1601 Double_t y1err,y2err;
1602
1603 TGraphErrors* g = new TGraphErrors(g1->GetN());
1604 Int_t j(0);
1605
1606 for ( Int_t i = 0; i < g1->GetN(); ++i )
1607 {
1608 g1->GetPoint(i,x1,y1);
1609 g2->GetPoint(i,x2,y2);
1610
1611 x1err = g1->GetErrorX(i);
1612 x2err = g2->GetErrorX(i);
1613
1614 y1err = g1->GetErrorY(i);
1615 y2err = g2->GetErrorY(i);
1616
1617 if (x1!=x2)
1618 {
1619 AliError(Form("Points at %d don't have the same x ! ",i));
1620 continue;
1621 }
1622
1623 Double_t y(0.0);
1624
1625 if ( TMath::Abs(y2) > 1E-12 )
1626 {
1627 y = y1/y2;
1628 }
1629
1630 Double_t yerr(0.0);
1631
1632 if ( TMath::Abs(x1) > 1E-12)
1633 {
1634 yerr += TMath::Sqrt(x1err*x1err/(x1*x1));
1635 }
1636
1637 if ( TMath::Abs(x2) > 1E-12)
1638 {
1639 yerr += TMath::Sqrt(x2err*x2err/(x2*x2));
1640 }
1641
1642 yerr *= y;
1643
1644 g->SetPoint(j,x1,y);
1645 g->SetPointError(j,x1err,yerr);
1646
1647 ++j;
1648 }
1649
1650 delete g1;
1651 delete g2;
1652
1653 TimeAxis(g);
1654
1655 return g;
1656}
1657
2f331ac9 1658//______________________________________________________________________________
c665b011 1659void AliAnalysisTriggerScalers::Print(Option_t* /* opt */) const
1660{
1661 /// print our runlist
1662 AliAnalysisTriggerScalers::PrintIntegers(fRunList,',');
1663}
1664
1665//______________________________________________________________________________
1666void AliAnalysisTriggerScalers::PrintIntegers(const std::vector<int>& integers,
2f331ac9 1667 const char sep,
1668 std::ostream& out)
1669{
1670 /// print a list of integers
1671 for ( std::vector<int>::size_type i = 0; i < integers.size(); ++i )
1672 {
1673 out << integers[i] << sep;
1674 }
1675 out << std::endl;
1676}
1677
1678//______________________________________________________________________________
1679void AliAnalysisTriggerScalers::ReadIntegers(const char* filename,
1680 std::vector<int>& integers,
1681 Bool_t resetVector)
1682{
1683 /// Read integers from filename, where integers are either
1684 /// separated by "," or by return carriage
1685 std::ifstream in(gSystem->ExpandPathName(filename));
1686 int i;
1687
1688 std::set<int> runset;
1689
1690 if (!resetVector)
1691 {
1692 for ( std::vector<int>::size_type j = 0; j < integers.size(); ++ j )
1693 {
1694 runset.insert(integers[j]);
1695 }
1696 }
1697
1698 char line[10000];
1699
1700 in.getline(line,10000,'\n');
1701
1702 TString sline(line);
1703
1704 if (sline.Contains(","))
1705 {
1706 TObjArray* a = sline.Tokenize(",");
1707 TIter next(a);
1708 TObjString* s;
1709 while ( ( s = static_cast<TObjString*>(next()) ) )
1710 {
1711 runset.insert(s->String().Atoi());
1712 }
1713 delete a;
1714 }
1715 else
1716 {
1717 runset.insert(sline.Atoi());
1718
1719 while ( in >> i )
1720 {
1721 runset.insert(i);
1722 }
1723 }
1724
1725 integers.clear();
1726
1727 for ( std::set<int>::const_iterator it = runset.begin(); it != runset.end(); ++it )
1728 {
1729 integers.push_back((*it));
1730 }
1731
1732 std::sort(integers.begin(),integers.end());
1733}
1734
1735
1736//______________________________________________________________________________
1737void AliAnalysisTriggerScalers::SetRunList(Int_t runNumber)
1738{
1739 // Make the runlist be a single run
1740 fRunList.clear();
1741 fRunList.push_back(runNumber);
1742}
1743
e538121a 1744//______________________________________________________________________________
1745void AliAnalysisTriggerScalers::SetRunList(const std::vector<int>& runs)
1746{
1747 // Make the runlist be a single run
1748 fRunList = runs;
1749}
1750
1751//______________________________________________________________________________
1752void AliAnalysisTriggerScalers::SetRunList(const std::set<int>& runs)
1753{
1754 // Make the runlist be a single run
1755 fRunList.clear();
1756 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
1757 {
1758 fRunList.push_back(*it);
1759 }
1760}
1761
2f331ac9 1762//______________________________________________________________________________
1763void AliAnalysisTriggerScalers::SetRunList(const char* runlist)
1764{
1765 // Read the runlist from an ASCII file or a comma separated list
1766 // or a space separated list
1767
1768 fRunList.clear();
1769
1770 if ( TString(runlist).Contains(",") || TString(runlist).Contains(" ") )
1771 {
1772 TObjArray* runs = 0x0;
1773 if ( TString(runlist).Contains(",") )
1774 {
1775 runs = TString(runlist).Tokenize(",");
1776 }
1777 else
1778 {
1779 runs = TString(runlist).Tokenize(" ");
1780 }
1781 TIter next(runs);
1782 TObjString* s;
1783 std::set<int> runset;
1784
1785 while ( ( s = static_cast<TObjString*>(next()) ) )
1786 {
1787 runset.insert(s->String().Atoi());
1788 }
1789
1790 for ( std::set<int>::const_iterator it = runset.begin(); it != runset.end(); ++it )
1791 {
1792 fRunList.push_back((*it));
1793 }
1794
1795 std::sort(fRunList.begin(),fRunList.end());
1796
1797 delete runs;
1798 }
1799 else
1800 {
1801 ReadIntegers(runlist,fRunList);
1802 }
1803}
1804
1805//______________________________________________________________________________
1806//______________________________________________________________________________
1807//______________________________________________________________________________
1808//______________________________________________________________________________
1809//______________________________________________________________________________
1810//______________________________________________________________________________
1811//______________________________________________________________________________
1812
1813ClassImp(AliAnalysisTriggerScalerItem)
1814
1815//______________________________________________________________________________
1816const char*
1817AliAnalysisTriggerScalerItem::BCMaskName() const
e538121a 1818{
1819 // return bc mask name
2f331ac9 1820 if ( BCMask() ) return BCMask()->GetName(); else return "";
1821}
1822
1823//______________________________________________________________________________
1824Int_t AliAnalysisTriggerScalerItem::Compare(const TObject* obj) const
1825{
e538121a 1826 /// compare two scaler items (by means of their run number only)
2f331ac9 1827 const AliAnalysisTriggerScalerItem* s = static_cast<const AliAnalysisTriggerScalerItem*>(obj);
1828
1829 if ( s->RunNumber() < RunNumber() )
1830 {
1831 return -1;
1832 }
1833 else if ( s->RunNumber() > RunNumber() )
1834 {
1835 return 1;
1836 }
1837 return 0;
1838}
1839
1840//______________________________________________________________________________
1841void AliAnalysisTriggerScalerItem::Print(Option_t* opt) const
1842{
e538121a 1843 /// Printout
2f331ac9 1844 TString sopt(opt);
1845
1846 if ( RunNumber() > 0 )
1847 {
1848 sopt.ToUpper();
1849
1850 if ( sopt.Contains("FULL") )
1851 {
1852 }
1853 else
1854 {
1855 std::cout << Form("RUN %6d CLASS %24s (%5s %4d BCs) SCALER %s %12llu DS %6d DURATION %ld",
1856 RunNumber(),TriggerClassName(),
1857 BCMaskName(),
1858 BCMask() ? BCMask()->GetNUnmaskedBCs() : 0,
1859 Level(),
1860 Value(),DownscalingFactor(),Duration()) << std::endl;
1861 }
1862 }
1863 else
1864 {
1865 std::cout << Form("CLASS %24s SCALER %20llu NRUNS %d",
1866 TriggerClassName(),Value(),NofRuns()) << std::endl;
1867 }
1868}