Debug msg
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTCTPData.cxx
CommitLineData
1dbbd625 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> *
1dbbd625 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
ffda78e3 19// @file AliHLTCTPData.cxx
20// @author Matthias Richter
21// @date 2009-08-20
22// @brief Container for CTP trigger classes and counters
23// @note
1dbbd625 24
25#include "AliHLTCTPData.h"
26#include "TClass.h"
1dbbd625 27#include "TObjString.h"
28#include "TFormula.h"
89413559 29#include "AliHLTComponent.h"
16e6f752 30#include "AliHLTCDHWrapper.h"
31#include <limits>
32#include <sstream>
1dbbd625 33
34/** ROOT macro for the implementation of ROOT specific class methods */
35ClassImp(AliHLTCTPData)
36
37AliHLTCTPData::AliHLTCTPData()
1462df14 38 : TNamed("AliHLTCTPData", "HLT counters for the CTP")
1dbbd625 39 , AliHLTLogging()
40 , fMask(0)
edd72347 41 , fTriggers(0)
1462df14 42 , fClassIds(AliHLTReadoutList::Class(), gkNCTPTriggerClasses)
59be6254 43 , fCounters(gkNCTPTriggerClasses)
ffda78e3 44 , fMap()
1dbbd625 45{
ffda78e3 46 // constructor
1dbbd625 47 // see header file for class documentation
48 // or
49 // refer to README to build package
50 // or
51 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
52}
53
54AliHLTCTPData::AliHLTCTPData(const char* parameter)
55 : TNamed("AliHLTCTPData", "HLT counters for the CTP")
56 , AliHLTLogging()
57 , fMask(0)
edd72347 58 , fTriggers(0)
1462df14 59 , fClassIds(AliHLTReadoutList::Class(), gkNCTPTriggerClasses)
59be6254 60 , fCounters(gkNCTPTriggerClasses)
ffda78e3 61 , fMap()
1dbbd625 62{
ffda78e3 63 // constructor, init the CTP trigger classes
1dbbd625 64 InitCTPTriggerClasses(parameter);
65}
66
67AliHLTCTPData::~AliHLTCTPData()
68{
ffda78e3 69 // destructor
1dbbd625 70 fClassIds.Delete();
71}
72
59be6254 73AliHLTCTPData::AliHLTCTPData(const AliHLTCTPData& src)
74 : TNamed(src.GetName(), src.GetTitle())
75 , AliHLTLogging()
76 , fMask(src.Mask())
edd72347 77 , fTriggers(src.fTriggers)
59be6254 78 , fClassIds(src.fClassIds)
79 , fCounters(src.Counters())
ffda78e3 80 , fMap()
59be6254 81{
ffda78e3 82 // copy constructor
83 ReadMap();
59be6254 84}
85
86AliHLTCTPData& AliHLTCTPData::operator=(const AliHLTCTPData& src)
87{
ffda78e3 88 // assignment operator, clone content
59be6254 89 if (this!=&src) {
90 SetName(src.GetName());
91 SetTitle(src.GetTitle());
92 fMask=src.Mask();
93 fClassIds.Delete();
94 fClassIds.ExpandCreate(gkNCTPTriggerClasses);
95 for (int i=0; i<gkNCTPTriggerClasses; i++) {
4a4318fe 96 if (i>src.fClassIds.GetLast()) break;
59be6254 97 ((TNamed*)fClassIds.At(i))->SetName(src.fClassIds.At(i)->GetName());
98 ((TNamed*)fClassIds.At(i))->SetTitle(src.fClassIds.At(i)->GetTitle());
99 }
100 fCounters=src.Counters();
101 }
102
ffda78e3 103 ReadMap();
59be6254 104 return *this;
105}
106
107int AliHLTCTPData::Add(const AliHLTCTPData& src, int factor, int &skipped)
108{
109 // see header file for class documentation
110
111 skipped=0;
112 for (int i=0; i<gkNCTPTriggerClasses; i++) {
113 TString c;
114 c=fClassIds.At(i)->GetName();
115 if (c.IsNull()) continue;
116 if (c.CompareTo(src.fClassIds.At(i)->GetName())==0) {
117 fCounters[i]+=factor*src.Counter(i);
118 } else {
119 skipped++;
120 }
121 }
122 return 0;
123}
124
125AliHLTCTPData& AliHLTCTPData::operator += (const AliHLTCTPData& src)
126{
127 // see header file for class documentation
128
129 int nofInconsistencies=0;
130 Add(src, 1, nofInconsistencies);
131 if (nofInconsistencies>0) {
132 HLTError("Inconsistent operants: skipping %d of %d CTP classes for operation", nofInconsistencies, gkNCTPTriggerClasses);
133 }
134 return *this;
135}
136
137AliHLTCTPData& AliHLTCTPData::operator -= (const AliHLTCTPData& src)
138{
139 // see header file for class documentation
140
141 int nofInconsistencies=0;
142 Add(src, -1, nofInconsistencies);
143 if (nofInconsistencies>0) {
144 HLTError("Inconsistent operants: skipping %d of %d CTP classes for operation", nofInconsistencies, gkNCTPTriggerClasses);
145 }
146 return *this;
147}
148
149AliHLTCTPData AliHLTCTPData::operator + (const AliHLTCTPData& src) const
150{
151 // see header file for class documentation
152
153 AliHLTCTPData result(*this);
154 result+=src;
155 return result;
156}
157
158AliHLTCTPData AliHLTCTPData::operator - (const AliHLTCTPData& src) const
159{
160 // see header file for class documentation
161
162 AliHLTCTPData result(*this);
163 result-=src;
164 return result;
165}
166
1dbbd625 167int AliHLTCTPData::InitCTPTriggerClasses(const char* ctpString)
168{
169 // see header file for function documentation
170 if (!ctpString) return -EINVAL;
171
79e538c6 172 HLTDebug("Parameter: %s", ctpString);
5be104b8 173
1dbbd625 174 fMask=0;
175 fClassIds.Delete();
176 fClassIds.ExpandCreate(gkNCTPTriggerClasses);
177
178 // general format of the CTP_TRIGGER_CLASS parameter
179 // <bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,<bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,...
1dbbd625 180 HLTDebug(": %s", ctpString);
181 TString string=ctpString;
1462df14 182 if (string.BeginsWith("CTP_TRIGGER_CLASS=")) string.ReplaceAll("CTP_TRIGGER_CLASS=", "");
1dbbd625 183 TObjArray* classEntries=string.Tokenize(",");
184 if (classEntries) {
1462df14 185 enum {kBit=0, kName, kDetectors};
77fd699f 186 for (int i=0; i<classEntries->GetEntriesFast(); i++) {
1dbbd625 187 TString entry=((TObjString*)classEntries->At(i))->GetString();
188 TObjArray* entryParams=entry.Tokenize(":");
189 if (entryParams) {
77fd699f 190 if (entryParams->GetEntriesFast()==3 &&
1462df14 191 (((TObjString*)entryParams->At(kBit))->GetString()).IsDigit()) {
192 int index=(((TObjString*)entryParams->At(kBit))->GetString()).Atoi();
1dbbd625 193 if (index<gkNCTPTriggerClasses) {
1462df14 194 AliHLTReadoutList* pCTPClass=dynamic_cast<AliHLTReadoutList*>(fClassIds.At(index));
195 if (pCTPClass) {
16e6f752 196 fMask.set(index);
1462df14 197 pCTPClass->SetTitle("CTP Class");
198 pCTPClass->SetName((((TObjString*)entryParams->At(kName))->GetString()).Data());
199 TObjArray* detectors=(((TObjString*)entryParams->At(kDetectors))->GetString()).Tokenize("-");
200 if (detectors) {
201 for (int dix=0; dix<detectors->GetEntriesFast(); dix++) {
202 if (!(((TObjString*)detectors->At(dix))->GetString()).IsDigit()) {
203 HLTError("invalid detector list format: trigger class entry %s", entry.Data());
204 break;
205 }
206 // see AliHLTReadoutList::EDetectorId for defines of detectors
207 pCTPClass->Enable(0x1<<(((TObjString*)detectors->At(dix))->GetString()).Atoi());
208 }
209 delete detectors;
210 }
211 } else {
212 }
1dbbd625 213 } else {
16e6f752 214 // the trigger bitfield is fixed to 100 bits (gkNCTPTriggerClasses)
1462df14 215 HLTError("invalid trigger class entry %s, index width of trigger bitfield exceeded (%d)", entry.Data(), gkNCTPTriggerClasses);
1dbbd625 216 }
217 } else {
218 HLTError("invalid trigger class entry %s", entry.Data());
219 }
220 delete entryParams;
221 }
222 }
223 delete classEntries;
224 }
225
226 ResetCounters();
ffda78e3 227 ReadMap();
1dbbd625 228
229 return 0;
230}
231
16e6f752 232AliHLTTriggerMask_t AliHLTCTPData::ActiveTriggers(const AliHLTComponentTriggerData& trigData)
e5339167 233{
234 // extract active triggers from the trigger data
16e6f752 235 AliHLTCDHWrapper cdh;
236 if (AliHLTComponent::ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL) != 0) return 0x0;
237 if ((cdh.GetL1TriggerMessage() & 0x1) == 0x1) return 0x0; // invalid for software triggers.
e5339167 238
16e6f752 239 AliHLTTriggerMask_t triggerLow(cdh.GetTriggerClasses()); //low bits
240 AliHLTTriggerMask_t triggerHigh(cdh.GetTriggerClassesNext50()); // high bits
241
242 return triggerLow | (triggerHigh << 50);
e5339167 243}
244
edd72347 245bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, const AliHLTComponentTriggerData& trigData) const
1dbbd625 246{
247 // see header file for function documentation
89413559 248
16e6f752 249 AliHLTCDHWrapper cdh;
89413559 250 if (AliHLTComponent::ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL, true) != 0) return false;
16e6f752 251 if ((cdh.GetL1TriggerMessage() & 0x1) == 0x1) return false; // invalid for software triggers.
252
253 AliHLTTriggerMask_t triggerMask(cdh.GetTriggerClasses());
254 AliHLTTriggerMask_t triggerHigh(cdh.GetTriggerClassesNext50());
255 triggerMask |= (triggerHigh << 50);
1dbbd625 256
257 if (fMask!=0 && (triggerMask & fMask)==0) {
89413559 258 AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
16e6f752 259 HLTWarning("invalid trigger mask %s, unknown CTP trigger, initialized %s",
260 TriggerMaskToString(triggerMask).c_str(), TriggerMaskToString(fMask).c_str() );
d66f4f29 261 for (int i=0; i<evtData->fCommonHeaderWordCnt; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
1dbbd625 262 return false;
263 }
264
edd72347 265 return EvaluateCTPTriggerClass(expression, triggerMask);
266}
267
16e6f752 268bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, AliHLTTriggerMask_t triggerMask) const
edd72347 269{
270 // see header file for function documentation
271
1dbbd625 272 // use a TFormula to interprete the expression
273 // all classname are replaced by '[n]' which means the n'th parameter in the formula
274 // the parameters are set to 0 or 1 depending on the bit in the trigger mask
ffda78e3 275 const vector<unsigned> *pMap=&fMap;
276 vector<unsigned> tmp;
277 if (fMap.size()==0 && fClassIds.GetLast()>=0) {
278 // read map into temporary array and use it
279 ReadMap(tmp);
280 pMap=&tmp;
281 static bool suppressWarning=false;
282 if (!suppressWarning) HLTWarning("map not yet initialized, creating local map (slow), suppressing further warnings");
283 suppressWarning=true;
284 }
1dbbd625 285 vector<Double_t> par;
286 TString condition=expression;
ffda78e3 287 for (unsigned index=0; index<pMap->size(); index++) {
288 const char* className=Name((*pMap)[index]);
1dbbd625 289 if (className && strlen(className)>0) {
290 //HLTDebug("checking trigger class %s", className.Data());
291 if (condition.Contains(className)) {
9678969f 292 TString replace; replace.Form("[%d]", (int)par.size());
1dbbd625 293 //HLTDebug("replacing %s with %s in \"%s\"", className.Data(), replace.Data(), condition.Data());
294 condition.ReplaceAll(className, replace);
16e6f752 295 if ( triggerMask.test((*pMap)[index]) ) par.push_back(1.0);
1dbbd625 296 else par.push_back(0.0);
297 }
298 }
299 }
300
301 TFormula form("trigger expression", condition);
302 if (form.Compile()!=0) {
303 HLTError("invalid expression %s", expression);
304 return false;
305 }
306 if (form.EvalPar(&par[0], &par[0])>0.5) return true;
307 return false;
308}
309
310void AliHLTCTPData::ResetCounters()
311{
312 // see header file for function documentation
313 fCounters.Set(gkNCTPTriggerClasses);
314 fCounters.Reset();
315}
316
317int AliHLTCTPData::Index(const char* name) const
318{
319 // see header file for function documentation
320 TObject* obj=fClassIds.FindObject(name);
321 return obj!=NULL?fClassIds.IndexOf(obj):-1;
322}
323
ffda78e3 324int AliHLTCTPData::CheckTrigger(const char* name) const
325{
326 // check status of a trigger class
327 int index=Index(name);
328 if (index<0) return index;
16e6f752 329 return ( fTriggers.test(index) ? 1 : 0 );
ffda78e3 330}
331
1dbbd625 332void AliHLTCTPData::Increment(const char* classIds)
333{
334 // see header file for function documentation
335 TString string=classIds;
336 TObjArray* classEntries=string.Tokenize(",");
337 if (classEntries) {
77fd699f 338 for (int i=0; i<classEntries->GetEntriesFast(); i++) {
1dbbd625 339 int index=Index(((TObjString*)classEntries->At(i))->GetString().Data());
340 if (index>=0 && index<fCounters.GetSize()) fCounters[index]++;
341 }
342 delete classEntries;
343 }
344}
345
16e6f752 346void AliHLTCTPData::Increment(AliHLTTriggerMask_t triggerPattern)
1dbbd625 347{
348 // see header file for function documentation
16e6f752 349 AliHLTTriggerMask_t pattern=triggerPattern&fMask;
1dbbd625 350 for (int i=0; i<fCounters.GetSize(); i++) {
16e6f752 351 if (!pattern.test(i)) continue;
1dbbd625 352 fCounters[i]++;
353 }
354}
355
356void AliHLTCTPData::Increment(int classIdx)
357{
358 // see header file for function documentation
359 if (classIdx<fCounters.GetSize() &&
16e6f752 360 fMask.test(classIdx)) {
1dbbd625 361 fCounters[classIdx]++;
362 }
363
364}
365
366int AliHLTCTPData::Increment(AliHLTComponentTriggerData& trigData)
367{
368 // see header file for function documentation
16e6f752 369 AliHLTCDHWrapper cdh;
89413559 370 int result = AliHLTComponent::ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL, true);
371 if (result != 0) return result;
16e6f752 372 if ((cdh.GetL1TriggerMessage() & 0x1) == 0x1) return 0; // invalid for software triggers.
1dbbd625 373
16e6f752 374 AliHLTTriggerMask_t triggerMask(cdh.GetTriggerClasses());
375 AliHLTTriggerMask_t triggerHigh(cdh.GetTriggerClassesNext50());
376 triggerMask |= (triggerHigh << 50);
377
378 if (fMask.any() && (triggerMask & fMask).none()) {
89413559 379 AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
16e6f752 380 HLTWarning("invalid trigger mask %s, unknown CTP trigger, initialized %s",
381 TriggerMaskToString(triggerMask).c_str(), TriggerMaskToString(fMask).c_str());
d66f4f29 382 for (int i=0; i<evtData->fCommonHeaderWordCnt; i++)
16e6f752 383 HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
1dbbd625 384 }
385 Increment(triggerMask);
386 return 0;
387}
388
389AliHLTUInt64_t AliHLTCTPData::Counter(int index) const
390{
391 // see header file for function documentation
392 if (index>=0 && index<Counters().GetSize()) return Counters()[index];
393 return 0;
394}
395
396AliHLTUInt64_t AliHLTCTPData::Counter(const char* classId) const
397{
398 // see header file for function documentation
399 return Counter(Index(classId));
400}
401
402const char* AliHLTCTPData::Name(int index) const
403{
404 // see header file for function documentation
405 if (index>fClassIds.GetLast()) return NULL;
406 return fClassIds.At(index)->GetName();
407}
408
ffda78e3 409int AliHLTCTPData::ReadMap(vector<unsigned> &map) const
410{
411 // read the index map for class names
412 // for nested class names (e.g. 'myclass' is contained in
413 // 'myclassA') the longer names is added first to the map.
414 for (int index=0; index<=fClassIds.GetLast(); index++) {
415 vector<unsigned>::iterator element=map.begin();
416 for (; element!=map.end(); element++) {
417 TString name=Name(index);
418 if (name.Contains(Name(*element))) {
419 // current name contains another one already in the map
420 // -> add before and go to next entry
421 element=map.insert(element, index);
422 break;
423 }
424 }
425
426 if (element==map.end()) {
427 // unique class name, append to map
428 map.push_back(index);
429 }
430 }
431 return 0;
432}
433
434
89413559 435AliHLTReadoutList AliHLTCTPData::ReadoutList(const AliHLTComponentTriggerData& trigData) const
1462df14 436{
437 // see header file for function documentation
1462df14 438
16e6f752 439 AliHLTCDHWrapper cdh;
89413559 440 if (AliHLTComponent::ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL, true) != 0) return AliHLTReadoutList();
ad1d7043 441 // Check if we are dealing with a software trigger. If so then we need to return
442 // a readout list with everything set because the CTP trigger bits are invalid.
443 // Thus we assume that everything should be read out.
16e6f752 444 if ((cdh.GetL1TriggerMessage() & 0x1) == 0x1) return ~ AliHLTReadoutList();
1462df14 445
16e6f752 446 AliHLTTriggerMask_t triggerMask(cdh.GetTriggerClasses());
447 AliHLTTriggerMask_t triggerHigh(cdh.GetTriggerClassesNext50());
448 triggerMask |= (triggerHigh << 50);
449
450 if (fMask.any() && (triggerMask & fMask).none()) {
89413559 451 AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
16e6f752 452 HLTWarning("invalid trigger mask %s, unknown CTP trigger, initialized %s",
453 TriggerMaskToString(triggerMask).c_str(), TriggerMaskToString(fMask).c_str());
d66f4f29 454 for (int i=0; i<evtData->fCommonHeaderWordCnt; i++)
16e6f752 455 HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
5be104b8 456 }
457
f11febe7 458 return ReadoutList(triggerMask);
459}
460
16e6f752 461AliHLTReadoutList AliHLTCTPData::ReadoutList(AliHLTTriggerMask_t triggerMask) const
f11febe7 462{
1462df14 463 // take an 'OR' of all active trigger classes
464 AliHLTReadoutList list;
465 for (int i=0; i<gkNCTPTriggerClasses; i++) {
466 if (i>fClassIds.GetLast()) break;
16e6f752 467 if (! triggerMask.test(i)) continue;
5be104b8 468 AliHLTReadoutList* tcrl=(AliHLTReadoutList*)fClassIds.At(i);
45398383 469 list.OrEq(*tcrl);
1462df14 470 }
471
472 return list;
473}
474
f11febe7 475
1dbbd625 476void AliHLTCTPData::Print(Option_t* /*option*/) const
477{
478 // see header file for function documentation
59be6254 479 cout << GetTitle() << endl;
edd72347 480 cout << "\tactive trigger mask: 0x" << hex << fTriggers << dec << endl;
1dbbd625 481 int count=0;
482 for (int i=0; i<gkNCTPTriggerClasses; i++) {
483 if (i>=Counters().GetSize()) break;
484 if (i>fClassIds.GetLast()) break;
16e6f752 485 if (! fMask.test(i)) continue;
1dbbd625 486 count++;
487 cout << "\t" << i << "\t" << Name(i) << "\t" << Counter(i) << endl;
488 }
489 if (count==0) cout << "\t(none)" << endl;
490}
16e6f752 491
492
493std::string AliHLTCTPData::TriggerMaskToString(AliHLTTriggerMask_t mask) const
494{
495 AliHLTTriggerMask_t max(std::numeric_limits<unsigned long>::max());
496 int digits = std::numeric_limits<unsigned long>::digits;
497 int numberOfWords = (mask.size() + digits - 1)/digits;
498 std::stringstream stream;
499 stream << "0x";
500 stream << std::hex << std::right;
501 for(int i=numberOfWords-1; i>=0; --i){
502 stream.width(digits/4);
503 stream.fill('0');
504 stream << ((mask >> (digits*i)) & max).to_ulong() << " ";
505 }
506 return stream.str();
507}
508