6cc17a857679771dd28700fe3c3b140295d467a7
[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 //*                  Timm Steinbeck <timm@kip.uni-heidelberg.de>           *
9 //*                  for The ALICE HLT Project.                            *
10 //*                                                                        *
11 //* Permission to use, copy, modify and distribute this software and its   *
12 //* documentation strictly for non-commercial purposes is hereby granted   *
13 //* without fee, provided that the above copyright notice appears in all   *
14 //* copies and that both the copyright notice and this permission notice   *
15 //* appear in the supporting documentation. The authors make no claims     *
16 //* about the suitability of this software for any purpose. It is          *
17 //* provided "as is" without express or implied warranty.                  *
18 //**************************************************************************
19
20 /** @file   AliHLTCTPData.cxx
21     @author Matthias Richter
22     @date   2009-08-20
23     @brief  Container for CTP trigger classes and counters
24 */
25
26 #include "AliHLTCTPData.h"
27 #include "TClass.h"
28 #include "TNamed.h"
29 #include "TObjString.h"
30 #include "TFormula.h"
31
32 /** ROOT macro for the implementation of ROOT specific class methods */
33 ClassImp(AliHLTCTPData)
34
35 AliHLTCTPData::AliHLTCTPData()
36 : TNamed("AliHLTCTPData", "HLT counters for the CTP")
37   , AliHLTLogging()
38   , fMask(0)
39   , fClassIds(TNamed::Class(), gkNCTPTriggerClasses)
40   , fCounters()
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   , fClassIds(TNamed::Class(), gkNCTPTriggerClasses)
54   , fCounters()
55 {
56   // see header file for class documentation
57   InitCTPTriggerClasses(parameter);
58 }
59
60 AliHLTCTPData::~AliHLTCTPData()
61 {
62   // see header file for class documentation
63   fClassIds.Delete();
64 }
65
66 int AliHLTCTPData::InitCTPTriggerClasses(const char* ctpString)
67 {
68   // see header file for function documentation
69   if (!ctpString) return -EINVAL;
70
71   fMask=0;
72   fClassIds.Delete();
73   fClassIds.ExpandCreate(gkNCTPTriggerClasses);
74
75   // general format of the CTP_TRIGGER_CLASS parameter
76   // <bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,<bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,...
77   // the detector ids are ignored for the moment
78   HLTDebug(": %s", ctpString);
79   TString string=ctpString;
80   TObjArray* classEntries=string.Tokenize(",");
81   if (classEntries) {
82     for (int i=0; i<classEntries->GetEntries(); i++) {
83       TString entry=((TObjString*)classEntries->At(i))->GetString();
84       TObjArray* entryParams=entry.Tokenize(":");
85       if (entryParams) {
86         if (entryParams->GetEntries()==3 &&
87             (((TObjString*)entryParams->At(0))->GetString()).IsDigit()) {
88           int index=(((TObjString*)entryParams->At(0))->GetString()).Atoi();
89           if (index<gkNCTPTriggerClasses) {
90             fMask|=(AliHLTUInt64_t)0x1 << index;
91             ((TNamed*)fClassIds.At(index))->SetTitle("TriggerClass");
92             ((TNamed*)fClassIds.At(index))->SetName((((TObjString*)entryParams->At(1))->GetString()).Data());
93           } else {
94             // the trigger bitfield is fixed to 50 bits (gkNCTPTriggerClasses)
95             HLTError("invalid trigger class entry %s, index width of trigger bitfield", entry.Data());
96           }
97         } else {
98           HLTError("invalid trigger class entry %s", entry.Data());
99         }
100         delete entryParams;
101       }
102     }
103     delete classEntries;
104   }
105
106   ResetCounters();
107
108   return 0;
109 }
110
111 bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, AliHLTComponentTriggerData& trigData) const
112 {
113   // see header file for function documentation
114   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
115     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
116     return false;
117   }
118
119   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
120   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
121   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6];
122   triggerMask<<=32;
123   triggerMask|=evtData->fCommonHeader[5];
124
125   if (fMask!=0 && (triggerMask & fMask)==0) {
126     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger", triggerMask);
127     return false;
128   }
129
130   // use a TFormula to interprete the expression
131   // all classname are replaced by '[n]' which means the n'th parameter in the formula
132   // the parameters are set to 0 or 1 depending on the bit in the trigger mask
133   //
134   // TODO: this will most likely fail for class names like 'base', 'baseA', 'baseB'
135   // the class names must be fully unique, none must be contained as substring in
136   // another class name. Probably not needed for the moment but needs to be extended.
137   vector<Double_t> par;
138   TString condition=expression;
139   for (int i=0; i<gkNCTPTriggerClasses; i++) {
140     const char* className=Name(i);
141     if (className && strlen(className)>0) {
142       //HLTDebug("checking trigger class %s", className.Data());
143       if (condition.Contains(className)) {
144         TString replace; replace.Form("[%d]", par.size());
145         //HLTDebug("replacing %s with %s in \"%s\"", className.Data(), replace.Data(), condition.Data());
146         condition.ReplaceAll(className, replace);
147         if (triggerMask&((AliHLTUInt64_t)0x1<<i)) par.push_back(1.0);
148         else par.push_back(0.0);
149       }
150     }
151   }
152
153   TFormula form("trigger expression", condition);
154   if (form.Compile()!=0) {
155     HLTError("invalid expression %s", expression);
156     return false;
157   }
158   if (form.EvalPar(&par[0], &par[0])>0.5) return true;
159   return false;
160 }
161
162 void AliHLTCTPData::ResetCounters()
163 {
164   // see header file for function documentation
165   fCounters.Set(gkNCTPTriggerClasses);
166   fCounters.Reset();
167 }
168
169 int AliHLTCTPData::Index(const char* name) const
170 {
171   // see header file for function documentation
172   TObject* obj=fClassIds.FindObject(name);
173   return obj!=NULL?fClassIds.IndexOf(obj):-1;
174 }
175
176 void AliHLTCTPData::Increment(const char* classIds)
177 {
178   // see header file for function documentation
179   TString string=classIds;
180   TObjArray* classEntries=string.Tokenize(",");
181   if (classEntries) {
182     for (int i=0; i<classEntries->GetEntries(); i++) {
183       int index=Index(((TObjString*)classEntries->At(i))->GetString().Data());
184       if (index>=0 && index<fCounters.GetSize()) fCounters[index]++;
185     }
186     delete classEntries;
187   }
188 }
189
190 void AliHLTCTPData::Increment(AliHLTUInt64_t triggerPattern)
191 {
192   // see header file for function documentation
193   AliHLTUInt64_t pattern=triggerPattern&fMask;
194   for (int i=0; i<fCounters.GetSize(); i++) {
195     if ((pattern&((AliHLTUInt64_t)0x1<<i))==0) continue;
196     fCounters[i]++;    
197   }
198 }
199
200 void AliHLTCTPData::Increment(int classIdx)
201 {
202   // see header file for function documentation
203   if (classIdx<fCounters.GetSize() &&
204       (fMask&((AliHLTUInt64_t)0x1<<classIdx))) {
205     fCounters[classIdx]++;    
206   }
207   
208 }
209
210 int AliHLTCTPData::Increment(AliHLTComponentTriggerData& trigData)
211 {
212   // see header file for function documentation
213   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
214     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
215     return -EBADF;
216   }
217
218   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
219   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
220   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6];
221   triggerMask<<=32;
222   triggerMask|=evtData->fCommonHeader[5];
223
224   if (fMask!=0 && (triggerMask & fMask)==0) {
225     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask);
226   }
227   Increment(triggerMask);
228   return 0;
229 }
230
231 AliHLTUInt64_t AliHLTCTPData::Counter(int index) const
232 {
233   // see header file for function documentation
234   if (index>=0 && index<Counters().GetSize()) return Counters()[index];
235   return 0;
236 }
237
238 AliHLTUInt64_t AliHLTCTPData::Counter(const char* classId) const
239 {
240   // see header file for function documentation
241   return Counter(Index(classId));
242 }
243
244 const char* AliHLTCTPData::Name(int index) const
245 {
246   // see header file for function documentation
247   if (index>fClassIds.GetLast()) return NULL;
248   return fClassIds.At(index)->GetName();
249 }
250
251 void AliHLTCTPData::Print(Option_t* /*option*/) const
252 {
253   // see header file for function documentation
254   cout << "CTP counters:" << endl;
255   int count=0;
256   for (int i=0; i<gkNCTPTriggerClasses; i++) {
257     if (i>=Counters().GetSize()) break;
258     if (i>fClassIds.GetLast()) break;
259     if ((fMask&((AliHLTUInt64_t)0x1<<i))==0) continue;
260     count++;
261     cout << "\t" << i << "\t" << Name(i) << "\t" << Counter(i) << endl;
262   }
263   if (count==0) cout << "\t(none)" << endl;
264 }