6611f3271633946fee8b7f9db8c4d31f5aaac8b9
[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 "AliHLTReadoutList.h"
28 #include "TClass.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(AliHLTReadoutList::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(AliHLTReadoutList::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   HLTImportant("Parameter: %s", ctpString);
72
73   fMask=0;
74   fClassIds.Delete();
75   fClassIds.ExpandCreate(gkNCTPTriggerClasses);
76
77   // general format of the CTP_TRIGGER_CLASS parameter
78   // <bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,<bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,...
79   HLTDebug(": %s", ctpString);
80   TString string=ctpString;
81   if (string.BeginsWith("CTP_TRIGGER_CLASS=")) string.ReplaceAll("CTP_TRIGGER_CLASS=", "");
82   TObjArray* classEntries=string.Tokenize(",");
83   if (classEntries) {
84     enum {kBit=0, kName, kDetectors};
85     for (int i=0; i<classEntries->GetEntries(); i++) {
86       TString entry=((TObjString*)classEntries->At(i))->GetString();
87       TObjArray* entryParams=entry.Tokenize(":");
88       if (entryParams) {
89         if (entryParams->GetEntries()==3 &&
90             (((TObjString*)entryParams->At(kBit))->GetString()).IsDigit()) {
91           int index=(((TObjString*)entryParams->At(kBit))->GetString()).Atoi();
92           if (index<gkNCTPTriggerClasses) {
93             AliHLTReadoutList* pCTPClass=dynamic_cast<AliHLTReadoutList*>(fClassIds.At(index));
94             if (pCTPClass) {
95               fMask|=(AliHLTUInt64_t)0x1 << index;
96               pCTPClass->SetTitle("CTP Class");
97               pCTPClass->SetName((((TObjString*)entryParams->At(kName))->GetString()).Data());
98               TObjArray* detectors=(((TObjString*)entryParams->At(kDetectors))->GetString()).Tokenize("-");
99               if (detectors) {
100                 for (int dix=0; dix<detectors->GetEntriesFast(); dix++) {
101                   if (!(((TObjString*)detectors->At(dix))->GetString()).IsDigit()) {
102                     HLTError("invalid detector list format: trigger class entry %s", entry.Data());
103                     break;
104                   }
105                   // see AliHLTReadoutList::EDetectorId for defines of detectors
106                   pCTPClass->Enable(0x1<<(((TObjString*)detectors->At(dix))->GetString()).Atoi());
107                 }
108                 delete detectors;
109               }
110             } else {
111             }
112           } else {
113             // the trigger bitfield is fixed to 50 bits (gkNCTPTriggerClasses)
114             HLTError("invalid trigger class entry %s, index width of trigger bitfield exceeded (%d)", entry.Data(), gkNCTPTriggerClasses);
115           }
116         } else {
117           HLTError("invalid trigger class entry %s", entry.Data());
118         }
119         delete entryParams;
120       }
121     }
122     delete classEntries;
123   }
124
125   ResetCounters();
126
127   return 0;
128 }
129
130 bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, AliHLTComponentTriggerData& trigData) const
131 {
132   // see header file for function documentation
133   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
134     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
135     return false;
136   }
137
138   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
139   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
140   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
141   triggerMask<<=32;
142   triggerMask|=evtData->fCommonHeader[5];
143
144   if (fMask!=0 && (triggerMask & fMask)==0) {
145     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask);
146     for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
147     return false;
148   }
149
150   // use a TFormula to interprete the expression
151   // all classname are replaced by '[n]' which means the n'th parameter in the formula
152   // the parameters are set to 0 or 1 depending on the bit in the trigger mask
153   //
154   // TODO: this will most likely fail for class names like 'base', 'baseA', 'baseB'
155   // the class names must be fully unique, none must be contained as substring in
156   // another class name. Probably not needed for the moment but needs to be extended.
157   vector<Double_t> par;
158   TString condition=expression;
159   for (int i=0; i<gkNCTPTriggerClasses; i++) {
160     const char* className=Name(i);
161     if (className && strlen(className)>0) {
162       //HLTDebug("checking trigger class %s", className.Data());
163       if (condition.Contains(className)) {
164         TString replace; replace.Form("[%d]", par.size());
165         //HLTDebug("replacing %s with %s in \"%s\"", className.Data(), replace.Data(), condition.Data());
166         condition.ReplaceAll(className, replace);
167         if (triggerMask&((AliHLTUInt64_t)0x1<<i)) par.push_back(1.0);
168         else par.push_back(0.0);
169       }
170     }
171   }
172
173   TFormula form("trigger expression", condition);
174   if (form.Compile()!=0) {
175     HLTError("invalid expression %s", expression);
176     return false;
177   }
178   if (form.EvalPar(&par[0], &par[0])>0.5) return true;
179   return false;
180 }
181
182 void AliHLTCTPData::ResetCounters()
183 {
184   // see header file for function documentation
185   fCounters.Set(gkNCTPTriggerClasses);
186   fCounters.Reset();
187 }
188
189 int AliHLTCTPData::Index(const char* name) const
190 {
191   // see header file for function documentation
192   TObject* obj=fClassIds.FindObject(name);
193   return obj!=NULL?fClassIds.IndexOf(obj):-1;
194 }
195
196 void AliHLTCTPData::Increment(const char* classIds)
197 {
198   // see header file for function documentation
199   TString string=classIds;
200   TObjArray* classEntries=string.Tokenize(",");
201   if (classEntries) {
202     for (int i=0; i<classEntries->GetEntries(); i++) {
203       int index=Index(((TObjString*)classEntries->At(i))->GetString().Data());
204       if (index>=0 && index<fCounters.GetSize()) fCounters[index]++;
205     }
206     delete classEntries;
207   }
208 }
209
210 void AliHLTCTPData::Increment(AliHLTUInt64_t triggerPattern)
211 {
212   // see header file for function documentation
213   AliHLTUInt64_t pattern=triggerPattern&fMask;
214   for (int i=0; i<fCounters.GetSize(); i++) {
215     if ((pattern&((AliHLTUInt64_t)0x1<<i))==0) continue;
216     fCounters[i]++;    
217   }
218 }
219
220 void AliHLTCTPData::Increment(int classIdx)
221 {
222   // see header file for function documentation
223   if (classIdx<fCounters.GetSize() &&
224       (fMask&((AliHLTUInt64_t)0x1<<classIdx))) {
225     fCounters[classIdx]++;    
226   }
227   
228 }
229
230 int AliHLTCTPData::Increment(AliHLTComponentTriggerData& trigData)
231 {
232   // see header file for function documentation
233   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
234     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
235     return -EBADF;
236   }
237
238   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
239   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
240   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
241   triggerMask<<=32;
242   triggerMask|=evtData->fCommonHeader[5];
243
244   if (fMask!=0 && (triggerMask & fMask)==0) {
245     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask);
246     for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
247   }
248   Increment(triggerMask);
249   return 0;
250 }
251
252 AliHLTUInt64_t AliHLTCTPData::Counter(int index) const
253 {
254   // see header file for function documentation
255   if (index>=0 && index<Counters().GetSize()) return Counters()[index];
256   return 0;
257 }
258
259 AliHLTUInt64_t AliHLTCTPData::Counter(const char* classId) const
260 {
261   // see header file for function documentation
262   return Counter(Index(classId));
263 }
264
265 const char* AliHLTCTPData::Name(int index) const
266 {
267   // see header file for function documentation
268   if (index>fClassIds.GetLast()) return NULL;
269   return fClassIds.At(index)->GetName();
270 }
271
272 AliHLTEventDDL AliHLTCTPData::ReadoutList(const AliHLTComponentTriggerData& trigData) const
273 {
274   // see header file for function documentation
275   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
276     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
277     AliHLTEventDDL dummy;
278     memset(&dummy, 0, sizeof(AliHLTEventDDL));
279     return dummy;
280   }
281
282   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
283   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
284   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
285   triggerMask<<=32;
286   triggerMask|=evtData->fCommonHeader[5];
287
288   if (fMask!=0 && (triggerMask & fMask)==0) {
289     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask);
290     for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
291   }
292
293   // take an 'OR' of all active trigger classes 
294   AliHLTReadoutList list;
295   for (int i=0; i<gkNCTPTriggerClasses; i++) {
296     if (i>fClassIds.GetLast()) break;
297     if ((triggerMask&((AliHLTUInt64_t)0x1<<i))==0) continue;
298     AliHLTReadoutList* tcrl=(AliHLTReadoutList*)fClassIds.At(i);
299     // 2009-08-27: this is a temorary bugfix:
300     // the operator functions of the AliHLTReadoutList class did not work
301     // when running online on the HLT cluster. The fix for the moment is
302     // to send out the readout list only for the first matching trigger
303     // class instead of merging the list. This is sufficient for the
304     // current trigger setups but needs to be corrected
305     return *tcrl;
306     list|=*tcrl;
307   }
308
309   return list;
310 }
311
312 void AliHLTCTPData::Print(Option_t* /*option*/) const
313 {
314   // see header file for function documentation
315   cout << "CTP counters:" << endl;
316   int count=0;
317   for (int i=0; i<gkNCTPTriggerClasses; i++) {
318     if (i>=Counters().GetSize()) break;
319     if (i>fClassIds.GetLast()) break;
320     if ((fMask&((AliHLTUInt64_t)0x1<<i))==0) continue;
321     count++;
322     cout << "\t" << i << "\t" << Name(i) << "\t" << Counter(i) << endl;
323   }
324   if (count==0) cout << "\t(none)" << endl;
325 }