7f73f75c068ae9fb94866db70bff979bf0a5b70c
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTCTPData.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8 //*                  for The ALICE HLT Project.                            *
9 //*                                                                        *
10 //* Permission to use, copy, modify and distribute this software and its   *
11 //* documentation strictly for non-commercial purposes is hereby granted   *
12 //* without fee, provided that the above copyright notice appears in all   *
13 //* copies and that both the copyright notice and this permission notice   *
14 //* appear in the supporting documentation. The authors make no claims     *
15 //* about the suitability of this software for any purpose. It is          *
16 //* provided "as is" without express or implied warranty.                  *
17 //**************************************************************************
18
19 //  @file   AliHLTCTPData.cxx
20 //  @author Matthias Richter
21 //  @date   2009-08-20
22 //  @brief  Container for CTP trigger classes and counters
23 //  @note
24
25 #include "AliHLTCTPData.h"
26 #include "AliHLTReadoutList.h"
27 #include "TClass.h"
28 #include "TObjString.h"
29 #include "TFormula.h"
30
31 /** ROOT macro for the implementation of ROOT specific class methods */
32 ClassImp(AliHLTCTPData)
33
34 AliHLTCTPData::AliHLTCTPData()
35   : TNamed("AliHLTCTPData", "HLT counters for the CTP")
36   , AliHLTLogging()
37   , fMask(0)
38   , fTriggers(0)
39   , fClassIds(AliHLTReadoutList::Class(), gkNCTPTriggerClasses)
40   , fCounters(gkNCTPTriggerClasses)
41   , fMap()
42 {
43   // constructor
44   // see header file for class documentation
45   // or
46   // refer to README to build package
47   // or
48   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
49 }
50
51 AliHLTCTPData::AliHLTCTPData(const char* parameter)
52   : TNamed("AliHLTCTPData", "HLT counters for the CTP")
53   , AliHLTLogging()
54   , fMask(0)
55   , fTriggers(0)
56   , fClassIds(AliHLTReadoutList::Class(), gkNCTPTriggerClasses)
57   , fCounters(gkNCTPTriggerClasses)
58   , fMap()
59 {
60   // constructor, init the CTP trigger classes
61   InitCTPTriggerClasses(parameter);
62 }
63
64 AliHLTCTPData::~AliHLTCTPData()
65 {
66   // destructor
67   fClassIds.Delete();
68 }
69
70 AliHLTCTPData::AliHLTCTPData(const AliHLTCTPData& src)
71   : TNamed(src.GetName(), src.GetTitle())
72   , AliHLTLogging()
73   , fMask(src.Mask())
74   , fTriggers(src.fTriggers)
75   , fClassIds(src.fClassIds)
76   , fCounters(src.Counters())
77   , fMap()
78 {
79   // copy constructor
80   ReadMap();
81 }
82
83 AliHLTCTPData& AliHLTCTPData::operator=(const AliHLTCTPData& src)
84 {
85   // assignment operator, clone content
86   if (this!=&src) {
87     SetName(src.GetName());
88     SetTitle(src.GetTitle());
89     fMask=src.Mask();
90     fClassIds.Delete();
91     fClassIds.ExpandCreate(gkNCTPTriggerClasses);
92     for (int i=0; i<gkNCTPTriggerClasses; i++) {
93       if (i>src.fClassIds.GetLast()) break;
94       ((TNamed*)fClassIds.At(i))->SetName(src.fClassIds.At(i)->GetName());
95       ((TNamed*)fClassIds.At(i))->SetTitle(src.fClassIds.At(i)->GetTitle());
96     }
97     fCounters=src.Counters();
98   }
99
100   ReadMap();
101   return *this;
102 }
103
104 int AliHLTCTPData::Add(const AliHLTCTPData& src, int factor, int &skipped)
105 {
106   // see header file for class documentation
107   
108   skipped=0;
109   for (int i=0; i<gkNCTPTriggerClasses; i++) {
110     TString c;
111     c=fClassIds.At(i)->GetName();
112     if (c.IsNull()) continue;
113     if (c.CompareTo(src.fClassIds.At(i)->GetName())==0) {
114       fCounters[i]+=factor*src.Counter(i);
115     } else {
116       skipped++;
117     }
118   }
119   return 0;
120 }
121
122 AliHLTCTPData& AliHLTCTPData::operator += (const AliHLTCTPData& src)
123 {
124   // see header file for class documentation
125   
126   int nofInconsistencies=0;
127   Add(src, 1, nofInconsistencies);
128   if (nofInconsistencies>0) {
129     HLTError("Inconsistent operants: skipping %d of %d CTP classes for operation", nofInconsistencies, gkNCTPTriggerClasses);
130   }
131   return *this;
132 }
133
134 AliHLTCTPData& AliHLTCTPData::operator -= (const AliHLTCTPData& src)
135 {
136   // see header file for class documentation
137   
138   int nofInconsistencies=0;
139   Add(src, -1, nofInconsistencies);
140   if (nofInconsistencies>0) {
141     HLTError("Inconsistent operants: skipping %d of %d CTP classes for operation", nofInconsistencies, gkNCTPTriggerClasses);
142   }
143   return *this;
144 }
145
146 AliHLTCTPData AliHLTCTPData::operator + (const AliHLTCTPData& src) const
147 {
148   // see header file for class documentation
149
150   AliHLTCTPData result(*this);
151   result+=src;
152   return result;
153 }
154
155 AliHLTCTPData AliHLTCTPData::operator - (const AliHLTCTPData& src) const
156 {
157   // see header file for class documentation
158
159   AliHLTCTPData result(*this);
160   result-=src;
161   return result;
162 }
163
164 int AliHLTCTPData::InitCTPTriggerClasses(const char* ctpString)
165 {
166   // see header file for function documentation
167   if (!ctpString) return -EINVAL;
168
169   HLTImportant("Parameter: %s", ctpString);
170
171   fMask=0;
172   fClassIds.Delete();
173   fClassIds.ExpandCreate(gkNCTPTriggerClasses);
174
175   // general format of the CTP_TRIGGER_CLASS parameter
176   // <bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,<bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,...
177   HLTDebug(": %s", ctpString);
178   TString string=ctpString;
179   if (string.BeginsWith("CTP_TRIGGER_CLASS=")) string.ReplaceAll("CTP_TRIGGER_CLASS=", "");
180   TObjArray* classEntries=string.Tokenize(",");
181   if (classEntries) {
182     enum {kBit=0, kName, kDetectors};
183     for (int i=0; i<classEntries->GetEntriesFast(); i++) {
184       TString entry=((TObjString*)classEntries->At(i))->GetString();
185       TObjArray* entryParams=entry.Tokenize(":");
186       if (entryParams) {
187         if (entryParams->GetEntriesFast()==3 &&
188             (((TObjString*)entryParams->At(kBit))->GetString()).IsDigit()) {
189           int index=(((TObjString*)entryParams->At(kBit))->GetString()).Atoi();
190           if (index<gkNCTPTriggerClasses) {
191             AliHLTReadoutList* pCTPClass=dynamic_cast<AliHLTReadoutList*>(fClassIds.At(index));
192             if (pCTPClass) {
193               fMask|=(AliHLTUInt64_t)0x1 << index;
194               pCTPClass->SetTitle("CTP Class");
195               pCTPClass->SetName((((TObjString*)entryParams->At(kName))->GetString()).Data());
196               TObjArray* detectors=(((TObjString*)entryParams->At(kDetectors))->GetString()).Tokenize("-");
197               if (detectors) {
198                 for (int dix=0; dix<detectors->GetEntriesFast(); dix++) {
199                   if (!(((TObjString*)detectors->At(dix))->GetString()).IsDigit()) {
200                     HLTError("invalid detector list format: trigger class entry %s", entry.Data());
201                     break;
202                   }
203                   // see AliHLTReadoutList::EDetectorId for defines of detectors
204                   pCTPClass->Enable(0x1<<(((TObjString*)detectors->At(dix))->GetString()).Atoi());
205                 }
206                 delete detectors;
207               }
208             } else {
209             }
210           } else {
211             // the trigger bitfield is fixed to 50 bits (gkNCTPTriggerClasses)
212             HLTError("invalid trigger class entry %s, index width of trigger bitfield exceeded (%d)", entry.Data(), gkNCTPTriggerClasses);
213           }
214         } else {
215           HLTError("invalid trigger class entry %s", entry.Data());
216         }
217         delete entryParams;
218       }
219     }
220     delete classEntries;
221   }
222
223   ResetCounters();
224   ReadMap();
225
226   return 0;
227 }
228
229 AliHLTUInt64_t AliHLTCTPData::ActiveTriggers(const AliHLTComponentTriggerData& trigData)
230 {
231   // extract active triggers from the trigger data
232  
233   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) return (AliHLTUInt64_t)0;
234
235   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
236   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
237   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
238   triggerMask<<=32;
239   triggerMask|=evtData->fCommonHeader[5];
240   return triggerMask;
241 }
242
243 bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, const AliHLTComponentTriggerData& trigData) const
244 {
245   // see header file for function documentation
246   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
247     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
248     return false;
249   }
250
251   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
252   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
253   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
254   triggerMask<<=32;
255   triggerMask|=evtData->fCommonHeader[5];
256
257   if (fMask!=0 && (triggerMask & fMask)==0) {
258     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask);
259     for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
260     return false;
261   }
262
263   return EvaluateCTPTriggerClass(expression, triggerMask);
264 }
265
266 bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, AliHLTUInt64_t triggerMask) const
267 {
268   // see header file for function documentation
269
270   // use a TFormula to interprete the expression
271   // all classname are replaced by '[n]' which means the n'th parameter in the formula
272   // the parameters are set to 0 or 1 depending on the bit in the trigger mask
273   const vector<unsigned> *pMap=&fMap;
274   vector<unsigned> tmp;
275   if (fMap.size()==0 && fClassIds.GetLast()>=0) {
276     // read map into temporary array and use it
277     ReadMap(tmp);
278     pMap=&tmp;
279     static bool suppressWarning=false;
280     if (!suppressWarning) HLTWarning("map not yet initialized, creating local map (slow), suppressing further warnings");
281     suppressWarning=true;
282   }
283   vector<Double_t> par;
284   TString condition=expression;
285   for (unsigned index=0; index<pMap->size(); index++) {
286     const char* className=Name((*pMap)[index]);
287     if (className && strlen(className)>0) {
288       //HLTDebug("checking trigger class %s", className.Data());
289       if (condition.Contains(className)) {
290         TString replace; replace.Form("[%d]", par.size());
291         //HLTDebug("replacing %s with %s in \"%s\"", className.Data(), replace.Data(), condition.Data());
292         condition.ReplaceAll(className, replace);
293         if (triggerMask&((AliHLTUInt64_t)0x1<<(*pMap)[index])) par.push_back(1.0);
294         else par.push_back(0.0);
295       }
296     }
297   }
298
299   TFormula form("trigger expression", condition);
300   if (form.Compile()!=0) {
301     HLTError("invalid expression %s", expression);
302     return false;
303   }
304   if (form.EvalPar(&par[0], &par[0])>0.5) return true;
305   return false;
306 }
307
308 void AliHLTCTPData::ResetCounters()
309 {
310   // see header file for function documentation
311   fCounters.Set(gkNCTPTriggerClasses);
312   fCounters.Reset();
313 }
314
315 int AliHLTCTPData::Index(const char* name) const
316 {
317   // see header file for function documentation
318   TObject* obj=fClassIds.FindObject(name);
319   return obj!=NULL?fClassIds.IndexOf(obj):-1;
320 }
321
322 int AliHLTCTPData::CheckTrigger(const char* name) const
323 {
324   // check status of a trigger class
325   int index=Index(name);
326   if (index<0) return index;
327   return (fTriggers&(0x1<<index))>0?1:0;
328 }
329
330 void AliHLTCTPData::Increment(const char* classIds)
331 {
332   // see header file for function documentation
333   TString string=classIds;
334   TObjArray* classEntries=string.Tokenize(",");
335   if (classEntries) {
336     for (int i=0; i<classEntries->GetEntriesFast(); i++) {
337       int index=Index(((TObjString*)classEntries->At(i))->GetString().Data());
338       if (index>=0 && index<fCounters.GetSize()) fCounters[index]++;
339     }
340     delete classEntries;
341   }
342 }
343
344 void AliHLTCTPData::Increment(AliHLTUInt64_t triggerPattern)
345 {
346   // see header file for function documentation
347   AliHLTUInt64_t pattern=triggerPattern&fMask;
348   for (int i=0; i<fCounters.GetSize(); i++) {
349     if ((pattern&((AliHLTUInt64_t)0x1<<i))==0) continue;
350     fCounters[i]++;    
351   }
352 }
353
354 void AliHLTCTPData::Increment(int classIdx)
355 {
356   // see header file for function documentation
357   if (classIdx<fCounters.GetSize() &&
358       (fMask&((AliHLTUInt64_t)0x1<<classIdx))) {
359     fCounters[classIdx]++;    
360   }
361   
362 }
363
364 int AliHLTCTPData::Increment(AliHLTComponentTriggerData& trigData)
365 {
366   // see header file for function documentation
367   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
368     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
369     return -EBADF;
370   }
371
372   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
373   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
374   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
375   triggerMask<<=32;
376   triggerMask|=evtData->fCommonHeader[5];
377
378   if (fMask!=0 && (triggerMask & fMask)==0) {
379     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask);
380     for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
381   }
382   Increment(triggerMask);
383   return 0;
384 }
385
386 AliHLTUInt64_t AliHLTCTPData::Counter(int index) const
387 {
388   // see header file for function documentation
389   if (index>=0 && index<Counters().GetSize()) return Counters()[index];
390   return 0;
391 }
392
393 AliHLTUInt64_t AliHLTCTPData::Counter(const char* classId) const
394 {
395   // see header file for function documentation
396   return Counter(Index(classId));
397 }
398
399 const char* AliHLTCTPData::Name(int index) const
400 {
401   // see header file for function documentation
402   if (index>fClassIds.GetLast()) return NULL;
403   return fClassIds.At(index)->GetName();
404 }
405
406 int AliHLTCTPData::ReadMap(vector<unsigned> &map) const
407 {
408   // read the index map for class names
409   // for nested class names (e.g. 'myclass' is contained in
410   // 'myclassA') the longer names is added first to the map.
411   for (int index=0; index<=fClassIds.GetLast(); index++) {
412     vector<unsigned>::iterator element=map.begin();
413     for (; element!=map.end(); element++) {
414       TString name=Name(index);
415       if (name.Contains(Name(*element))) {
416         // current name contains another one already in the map
417         // -> add before and go to next entry
418         element=map.insert(element, index);
419         break;
420       }
421     }
422
423     if (element==map.end()) {
424       // unique class name, append to map
425       map.push_back(index);
426     }
427   }
428   return 0;
429 }
430
431
432 AliHLTEventDDL AliHLTCTPData::ReadoutList(const AliHLTComponentTriggerData& trigData) const
433 {
434   // see header file for function documentation
435   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
436     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
437     AliHLTEventDDL dummy;
438     memset(&dummy, 0, sizeof(AliHLTEventDDL));
439     return dummy;
440   }
441
442   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
443   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
444   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
445   triggerMask<<=32;
446   triggerMask|=evtData->fCommonHeader[5];
447
448   if (fMask!=0 && (triggerMask & fMask)==0) {
449     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask);
450     for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
451   }
452
453   return ReadoutList(triggerMask);
454 }
455
456 AliHLTEventDDL AliHLTCTPData::ReadoutList(AliHLTUInt64_t  triggerMask) const
457 {
458   // take an 'OR' of all active trigger classes 
459   AliHLTReadoutList list;
460   for (int i=0; i<gkNCTPTriggerClasses; i++) {
461     if (i>fClassIds.GetLast()) break;
462     if ((triggerMask&((AliHLTUInt64_t)0x1<<i))==0) continue;
463     AliHLTReadoutList* tcrl=(AliHLTReadoutList*)fClassIds.At(i);
464     list.OrEq(*tcrl);
465   }
466
467   return list;
468 }
469
470
471 void AliHLTCTPData::Print(Option_t* /*option*/) const
472 {
473   // see header file for function documentation
474   cout << GetTitle() << endl;
475   cout << "\tactive trigger mask: 0x" << hex << fTriggers << dec << endl;
476   int count=0;
477   for (int i=0; i<gkNCTPTriggerClasses; i++) {
478     if (i>=Counters().GetSize()) break;
479     if (i>fClassIds.GetLast()) break;
480     if ((fMask&((AliHLTUInt64_t)0x1<<i))==0) continue;
481     count++;
482     cout << "\t" << i << "\t" << Name(i) << "\t" << Counter(i) << endl;
483   }
484   if (count==0) cout << "\t(none)" << endl;
485 }