]>
Commit | Line | Data |
---|---|---|
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->GetEntriesFast(); i++) { | |
177 | TString entry=((TObjString*)classEntries->At(i))->GetString(); | |
178 | TObjArray* entryParams=entry.Tokenize(":"); | |
179 | if (entryParams) { | |
180 | if (entryParams->GetEntriesFast()==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->GetEntriesFast(); 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 | return ReadoutList(triggerMask); | |
406 | } | |
407 | ||
408 | AliHLTEventDDL AliHLTCTPData::ReadoutList(AliHLTUInt64_t triggerMask) const | |
409 | { | |
410 | // take an 'OR' of all active trigger classes | |
411 | AliHLTReadoutList list; | |
412 | for (int i=0; i<gkNCTPTriggerClasses; i++) { | |
413 | if (i>fClassIds.GetLast()) break; | |
414 | if ((triggerMask&((AliHLTUInt64_t)0x1<<i))==0) continue; | |
415 | AliHLTReadoutList* tcrl=(AliHLTReadoutList*)fClassIds.At(i); | |
416 | list.OrEq(*tcrl); | |
417 | } | |
418 | ||
419 | return list; | |
420 | } | |
421 | ||
422 | ||
423 | void AliHLTCTPData::Print(Option_t* /*option*/) const | |
424 | { | |
425 | // see header file for function documentation | |
426 | cout << GetTitle() << endl; | |
427 | cout << "\tactive trigger mask: 0x" << hex << fTriggers << dec << endl; | |
428 | int count=0; | |
429 | for (int i=0; i<gkNCTPTriggerClasses; i++) { | |
430 | if (i>=Counters().GetSize()) break; | |
431 | if (i>fClassIds.GetLast()) break; | |
432 | if ((fMask&((AliHLTUInt64_t)0x1<<i))==0) continue; | |
433 | count++; | |
434 | cout << "\t" << i << "\t" << Name(i) << "\t" << Counter(i) << endl; | |
435 | } | |
436 | if (count==0) cout << "\t(none)" << endl; | |
437 | } |