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