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