4d5b7ea05f414fb4ce0ac6a219eaa6ed6476a13e
[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 */
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 {
42   // see header file for class documentation
43   // or
44   // refer to README to build package
45   // or
46   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
47 }
48
49 AliHLTCTPData::AliHLTCTPData(const char* parameter)
50   : TNamed("AliHLTCTPData", "HLT counters for the CTP")
51   , AliHLTLogging()
52   , fMask(0)
53   , fTriggers(0)
54   , fClassIds(AliHLTReadoutList::Class(), gkNCTPTriggerClasses)
55   , fCounters(gkNCTPTriggerClasses)
56 {
57   // see header file for class documentation
58   InitCTPTriggerClasses(parameter);
59 }
60
61 AliHLTCTPData::~AliHLTCTPData()
62 {
63   // see header file for class documentation
64   fClassIds.Delete();
65 }
66
67 AliHLTCTPData::AliHLTCTPData(const AliHLTCTPData& src)
68   : TNamed(src.GetName(), src.GetTitle())
69   , AliHLTLogging()
70   , fMask(src.Mask())
71   , fTriggers(src.fTriggers)
72   , fClassIds(src.fClassIds)
73   , fCounters(src.Counters())
74 {
75   // see header file for class documentation
76 }
77
78 AliHLTCTPData& AliHLTCTPData::operator=(const AliHLTCTPData& src)
79 {
80   // see header file for class documentation
81   if (this!=&src) {
82     SetName(src.GetName());
83     SetTitle(src.GetTitle());
84     fMask=src.Mask();
85     fClassIds.Delete();
86     fClassIds.ExpandCreate(gkNCTPTriggerClasses);
87     for (int i=0; i<gkNCTPTriggerClasses; i++) {
88       ((TNamed*)fClassIds.At(i))->SetName(src.fClassIds.At(i)->GetName());
89       ((TNamed*)fClassIds.At(i))->SetTitle(src.fClassIds.At(i)->GetTitle());
90     }
91     fCounters=src.Counters();
92   }
93
94   return *this;
95 }
96
97 int AliHLTCTPData::Add(const AliHLTCTPData& src, int factor, int &skipped)
98 {
99   // see header file for class documentation
100   
101   skipped=0;
102   for (int i=0; i<gkNCTPTriggerClasses; i++) {
103     TString c;
104     c=fClassIds.At(i)->GetName();
105     if (c.IsNull()) continue;
106     if (c.CompareTo(src.fClassIds.At(i)->GetName())==0) {
107       fCounters[i]+=factor*src.Counter(i);
108     } else {
109       skipped++;
110     }
111   }
112   return 0;
113 }
114
115 AliHLTCTPData& AliHLTCTPData::operator += (const AliHLTCTPData& src)
116 {
117   // see header file for class documentation
118   
119   int nofInconsistencies=0;
120   Add(src, 1, nofInconsistencies);
121   if (nofInconsistencies>0) {
122     HLTError("Inconsistent operants: skipping %d of %d CTP classes for operation", nofInconsistencies, gkNCTPTriggerClasses);
123   }
124   return *this;
125 }
126
127 AliHLTCTPData& AliHLTCTPData::operator -= (const AliHLTCTPData& src)
128 {
129   // see header file for class documentation
130   
131   int nofInconsistencies=0;
132   Add(src, -1, nofInconsistencies);
133   if (nofInconsistencies>0) {
134     HLTError("Inconsistent operants: skipping %d of %d CTP classes for operation", nofInconsistencies, gkNCTPTriggerClasses);
135   }
136   return *this;
137 }
138
139 AliHLTCTPData AliHLTCTPData::operator + (const AliHLTCTPData& src) const
140 {
141   // see header file for class documentation
142
143   AliHLTCTPData result(*this);
144   result+=src;
145   return result;
146 }
147
148 AliHLTCTPData AliHLTCTPData::operator - (const AliHLTCTPData& src) const
149 {
150   // see header file for class documentation
151
152   AliHLTCTPData result(*this);
153   result-=src;
154   return result;
155 }
156
157 int AliHLTCTPData::InitCTPTriggerClasses(const char* ctpString)
158 {
159   // see header file for function documentation
160   if (!ctpString) return -EINVAL;
161
162   HLTImportant("Parameter: %s", ctpString);
163
164   fMask=0;
165   fClassIds.Delete();
166   fClassIds.ExpandCreate(gkNCTPTriggerClasses);
167
168   // general format of the CTP_TRIGGER_CLASS parameter
169   // <bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,<bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,...
170   HLTDebug(": %s", ctpString);
171   TString string=ctpString;
172   if (string.BeginsWith("CTP_TRIGGER_CLASS=")) string.ReplaceAll("CTP_TRIGGER_CLASS=", "");
173   TObjArray* classEntries=string.Tokenize(",");
174   if (classEntries) {
175     enum {kBit=0, kName, kDetectors};
176     for (int i=0; i<classEntries->GetEntries(); i++) {
177       TString entry=((TObjString*)classEntries->At(i))->GetString();
178       TObjArray* entryParams=entry.Tokenize(":");
179       if (entryParams) {
180         if (entryParams->GetEntries()==3 &&
181             (((TObjString*)entryParams->At(kBit))->GetString()).IsDigit()) {
182           int index=(((TObjString*)entryParams->At(kBit))->GetString()).Atoi();
183           if (index<gkNCTPTriggerClasses) {
184             AliHLTReadoutList* pCTPClass=dynamic_cast<AliHLTReadoutList*>(fClassIds.At(index));
185             if (pCTPClass) {
186               fMask|=(AliHLTUInt64_t)0x1 << index;
187               pCTPClass->SetTitle("CTP Class");
188               pCTPClass->SetName((((TObjString*)entryParams->At(kName))->GetString()).Data());
189               TObjArray* detectors=(((TObjString*)entryParams->At(kDetectors))->GetString()).Tokenize("-");
190               if (detectors) {
191                 for (int dix=0; dix<detectors->GetEntriesFast(); dix++) {
192                   if (!(((TObjString*)detectors->At(dix))->GetString()).IsDigit()) {
193                     HLTError("invalid detector list format: trigger class entry %s", entry.Data());
194                     break;
195                   }
196                   // see AliHLTReadoutList::EDetectorId for defines of detectors
197                   pCTPClass->Enable(0x1<<(((TObjString*)detectors->At(dix))->GetString()).Atoi());
198                 }
199                 delete detectors;
200               }
201             } else {
202             }
203           } else {
204             // the trigger bitfield is fixed to 50 bits (gkNCTPTriggerClasses)
205             HLTError("invalid trigger class entry %s, index width of trigger bitfield exceeded (%d)", entry.Data(), gkNCTPTriggerClasses);
206           }
207         } else {
208           HLTError("invalid trigger class entry %s", entry.Data());
209         }
210         delete entryParams;
211       }
212     }
213     delete classEntries;
214   }
215
216   ResetCounters();
217
218   return 0;
219 }
220
221 AliHLTUInt64_t AliHLTCTPData::ActiveTriggers(const AliHLTComponentTriggerData& trigData)
222 {
223   // extract active triggers from the trigger data
224  
225   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) return (AliHLTUInt64_t)0;
226
227   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
228   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
229   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
230   triggerMask<<=32;
231   triggerMask|=evtData->fCommonHeader[5];
232   return triggerMask;
233 }
234
235 bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, const AliHLTComponentTriggerData& trigData) const
236 {
237   // see header file for function documentation
238   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
239     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
240     return false;
241   }
242
243   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
244   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
245   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
246   triggerMask<<=32;
247   triggerMask|=evtData->fCommonHeader[5];
248
249   if (fMask!=0 && (triggerMask & fMask)==0) {
250     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask);
251     for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
252     return false;
253   }
254
255   return EvaluateCTPTriggerClass(expression, triggerMask);
256 }
257
258 bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, AliHLTUInt64_t triggerMask) const
259 {
260   // see header file for function documentation
261
262   // use a TFormula to interprete the expression
263   // all classname are replaced by '[n]' which means the n'th parameter in the formula
264   // the parameters are set to 0 or 1 depending on the bit in the trigger mask
265   //
266   // TODO: this will most likely fail for class names like 'base', 'baseA', 'baseB'
267   // the class names must be fully unique, none must be contained as substring in
268   // another class name. Probably not needed for the moment but needs to be extended.
269   vector<Double_t> par;
270   TString condition=expression;
271   for (int i=0; i<gkNCTPTriggerClasses; i++) {
272     const char* className=Name(i);
273     if (className && strlen(className)>0) {
274       //HLTDebug("checking trigger class %s", className.Data());
275       if (condition.Contains(className)) {
276         TString replace; replace.Form("[%d]", par.size());
277         //HLTDebug("replacing %s with %s in \"%s\"", className.Data(), replace.Data(), condition.Data());
278         condition.ReplaceAll(className, replace);
279         if (triggerMask&((AliHLTUInt64_t)0x1<<i)) par.push_back(1.0);
280         else par.push_back(0.0);
281       }
282     }
283   }
284
285   TFormula form("trigger expression", condition);
286   if (form.Compile()!=0) {
287     HLTError("invalid expression %s", expression);
288     return false;
289   }
290   if (form.EvalPar(&par[0], &par[0])>0.5) return true;
291   return false;
292 }
293
294 void AliHLTCTPData::ResetCounters()
295 {
296   // see header file for function documentation
297   fCounters.Set(gkNCTPTriggerClasses);
298   fCounters.Reset();
299 }
300
301 int AliHLTCTPData::Index(const char* name) const
302 {
303   // see header file for function documentation
304   TObject* obj=fClassIds.FindObject(name);
305   return obj!=NULL?fClassIds.IndexOf(obj):-1;
306 }
307
308 void AliHLTCTPData::Increment(const char* classIds)
309 {
310   // see header file for function documentation
311   TString string=classIds;
312   TObjArray* classEntries=string.Tokenize(",");
313   if (classEntries) {
314     for (int i=0; i<classEntries->GetEntries(); i++) {
315       int index=Index(((TObjString*)classEntries->At(i))->GetString().Data());
316       if (index>=0 && index<fCounters.GetSize()) fCounters[index]++;
317     }
318     delete classEntries;
319   }
320 }
321
322 void AliHLTCTPData::Increment(AliHLTUInt64_t triggerPattern)
323 {
324   // see header file for function documentation
325   AliHLTUInt64_t pattern=triggerPattern&fMask;
326   for (int i=0; i<fCounters.GetSize(); i++) {
327     if ((pattern&((AliHLTUInt64_t)0x1<<i))==0) continue;
328     fCounters[i]++;    
329   }
330 }
331
332 void AliHLTCTPData::Increment(int classIdx)
333 {
334   // see header file for function documentation
335   if (classIdx<fCounters.GetSize() &&
336       (fMask&((AliHLTUInt64_t)0x1<<classIdx))) {
337     fCounters[classIdx]++;    
338   }
339   
340 }
341
342 int AliHLTCTPData::Increment(AliHLTComponentTriggerData& trigData)
343 {
344   // see header file for function documentation
345   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
346     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
347     return -EBADF;
348   }
349
350   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
351   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
352   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
353   triggerMask<<=32;
354   triggerMask|=evtData->fCommonHeader[5];
355
356   if (fMask!=0 && (triggerMask & fMask)==0) {
357     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask);
358     for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
359   }
360   Increment(triggerMask);
361   return 0;
362 }
363
364 AliHLTUInt64_t AliHLTCTPData::Counter(int index) const
365 {
366   // see header file for function documentation
367   if (index>=0 && index<Counters().GetSize()) return Counters()[index];
368   return 0;
369 }
370
371 AliHLTUInt64_t AliHLTCTPData::Counter(const char* classId) const
372 {
373   // see header file for function documentation
374   return Counter(Index(classId));
375 }
376
377 const char* AliHLTCTPData::Name(int index) const
378 {
379   // see header file for function documentation
380   if (index>fClassIds.GetLast()) return NULL;
381   return fClassIds.At(index)->GetName();
382 }
383
384 AliHLTEventDDL AliHLTCTPData::ReadoutList(const AliHLTComponentTriggerData& trigData) const
385 {
386   // see header file for function documentation
387   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
388     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
389     AliHLTEventDDL dummy;
390     memset(&dummy, 0, sizeof(AliHLTEventDDL));
391     return dummy;
392   }
393
394   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
395   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
396   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
397   triggerMask<<=32;
398   triggerMask|=evtData->fCommonHeader[5];
399
400   if (fMask!=0 && (triggerMask & fMask)==0) {
401     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask);
402     for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
403   }
404
405   // take an 'OR' of all active trigger classes 
406   AliHLTReadoutList list;
407   for (int i=0; i<gkNCTPTriggerClasses; i++) {
408     if (i>fClassIds.GetLast()) break;
409     if ((triggerMask&((AliHLTUInt64_t)0x1<<i))==0) continue;
410     AliHLTReadoutList* tcrl=(AliHLTReadoutList*)fClassIds.At(i);
411     list.OrEq(*tcrl);
412   }
413
414   return list;
415 }
416
417 void AliHLTCTPData::Print(Option_t* /*option*/) const
418 {
419   // see header file for function documentation
420   cout << GetTitle() << endl;
421   cout << "\tactive trigger mask: 0x" << hex << fTriggers << dec << endl;
422   int count=0;
423   for (int i=0; i<gkNCTPTriggerClasses; i++) {
424     if (i>=Counters().GetSize()) break;
425     if (i>fClassIds.GetLast()) break;
426     if ((fMask&((AliHLTUInt64_t)0x1<<i))==0) continue;
427     count++;
428     cout << "\t" << i << "\t" << Name(i) << "\t" << Counter(i) << endl;
429   }
430   if (count==0) cout << "\t(none)" << endl;
431 }