]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/AliQADataMaker.cxx
Changes in QA to be able to process separately different triggers (Ruben)
[u/mrichter/AliRoot.git] / STEER / AliQADataMaker.cxx
CommitLineData
421ab0fb 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
17/* $Id$ */
18
202374b1 19//
20// Base Class
21// Produces the data needed to calculate the quality assurance.
22// All data must be mergeable objects.
23// Y. Schutz CERN July 2007
24//
421ab0fb 25
26// --- ROOT system ---
eca4fa66 27#include <TROOT.h>
421ab0fb 28#include <TSystem.h>
29#include <TFile.h>
6c18591a 30#include <TList.h>
d76c31f4 31#include <TTree.h>
d5cf81bd 32#include <TClonesArray.h>
a2b64fbd 33#include <TParameter.h>
57acd2d2 34#include <TH1K.h>
35#include <TH2C.h>
92664bc8 36#include <TH2F.h>
57acd2d2 37#include <TH2F.h>
38#include <TH2I.h>
39#include <TH3C.h>
92664bc8 40#include <TH3F.h>
57acd2d2 41#include <TH3F.h>
42#include <TH3I.h>
43#include <TH3S.h>
92664bc8 44#include <TArrayI.h>
45#include <TPRegexp.h>
421ab0fb 46// --- Standard library ---
47
48// --- AliRoot header files ---
49#include "AliLog.h"
2e42b4d4 50#include "AliQADataMaker.h"
51#include "AliQAChecker.h"
d76c31f4 52#include "AliESDEvent.h"
d5cf81bd 53#include "AliRawReader.h"
5e232cd6 54#include "AliDetectorRecoParam.h"
55
421ab0fb 56
2e42b4d4 57ClassImp(AliQADataMaker)
92664bc8 58
59const Char_t* AliQADataMaker::fgkTriggerPrefix = "_$TR$_";
60TObjArray* AliQADataMaker::fgCloningRequest = 0;
61TObjArray* AliQADataMaker::fgTrigClasses = 0;
62TObjArray AliQADataMaker::fgEventTrigClasses;
63
421ab0fb 64//____________________________________________________________________________
fec0891b 65AliQADataMaker::AliQADataMaker(const Char_t * name, const Char_t * title) :
421ab0fb 66 TNamed(name, title),
67 fOutput(0x0),
6c18591a 68 fDetectorDir(0x0),
312e6f8d 69 fDetectorDirName(""),
930e6e3e 70 fCurrentCycle(0),
5b188f2f 71 fCycle(9999999),
72 fCycleCounter(0),
b1af1125 73 fWriteExpert(kFALSE),
57acd2d2 74 fParameterList(new TList*[AliRecoParam::kNSpecies]),
75 fRun(0),
71f27f1f 76 fEventSpecie(AliRecoParam::kDefault),
6252ceeb 77 fDigitsArray(NULL)
421ab0fb 78{
79 // ctor
421ab0fb 80 fDetectorDirName = GetName() ;
92664bc8 81 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
82 fParameterList[specie] = NULL ;
83 fEvCountCycle[specie].Set(AliQAv1::kNTASKINDEX);
84 fEvCountTotal[specie].Set(AliQAv1::kNTASKINDEX);
85 }
86
421ab0fb 87}
88
89//____________________________________________________________________________
2e42b4d4 90AliQADataMaker::AliQADataMaker(const AliQADataMaker& qadm) :
421ab0fb 91 TNamed(qadm.GetName(), qadm.GetTitle()),
92 fOutput(qadm.fOutput),
6c18591a 93 fDetectorDir(qadm.fDetectorDir),
312e6f8d 94 fDetectorDirName(qadm.fDetectorDirName),
5b188f2f 95 fCurrentCycle(qadm.fCurrentCycle),
96 fCycle(qadm.fCycle),
97 fCycleCounter(qadm.fCycleCounter),
b1af1125 98 fWriteExpert(qadm.fWriteExpert),
a2b64fbd 99 fParameterList(qadm.fParameterList),
57acd2d2 100 fRun(qadm.fRun),
634696f5 101 fEventSpecie(qadm.fEventSpecie),
6252ceeb 102 fDigitsArray(NULL)
421ab0fb 103{
104 //copy ctor
105 fDetectorDirName = GetName() ;
eca4fa66 106 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
107 fParameterList[specie] = qadm.fParameterList[specie] ;
92664bc8 108 fEvCountCycle[specie] = qadm.fEvCountCycle[specie];
109 fEvCountTotal[specie] = qadm.fEvCountTotal[specie];
110 // fImage[specie] = qadm.fImage[specie] ;
eca4fa66 111 }
421ab0fb 112}
113
71f27f1f 114//____________________________________________________________________________
115AliQADataMaker::~AliQADataMaker()
116{
117 for (Int_t esIndex = 0 ; esIndex < AliRecoParam::kNSpecies ; esIndex++) {
71f27f1f 118 if (fParameterList[esIndex] )
119 delete fParameterList[esIndex] ;
120 }
71f27f1f 121 delete[] fParameterList ;
6252ceeb 122 if (fDigitsArray) {
123 fDigitsArray->Clear() ;
124 delete fDigitsArray ;
125 }
71f27f1f 126}
127
ba7aca7d 128//____________________________________________________________________________
7d297381 129Int_t AliQADataMaker::Add2List(TH1 * hist, const Int_t index, TObjArray ** list, const Bool_t expert, const Bool_t image, const Bool_t saveForCorr)
ba7aca7d 130{
92664bc8 131 // Set histograms memory resident and add to the list
132 // Maximm allowed is 10000
57acd2d2 133
134 Int_t rv = -1 ;
135 TClass * classType = hist->Class() ;
136 TString className(classType->GetName()) ;
137 if( ! className.BeginsWith("T") && ! classType->InheritsFrom("TH1") ) {
138 AliError(Form("QA data Object must be a generic ROOT object and derive fom TH1 and not %s", className.Data())) ;
92664bc8 139 } else if ( index > AliQAv1::GetMaxQAObj() ) {
140 AliError(Form("Max number of authorized QA objects is %d", AliQAv1::GetMaxQAObj())) ;
eca4fa66 141 } else {
92664bc8 142 hist->SetDirectory(0);
750730d8 143 if (expert)
7d297381 144 hist->SetBit(AliQAv1::GetExpertBit()) ;
145 if (image)
146 hist->SetBit(AliQAv1::GetImageBit()) ;
eca4fa66 147 const Char_t * name = Form("%s_%s", AliRecoParam::GetEventSpecieName(fEventSpecie), hist->GetName()) ;
148 hist->SetName(name) ;
149 if(saveForCorr) {
150 const Char_t * cname = Form("%s_%s", list[AliRecoParam::AConvert(AliRecoParam::kDefault)]->GetName(), hist->GetName()) ;
151 TParameter<double> * p = new TParameter<double>(cname, 9999.9999) ;
152 if ( fParameterList[AliRecoParam::AConvert(fEventSpecie)] == NULL )
153 fParameterList[AliRecoParam::AConvert(fEventSpecie)] = new TList() ;
154 fParameterList[AliRecoParam::AConvert(fEventSpecie)]->Add(p) ;
a2b64fbd 155 }
8db8be00 156 TObject* old = list[AliRecoParam::AConvert(fEventSpecie)]->At(index);
157 if (old) {
158 AliError(Form("%s - OUPS ! Already got an object (%p,%s) for index=%d => will most probably get a memory leak by replacing it with (%p,%s) !",
159 GetName(),old,old->GetName(),index,hist,hist->GetName()));
160 }
eca4fa66 161 list[AliRecoParam::AConvert(fEventSpecie)]->AddAtAndExpand(hist, index) ;
162 rv = list[AliRecoParam::AConvert(fEventSpecie)]->GetLast() ;
a2b64fbd 163 }
57acd2d2 164 return rv ;
165}
166
92664bc8 167//____________________________________________________________________________
168void AliQADataMaker::ClonePerTrigClassL(TObjArray ** list, AliQAv1::TASKINDEX_t task)
169{
170 // scan the histos of the list, match them to requested histo names to be
171 // cloned and create the clones per trigger class
172 int spec = AliRecoParam::AConvert(fEventSpecie);
173 if (!fgCloningRequest || !GetNTrigClasses()) return;
174 if (!list || !list[spec]) {
175 AliDebug(1,Form("Array for %s specie is not created",AliRecoParam::GetEventSpecieName(fEventSpecie)));
176 return;
177 }
178 //
179 // if the counters were not expanded, do this now
180 if (fEvCountCycle[spec].GetSize()==AliQAv1::kNTASKINDEX) {
181 fEvCountCycle[spec].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
182 fEvCountTotal[spec].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
183 }
184 //
185
186 TString prefix = Form("%s/%s/",GetName(),AliQAv1::GetTaskName(task).Data()); // take care of requests with this prefix
187 int prefLgt = prefix.Length();
188 //
189 for (int ir=fgCloningRequest->GetEntriesFast();ir--;) {
190 TNamed* rec = dynamic_cast<TNamed*>(fgCloningRequest->At(ir));
191 if (!rec) continue;
192 TString hfname = rec->GetName(); // histogram names
193 if (!hfname.BeginsWith(prefix)) continue;
194 Bool_t keepOrig = rec->TestBit(AliQAv1::GetOrigHistoKeptBit()); // is original to be kept?
195 ClonePerTrigClassA(list[spec], hfname.Data()+prefLgt, rec->GetTitle(), keepOrig);
196 }
197 //
198}
199
200//____________________________________________________________________________
201Int_t AliQADataMaker::ClonePerTrigClassA(TObjArray * list, const char* hnm, const char* triggers, Bool_t keepOriginal)
202{
203 // substitute the matching histogram by the TObjArray containing clones of
204 // original histogram for each trigger from the space-separated tiggers string
205 // When keepOriginal is requested, the original histo is not deleted and filled for each trigger
206 if (!list) return 0;
207 int nh = list->GetEntriesFast();
208 if (!nh) return 0;
209 //
210 AliDebug(AliQAv1::GetQADebugLevel(),Form("Cloning histogram %s for triggers %s in array %s",hnm,triggers,list->GetName()));
211 //
212 TString trigStr = triggers;
213 TObjArray* trigArr = trigStr.Tokenize(" ");
214 int nTrigs = trigArr->GetEntriesFast();
215 Bool_t cloneAll=kFALSE, cloneMany=kFALSE;
216 if (!nTrigs) {
217 AliError(Form("Triggers string supplied for histo %s is empty", hnm));
218 delete trigArr;
219 return 0;
220 }
221 // match the trigger class id to selected aliases
222 for (int i=nTrigs;i--;) {
223 TObject* alias = fgTrigClasses->FindObject( trigArr->At(i)->GetName() );
224 if (!alias) {
225 AliError(Form("Cloning for undefined trigger class %s was requested for histogram %s",trigArr->At(i)->GetName(),hnm));
226 delete trigArr->RemoveAt(i);
227 trigArr->Compress();
228 continue;
229 }
230 trigArr->At(i)->SetUniqueID( alias->GetUniqueID() );
231 }
232 //
233 TString histPatt = hnm;
234 if (histPatt == "*") {
235 cloneAll = kTRUE;
236 cloneMany = kTRUE;
237 }
238 else {
239 histPatt.Prepend(Form("%s_", AliRecoParam::GetEventSpecieName(fEventSpecie)));
240 //
241 // The histogram name may contain %d formats for histos created in loop.
242 // Then we expect more than 1 histo matching to name
243 TPRegexp rgx("%\\d*d");
244 if (histPatt.Contains(rgx)) { // need to convert to perl expression, make sure there are no perl special characters
245 const char *specials = "^$.{}[]*+?\\";
246 for (int i=strlen(specials);i--;) histPatt.ReplaceAll(specials+i,1,Form("\\%c",specials[i]),2);
247 rgx.Substitute(histPatt,"\\d+","g");
248 histPatt.Prepend('^'); histPatt += "$";
249 cloneMany = kTRUE;
250 }
251 }
252 //
253 int nCloned = 0;
254 for (int ih=0;ih<nh;ih++) {
255 TH1* hist = (TH1*)list->At(ih);
256 if (!hist) continue;
257 if (!cloneAll) {
258 TString hname = hist->GetName();
259 if (cloneMany) {
260 TPRegexp patPR(histPatt);
261 if ( !hname.Contains(patPR) ) continue;
262 }
263 else {
264 if ( !hname.Contains(histPatt) ) continue;
265 }
266 }
267 //
268 // histo name matches, clone it
269 nCloned += ClonePerTrigClassH(ih, list, trigArr, keepOriginal);
270 if (!cloneMany) break; // no wildcards, just one histo is expected
271 }
272 //
273 delete trigArr;
274 return nCloned;
275}
276
277//____________________________________________________________________________
278Int_t AliQADataMaker::ClonePerTrigClassH(Int_t index, TObjArray* list, TObjArray* trigArr, Bool_t keepOriginal)
279{
280 // substitute the histogram at position index by the TObjArray containing clones of
281 // original histogram for each trigger from the trigArr
282 // When keepOriginal is requested, the original histo is not deleted and filled for each trigger
283 TH1* hist = (TH1*) list->At(index);
284 if (!hist) return 0; // should never happen, checked in calling method
285
286 if (IsCloningForbidden(hist)) {
287 AliError(Form("Cloning per trigger is forbidden for histo %s at slot %d",hist->GetName(),index));
288 return 0;
289 }
290 //
291 if (hist->TestBit(AliQAv1::GetClonedBit())) {
292 AliError(Form("histo %s at slot %d was already cloned!",((TObjArray*)hist)->GetName(),index));
293 return 0;
294 }
295 //
296 int nTrigs = trigArr->GetEntriesFast();
297 TObjArray* clonesArr = new TObjArray(GetNTrigClasses()+keepOriginal);
298 // transfer the user bits of the histo to be cloned to array
299 for (int ib=14;ib<=23;ib++) if (hist->TestBit(1<<ib)) clonesArr->SetBit(1<<ib);
300 //
301 if (keepOriginal) {
302 clonesArr->AddAt(hist,GetNTrigClasses());
303 clonesArr->SetBit(AliQAv1::GetOrigHistoKeptBit());
304 }
305 clonesArr->SetBit(AliQAv1::GetClonedBit());
306 clonesArr->SetName(hist->GetName());
307 for (int itr=0;itr<nTrigs;itr++) {
308 TObject* trigClass = trigArr->At(itr);
309 TH1* hclone = (TH1*)hist->Clone(Form("%s%s%s",hist->GetName(), fgkTriggerPrefix, trigClass->GetName()));
310 hclone->SetTitle(Form("%s %s",hist->GetTitle(), trigClass->GetName()));
311 hclone->SetDirectory(hist->GetDirectory());
312 //
313 // NOTE: the clone is added at position corresponding to ID of the trigger alias
314 clonesArr->AddAt(hclone, trigClass->GetUniqueID());
315 hclone->SetBit(AliQAv1::GetClonedBit());
316 AliDebug(AliQAv1::GetQADebugLevel(),Form("Cloned histogram %s for trigger class %s",hist->GetName(),trigClass->GetName()));
317 }
318 //
319 list->RemoveAt(index); // remove original histogram
320 list->AddAt(clonesArr, index);
321 if (!keepOriginal) delete hist;
322 //
323 clonesArr->SetOwner(kTRUE);
324 return clonesArr->GetEntries();
325}
326
327//____________________________________________________________________________
328Char_t* AliQADataMaker::GetHistoTrigger(const TH1* h) const
329{
330 // extract the name of the trigger from the histogram name
331 if (!h || !h->TestBit(AliQAv1::GetClonedBit())) return 0;
332 TString hnm = h->GetName();
333 int idx = hnm.Index(fgkTriggerPrefix);
334 if (idx<0) return 0; // not cloned
335 return (char*) h->GetName() + idx + sizeof(fgkTriggerPrefix) - 1;
336}
337
338//____________________________________________________________________________
339Int_t AliQADataMaker::SetEventTrigClasses(const char* triggers)
340{
341 // sets the array of triggers fired in given event, return the number of triggers
342 //
343 ResetEventTrigClasses();
344 fgEventTrigClasses.SetUniqueID(1); // flag that this is a triggered event
345 if (!GetNTrigClasses()) return 0; // meaningless if the trigger aliases are not set
346 TString trigStr = triggers;
347 TObjArray* tarr = trigStr.Tokenize(" ");
348 int nTrigs = tarr->GetEntriesFast();
349 if (!nTrigs) {
350 AliWarningClass("The string for event triggers is empty");
351 return 0;
352 }
353 int nTrClasses = 0;
354 for (int ial=fgTrigClasses->GetEntriesFast();ial--;) {
355 TNamed *pair = (TNamed*)fgTrigClasses->At(ial);
356 TString triggSet = pair->GetTitle(); // list of trigger names
357 for (int itr=nTrigs;itr--;) {
358 if ( !triggSet.Contains(tarr->At(itr)->GetName()) ) continue;
359 fgEventTrigClasses.Add(pair);
360 nTrClasses++;
361 break;
362 }
363 }
364 //
365 fgEventTrigClasses.SetOwner(kFALSE);
366 delete tarr;
367 //
368 return nTrClasses;
369}
370
371//____________________________________________________________________________
372TH1* AliQADataMaker::GetMatchingHisto(TObjArray ** list, Int_t index, Int_t trigId)
373{
374 // get histo with given index matching to trigId-th current trigger class
375 // trigId < 0 means default hist (only if cloning was done)
376 TObject* data = GetData(list,index);
377 if (!data) return 0;
378 if (trigId<0 || trigId==GetNEventTrigClasses()) { // original histo is requested
379 if (!data->TestBit(AliQAv1::GetClonedBit())) return (TH1*)data; // was not cloned per trigger
380 // check if during the cloning the original histo was kept (always at slot GetNTrigClasses())
381 else if (data->TestBit(AliQAv1::GetOrigHistoKeptBit())) return (TH1*)((TObjArray*)data)->At(GetNTrigClasses());
382 return 0;
383 }
384 //
385 if (!data->TestBit(AliQAv1::GetClonedBit())) return 0; // no cloning was done
386 if (trigId>GetNEventTrigClasses()) {
387 AliError(Form("Current event has %d triggers only, %d-th is requested",GetNEventTrigClasses(),trigId));
388 return 0; // invalid trigger
389 }
390 int slot = fgEventTrigClasses.At(trigId)->GetUniqueID(); // the histos are at slots corresponding to trig.class ID
391 return (TH1*)((TObjArray*)data)->At(slot);
392 //
393}
394
395//____________________________________________________________________________
396TObjArray* AliQADataMaker::GetMatchingHistosSet(TObjArray ** list, const Int_t* indexList, Int_t nHist, Int_t trigId)
397{
398 // get set of nHist histos with indices from the indexList matching to trigId-th current trigger
399 // Note: a static array is returned, it will be overwritten at the next call
400 static TObjArray garr;
401 garr.Clear();
402 for (int ih=0;ih<nHist;ih++) {
403 TH1* histo = GetMatchingHisto(list, indexList[ih],trigId);
404 if (!histo) return 0; // if at least 1 histo is not found, return nothing
405 garr.Add(histo);
406 }
407 return &garr;
408}
409
410//____________________________________________________________________________
411Bool_t AliQADataMaker::CheckCloningConsistency(TObjArray ** list, const Int_t* indexList, Int_t nHist, Bool_t checkTriggers)
412{
413 // Make sure that histograms at slots mentioned in the indexList are either
414 // not cloned per trigger or
415 // cloned for the same amount of triggers and if original histo was kept, then it is done for all histos.
416 // If checkTriggers is requested, apart from clones count also the trigger names are checked
417 //
418 // This consistency check is needed to ensure validity of the operations over the group of histograms in the EndOfDetectorCycle's
419 //
420 TObjArray* refArr = 0;
421 int refSlot = -1;
422 for (int isl=0;isl<nHist;isl++) {
423 int slot = indexList[isl];
424 TObject* data = GetData(list,slot);
425 if (!data) {AliError(Form("Slot %d is not booked",slot)); return kFALSE;}
426 //
427 if (refSlot<0) { // just take the 1st mentioned slot as a reference;
428 if (data->TestBit(AliQAv1::GetClonedBit())) refArr = (TObjArray*) data; // data was cloned
429 refSlot = slot;
430 continue;
431 }
432 //
433 if (!data->TestBit(AliQAv1::GetClonedBit())) { // this slot is not cloned, compare with reference
434 if (refArr) {AliError(Form("Slot %d is not cloned, slot %d is cloned",slot, refSlot)); return kFALSE;}
435 else continue;
436 }
437 //
438 TObjArray* currArr = (TObjArray*) data; // current slot is cloned
439 if (!refArr) {AliError(Form("Slot %d is not cloned, slot %d is cloned",refSlot,slot)); return kFALSE;}
440 //
441 // both are cloned
442 if (refArr->GetEntriesFast()!=currArr->GetEntriesFast()) {
443 AliError(Form("Different number of clones: slot %d: %d vs slot %d: %d",
444 refSlot,refArr->GetEntriesFast(), slot,currArr->GetEntriesFast()));
445 return kFALSE;
446 }
447 //
448 if (refArr->TestBit(AliQAv1::GetOrigHistoKeptBit())!=currArr->TestBit(AliQAv1::GetOrigHistoKeptBit())) {
449 AliError(Form("Slot %d kept original histo, slot %d did not",
450 refArr->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? refSlot:slot,refArr->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? slot:refSlot));
451 return kFALSE;
452 }
453 //
454 if (checkTriggers) {
455 for (int ih=refArr->GetEntriesFast();ih--;) {
456 TH1* hRef = (TH1*)refArr->At(ih);
457 if (!hRef->TestBit(AliQAv1::GetClonedBit())) continue; // original histo was kept, no trigger name is expected
458 TString hnm = ((TH1*)currArr->At(ih))->GetName();
459 if (!hnm.EndsWith( GetHistoTrigger(hRef) )) {
460 AliError(Form("Slots %d and %d have different trigger names for clone %d: %s vs %s",
461 refSlot,slot,ih,hRef->GetName(),hnm.Data()));
462 return kFALSE;
463 }
464 }
465 }
466 }
467 //
468 return kTRUE;
469}
470
471//____________________________________________________________________________
472TObjArray* AliQADataMaker::GetMatchingHistos(TObjArray ** list, Int_t index, TObjArray* optDest)
473{
474 // return all histograms of given index matching to any trigger in the current event trigger's list
475 // If the destination optDest is provided - use it, otherwise fill/return own static array
476 // In the latter case one should be careful: the content is overwritten at each call
477 // If the original histo was cloned but kept, it is also returned
478 //
479 // Note: if there are no triggers set, all eventual clones are returned
480 // (used for EndOfDetectorCycle loop over all histos)
481 static TObjArray garr;
482 TObjArray *dest = optDest ? optDest : &garr;
483 dest->SetOwner(kFALSE);
484 dest->Clear();
485 TObject* data = GetData(list,index);
486 if (!data) return 0;
487 if (!data->TestBit(AliQAv1::GetClonedBit())) dest->AddLast(data); // not cloned per trigger
488 else {
489 TObjArray* arr = dynamic_cast<TObjArray*>(data);
490 if (IsEventTriggerSet()) {
491 int ncl = GetNEventTrigClasses();
492 for (int icl=0;icl<ncl;icl++) {
493 int indCl = GetEventTrigClass(icl)->GetUniqueID();
494 // AliInfo(Form("Ind %d at %d of %p of %p",index,indCl, arr, list[AliRecoParam::AConvert(fEventSpecie)]));
495 TH1* histo = dynamic_cast<TH1*>(arr->At(indCl));
496 dest->AddLast(histo);
497 // AliInfo(Form("EvCl%d IndTr%d add to %d IndH %d %p %s",icl,indCl,dest->LastIndex(),index,histo,histo ? histo->GetName():"XXX"));
498 }
499 // check if original histo was kept
500 if (arr->TestBit(AliQAv1::GetOrigHistoKeptBit())) {
501 TH1* histo = dynamic_cast<TH1*>(arr->At(GetNTrigClasses()));
502 dest->AddLast(histo);
503 // AliInfo(Form("Def add to %d inex: %d %p %s",dest->LastIndex(),index,histo,histo ? histo->GetName():"XXX"));
504 }
505 }
506 else { // trigger is not set, return all clones
507 for (int ih=arr->GetEntriesFast();ih--;) if (arr->At(ih)) dest->AddLast(arr->At(ih));
508 }
509 }
510 return dest;
511}
512
513//____________________________________________________________________________
514Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x)
515{
516 // fills single histo or its trigger-dependent clones, return number of histos filled
517 TObjArray* arr = GetMatchingHistos(list,index);
518 int count = arr->GetEntriesFast();
519 for (int ih=count;ih--;) ((TH1*)arr->At(ih))->Fill(x);
520 return count;
521}
522
523//____________________________________________________________________________
524Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x, double y)
525{
526 // fills single histo or its trigger-dependent clones, return number of histos filled
527 TObjArray* arr = GetMatchingHistos(list,index);
528 int count = arr->GetEntriesFast();
529 for (int ih=count;ih--;) ((TH1*)arr->At(ih))->Fill(x,y);
530 return count;
531}
532
533//____________________________________________________________________________
534Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x, double y, double z)
535{
536 // fills single histo or its trigger-dependent clones, return number of histos filled
537 TObjArray* arr = GetMatchingHistos(list,index);
538 int count = arr->GetEntriesFast();
539 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->Fill(x,y,z);
540 return count;
541}
542
543//____________________________________________________________________________
544Int_t AliQADataMaker::SetDataBinContent(TObjArray ** list, Int_t index, int bin, double w)
545{
546 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
547 TObjArray* arr = GetMatchingHistos(list,index);
548 int count = arr->GetEntriesFast();
549 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinContent(bin,w);
550 return count;
551}
552
553//____________________________________________________________________________
554Int_t AliQADataMaker::SetDataBinContent(TObjArray ** list, Int_t index, int binX, int binY, double w)
555{
556 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
557 TObjArray* arr = GetMatchingHistos(list,index);
558 int count = arr->GetEntriesFast();
559 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinContent(binX,binY,w);
560 return count;
561}
562
563//____________________________________________________________________________
564Int_t AliQADataMaker::SetDataBinError(TObjArray ** list, Int_t index, int bin, double err)
565{
566 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
567 TObjArray* arr = GetMatchingHistos(list,index);
568 int count = arr->GetEntriesFast();
569 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinError(bin,err);
570 return count;
571}
572
573//____________________________________________________________________________
574Int_t AliQADataMaker::SetDataBinError(TObjArray ** list, Int_t index, int binX, int binY, double err)
575{
576 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
577 TObjArray* arr = GetMatchingHistos(list,index);
578 int count = arr->GetEntriesFast();
579 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinError(binX,binY,err);
580 return count;
581}
582
583//____________________________________________________________________________
584Int_t AliQADataMaker::ResetData(TObjArray ** list, Int_t index, Option_t* option)
585{
586 // reset content of single histo or its trigger-dependent clones, return number of histos processed
587 TObjArray* arr = GetMatchingHistos(list,index);
588 int count = arr->GetEntriesFast();
589 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->Reset(option);
590 return count;
591}
592
593//____________________________________________________________________________
594Int_t AliQADataMaker::ResetStatsData(TObjArray ** list, Int_t index)
595{
596 // reset stats of single histo or its trigger-dependent clones, return number of histos processed
597 TObjArray* arr = GetMatchingHistos(list,index);
598 int count = arr->GetEntriesFast();
599 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->ResetStats();
600 return count;
601}
602
57acd2d2 603//____________________________________________________________________________
604TH1 * AliQADataMaker::CloneMe(TH1 * hist, Int_t specie) const
605{
606 // clones a histogram
fec0891b 607 const Char_t * name = Form("%s_%s", AliRecoParam::GetEventSpecieName(specie), hist->GetName()) ;
eca4fa66 608 TH1 * hClone = static_cast<TH1 *>(hist->Clone(name)) ;
4e25ac79 609 if ( hist->TestBit(AliQAv1::GetExpertBit()) )
b2db43c5 610 hClone->SetBit(AliQAv1::GetExpertBit()) ;
611 if ( hist->TestBit(AliQAv1::GetImageBit()) )
612 hClone->SetBit(AliQAv1::GetImageBit()) ;
75373542 613 return hClone ;
421ab0fb 614}
615
96d67a8d 616//____________________________________________________________________________
4e25ac79 617void AliQADataMaker::DefaultEndOfDetectorCycle(AliQAv1::TASKINDEX_t task)
96d67a8d 618{
92664bc8 619 // this method must be oveloaded by detectors
620 // sets the QA result to Fatal
621 AliQAv1::Instance(AliQAv1::GetDetIndex(GetName())) ;
622 AliQAv1 * qa = AliQAv1::Instance(task) ;
57acd2d2 623 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
4e25ac79 624 qa->Set(AliQAv1::kFATAL, specie) ;
92664bc8 625 AliQAv1::GetQAResultFile()->cd() ;
626 qa->Write(AliQAv1::GetQAName(), kWriteDelete) ;
627 AliQAv1::GetQAResultFile()->Close() ;
96d67a8d 628}
629
421ab0fb 630//____________________________________________________________________________
c65c502a 631void AliQADataMaker::Finish() const
421ab0fb 632{
92664bc8 633 // write to the output File
634 if (fOutput)
635 fOutput->Close() ;
421ab0fb 636}
637
92664bc8 638//____________________________________________________________________________
639TH1* AliQADataMaker::GetData(TObjArray ** list, const Int_t index, int cloneID)
640{
641 // get the cloneID-th clone of the histo, -1 for original (if kept)
642 TObject* data = GetData(list,index);
643 if (!data) return 0;
644 Bool_t orig = cloneID<0 || cloneID==GetNTrigClasses();
645 if (data->TestBit(AliQAv1::GetClonedBit())) {
646 if (orig) return data->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? (TH1*)((TObjArray*)data)->At(GetNTrigClasses()) : 0;
647 else return (TH1*)((TObjArray*)data)->At(cloneID); // there was a cloning
648 }
649 //
650 // not cloned, is the original histo requested?
651 if (cloneID<0 || cloneID==GetNTrigClasses()) return (TH1*)data;
652 return 0;
653 //
654}
655
656//____________________________________________________________________________
657TObjArray* AliQADataMaker::GetDataOfTrigClass(TObjArray ** list, Int_t specieIndex, int cloneID, TObjArray *dest)
658{
659 // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
660 // a single array (if dest is not provided, use its own static array).
661 // Existing histos are attached at their original positions
662 TObjArray* arr = list[specieIndex] ;
663 return GetDataOfTrigClass(arr, cloneID, dest);
664}
665
666//____________________________________________________________________________
667TObjArray* AliQADataMaker::GetDataOfTrigClass(TObjArray *arr, int cloneID, TObjArray *dest)
668{
669 // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
670 // a single array (if dest is not provided, use its own static array).
671 // Existing histos are attached at their original positions
672 static TObjArray arrTransf;
673 TObjArray* destS = dest ? dest : &arrTransf;
674 destS->SetOwner(kFALSE);
675 destS->Clear();
676 if (arr) {
677 Bool_t orig = cloneID<0 || cloneID==GetNTrigClasses(); // is trigger-blind histo requested?
678 int nh = arr->GetEntriesFast();
679 if (nh>destS->GetSize()) destS->Expand(nh);
680 for (int ih=nh;ih--;) {
681 TObject* ob = arr->At(ih);
682 if (!ob) continue;
683 //
684 if (ob->TestBit(AliQAv1::GetClonedBit())) { // this is array of cloned histos
685 if (orig) ob = ob->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? ((TObjArray*)ob)->At(GetNTrigClasses()) : 0;
686 else ob = ((TObjArray*)ob)->At(cloneID);
687 }
688 else if (!orig) ob = 0; // histogram was not cloned but the clone is requested
689 if (!ob) continue;
690 (*destS)[ih] = ob;
691 }
692 }
693 return destS;
694 //
695}
696
697//____________________________________________________________________________
698TObjArray* AliQADataMaker::GetDataOfTrigClass(TObjArray ** list, int cloneID, TObjArray *dest)
699{
700 // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
701 // a single array (if dest is not provided, use its own static array).
702 // Existing histos are attached at their original positions
703 //
704 GetData(list,0); //just to initialize, if needed
705 Int_t esindex = AliRecoParam::AConvert(fEventSpecie);
706 return GetDataOfTrigClass(list, esindex, cloneID, dest);
707 //
708}
709
421ab0fb 710//____________________________________________________________________________
57acd2d2 711TObject * AliQADataMaker::GetData(TObjArray ** list, const Int_t index)
04236e67 712{
92664bc8 713 // Returns the QA object at index. Limit is AliQAv1::GetMaxQAObj()
76c42cb4 714 if ( ! list ) {
92664bc8 715 AliError("Data list is NULL !!") ;
716 return NULL ;
717 }
eca4fa66 718 Int_t esindex = AliRecoParam::AConvert(fEventSpecie) ;
92664bc8 719 TObject* histClone = NULL ;
49466ea2 720 TObjArray * arr = list[esindex] ;
92664bc8 721 if (arr) {
6252ceeb 722 if ( ! arr->GetEntriesFast() ) {
723 // Initializes the histograms
724 TString arrName(arr->GetName()) ;
725 if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kRAWS)))
726 InitRaws() ;
727 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kHITS)))
728 InitHits() ;
729 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kSDIGITS)))
730 InitSDigits() ;
731 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kDIGITS)))
732 InitDigits() ;
733 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kDIGITSR)))
7f0f88e7 734 InitDigits() ;
6252ceeb 735 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kRECPOINTS)))
736 InitRecPoints() ;
737 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kESDS)))
738 InitESDs() ;
739 }
92664bc8 740 if ( index > AliQAv1::GetMaxQAObj() ) {
741 AliError(Form("Max number of authorized QA objects is %d", AliQAv1::GetMaxQAObj())) ;
742 } else {
49466ea2 743 if ( arr->At(index) ) {
92664bc8 744 histClone = arr->At(index);
eca4fa66 745 }
746 }
747 }
748 return histClone ;
27773260 749}
7d297381 750
211a7313 751//____________________________________________________________________________
752TObjArray* AliQADataMaker::Init(AliQAv1::TASKINDEX_t task, AliRecoParam::EventSpecie_t es, Int_t cycles)
753{
754 // Initialializes and returns the QAData list for a given event specie
755 TObjArray ** ar = Init(task, cycles) ;
756 return ar[AliRecoParam::AConvert(es)] ;
757}
758
6252ceeb 759//____________________________________________________________________________
760Bool_t AliQADataMaker::IsValidEventSpecie(Int_t eventSpecieIndex, TObjArray ** list)
761{
762 // check if event specie was present in current run or
763 // if histograms of this event specie have been created
764 if (! AliQAv1::Instance(AliQAv1::GetDetIndex(GetName()))->IsEventSpecieSet(AliRecoParam::ConvertIndex(eventSpecieIndex)) || ! list[eventSpecieIndex]->GetEntriesFast() )
765 return kFALSE ;
766 else
767 return kTRUE ;
768}
9ac91920 769
92664bc8 770//____________________________________________________________________________
771void AliQADataMaker::SetCloningRequest(TObjArray* aliases, TObjArray* histos)
772{
773 // set associations {trigger names} <-> {trigger class alias}
774 //
775 const UInt_t kDummyID = 0xffff;
776 //
777 if (fgTrigClasses || fgCloningRequest) {
778 AliWarningClass("Cloning request is already set");
779 return;
780 }
781 ResetEventTrigClasses();
782 if (!aliases || !histos) {
783 AliWarningClass("Cloning request is incomplete");
784 return;
785 }
786 fgTrigClasses = aliases;
787 fgCloningRequest = histos;
788 //
789 // flag those aliases which are actually used
790 fgCloningRequest->Compress();
791 fgTrigClasses->Compress();
792 int nalias = fgTrigClasses->GetEntriesFast();
793 int nhisto = fgCloningRequest->GetEntriesFast();
794 //
795 int naliasUsed = 0;
796 for (int ial=0;ial<nalias;ial++) {
797 TNamed* alias = (TNamed*)fgTrigClasses->At(ial);
798 alias->SetUniqueID(kDummyID);
799 TString aliasName = alias->GetName();
800 for (int ih=nhisto;ih--;) {
801 TNamed* histo = (TNamed*)fgCloningRequest->At(ih);
802 TString histoReq = histo->GetTitle(); // list of aliases for which the histo must be cloned
803 TObjArray* alList = histoReq.Tokenize(" ");
804 if (!alList) continue;
805 for (int iha=alList->GetEntriesFast();iha--;) {
806 if (!(aliasName == alList->At(iha)->GetName())) continue;
807 alias->SetUniqueID(naliasUsed++); // acknowledge used alias
808 break;
809 }
810 if (alias->GetUniqueID()!=kDummyID) break; // once alias is validated, check the next one
811 }
812 }
813 // eliminate unused aliases
814 for (int ial=0;ial<nalias;ial++) if (fgTrigClasses->At(ial)->GetUniqueID()==kDummyID) delete fgTrigClasses->RemoveAt(ial);
815 fgTrigClasses->Compress();
816 //
817 AliInfoClass("Aliases for trigger classes:");
818 for (int i=0;i<fgTrigClasses->GetEntriesFast();i++) {
819 TNamed* item = (TNamed*)fgTrigClasses->At(i);
820 AliInfoClass(Form("%s -> %s",item->GetName(),item->GetTitle()));
821 }
822 //
823 AliInfoClass("Histograms to clone:");
824 for (int i=0;i<fgCloningRequest->GetEntriesFast();i++) {
825 TNamed* item = (TNamed*)fgCloningRequest->At(i);
826 AliInfoClass(Form("%s -> %s %s",item->GetName(),item->GetTitle(),
827 item->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? " + TriggerBlind":""));
828 }
829 //
830}
831
832//____________________________________________________________________________
833void AliQADataMaker::IncEvCountCycle(AliQAv1::TASKINDEX_t task, Int_t diff)
834{
835 // incerment by "diff" the cycle counters for the current event trigger classes (+ the global one)
836 int ncl = GetNTrigClasses();
837 int isp = AliRecoParam::AConvert(fEventSpecie);
838 //
839 if (fEvCountCycle[isp].GetSize()==AliQAv1::kNTASKINDEX && ncl>0) fEvCountCycle[isp].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
840 //
841 fEvCountCycle[isp][task*(1+ncl)+ncl] += diff; // trigger independent counter
842 for (int icl=GetNEventTrigClasses();icl--;) fEvCountCycle[isp][task*(1+ncl)+ GetEventTrigClass(icl)->GetUniqueID()] += diff;
843}
844
845//____________________________________________________________________________
846void AliQADataMaker::IncEvCountTotal(AliQAv1::TASKINDEX_t task, Int_t diff)
847{
848 // incerment by "diff" the cycle counters for the current event trigger classes (+ the global one)
849 int ncl = GetNTrigClasses();
850 int isp = AliRecoParam::AConvert(fEventSpecie);
851 //
852 if (fEvCountTotal[isp].GetSize()==AliQAv1::kNTASKINDEX && ncl>0) fEvCountTotal[isp].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
853 //
854 fEvCountTotal[isp][task*(1+ncl)+ncl] += diff; // trigger independent counter
855 for (int icl=GetNEventTrigClasses();icl--;) fEvCountTotal[isp][task*(1+ncl)+ GetEventTrigClass(icl)->GetUniqueID()] += diff;
856}
857
858//____________________________________________________________________________
859void AliQADataMaker::ResetEvCountCycle(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task)
860{
861 // reset counter for specific trigger class for specific specie (within the cycle)
862 int ncl = GetNTrigClasses();
863 // check if it was already expanded
864 if (fEvCountCycle[isp].GetSize()==AliQAv1::kNTASKINDEX) fEvCountCycle[isp].Set(AliQAv1::kNTASKINDEX*(ncl+1));
865 for (int icl=ncl+1;icl--;) fEvCountCycle[AliRecoParam::AConvert(isp)][task*(1+ncl) + icl] = 0;
866}
867
868//____________________________________________________________________________
869void AliQADataMaker::ResetEvCountTotal(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task)
870{
871 // reset counter for specific trigger class for specific specie (global count)
872 int ncl = GetNTrigClasses();
873 // check if it was already expanded
874 if (fEvCountTotal[isp].GetSize()==AliQAv1::kNTASKINDEX) fEvCountTotal[isp].Set(AliQAv1::kNTASKINDEX*(ncl+1));
875 for (int icl=ncl+1;icl--;) fEvCountTotal[AliRecoParam::AConvert(isp)][task*(1+ncl) + icl] = 0;
876}
877
878//____________________________________________________________________________
879Int_t AliQADataMaker::GetEvCountCycle(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task, Int_t trCl) const
880{
881 // get counter for specific trigger class for specific specie (within the cycle)
882 int ncl = GetNTrigClasses();
883 return fEvCountCycle[AliRecoParam::AConvert(isp)][task*(1+ncl) + (trCl<0||trCl>=ncl ? ncl:trCl)];
884}
885//____________________________________________________________________________
886Int_t AliQADataMaker::GetEvCountTotal(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task, Int_t trCl) const
887{
888 // get counter for specific trigger class for specific specie (global count)
889 int ncl = GetNTrigClasses();
890 return fEvCountTotal[AliRecoParam::AConvert(isp)][task*(1+ncl) + (trCl<0||trCl>=ncl ? ncl:trCl)];
891}
892