#include "AliHLTCTPData.h"
#include "TClass.h"
#include "TObjString.h"
#include "TFormula.h"
#include "AliHLTComponent.h"
#include "AliHLTCDHWrapper.h"
#include <limits>
#include <sstream>
ClassImp(AliHLTCTPData)
AliHLTCTPData::AliHLTCTPData()
: TNamed("AliHLTCTPData", "HLT counters for the CTP")
, AliHLTLogging()
, fMask(0)
, fTriggers(0)
, fClassIds(AliHLTReadoutList::Class(), gkNCTPTriggerClasses)
, fCounters(gkNCTPTriggerClasses)
, fMap()
{
}
AliHLTCTPData::AliHLTCTPData(const char* parameter)
: TNamed("AliHLTCTPData", "HLT counters for the CTP")
, AliHLTLogging()
, fMask(0)
, fTriggers(0)
, fClassIds(AliHLTReadoutList::Class(), gkNCTPTriggerClasses)
, fCounters(gkNCTPTriggerClasses)
, fMap()
{
InitCTPTriggerClasses(parameter);
}
AliHLTCTPData::~AliHLTCTPData()
{
fClassIds.Delete();
}
AliHLTCTPData::AliHLTCTPData(const AliHLTCTPData& src)
: TNamed(src.GetName(), src.GetTitle())
, AliHLTLogging()
, fMask(src.Mask())
, fTriggers(src.fTriggers)
, fClassIds(src.fClassIds)
, fCounters(src.Counters())
, fMap()
{
ReadMap();
}
AliHLTCTPData& AliHLTCTPData::operator=(const AliHLTCTPData& src)
{
if (this!=&src) {
SetName(src.GetName());
SetTitle(src.GetTitle());
fMask=src.Mask();
fClassIds.Delete();
fClassIds.ExpandCreate(gkNCTPTriggerClasses);
for (int i=0; i<gkNCTPTriggerClasses; i++) {
if (i>src.fClassIds.GetLast()) break;
((TNamed*)fClassIds.At(i))->SetName(src.fClassIds.At(i)->GetName());
((TNamed*)fClassIds.At(i))->SetTitle(src.fClassIds.At(i)->GetTitle());
}
fCounters=src.Counters();
}
ReadMap();
return *this;
}
int AliHLTCTPData::Add(const AliHLTCTPData& src, int factor, int &skipped)
{
skipped=0;
for (int i=0; i<gkNCTPTriggerClasses; i++) {
TString c;
c=fClassIds.At(i)->GetName();
if (c.IsNull()) continue;
if (c.CompareTo(src.fClassIds.At(i)->GetName())==0) {
fCounters[i]+=factor*src.Counter(i);
} else {
skipped++;
}
}
return 0;
}
AliHLTCTPData& AliHLTCTPData::operator += (const AliHLTCTPData& src)
{
int nofInconsistencies=0;
Add(src, 1, nofInconsistencies);
if (nofInconsistencies>0) {
HLTError("Inconsistent operants: skipping %d of %d CTP classes for operation", nofInconsistencies, gkNCTPTriggerClasses);
}
return *this;
}
AliHLTCTPData& AliHLTCTPData::operator -= (const AliHLTCTPData& src)
{
int nofInconsistencies=0;
Add(src, -1, nofInconsistencies);
if (nofInconsistencies>0) {
HLTError("Inconsistent operants: skipping %d of %d CTP classes for operation", nofInconsistencies, gkNCTPTriggerClasses);
}
return *this;
}
AliHLTCTPData AliHLTCTPData::operator + (const AliHLTCTPData& src) const
{
AliHLTCTPData result(*this);
result+=src;
return result;
}
AliHLTCTPData AliHLTCTPData::operator - (const AliHLTCTPData& src) const
{
AliHLTCTPData result(*this);
result-=src;
return result;
}
int AliHLTCTPData::InitCTPTriggerClasses(const char* ctpString)
{
if (!ctpString) return -EINVAL;
HLTImportant("Parameter: %s", ctpString);
fMask=0;
fClassIds.Delete();
fClassIds.ExpandCreate(gkNCTPTriggerClasses);
HLTDebug(": %s", ctpString);
TString string=ctpString;
if (string.BeginsWith("CTP_TRIGGER_CLASS=")) string.ReplaceAll("CTP_TRIGGER_CLASS=", "");
TObjArray* classEntries=string.Tokenize(",");
if (classEntries) {
enum {kBit=0, kName, kDetectors};
for (int i=0; i<classEntries->GetEntriesFast(); i++) {
TString entry=((TObjString*)classEntries->At(i))->GetString();
TObjArray* entryParams=entry.Tokenize(":");
if (entryParams) {
if (entryParams->GetEntriesFast()==3 &&
(((TObjString*)entryParams->At(kBit))->GetString()).IsDigit()) {
int index=(((TObjString*)entryParams->At(kBit))->GetString()).Atoi();
if (index<gkNCTPTriggerClasses) {
AliHLTReadoutList* pCTPClass=dynamic_cast<AliHLTReadoutList*>(fClassIds.At(index));
if (pCTPClass) {
fMask.set(index);
pCTPClass->SetTitle("CTP Class");
pCTPClass->SetName((((TObjString*)entryParams->At(kName))->GetString()).Data());
TObjArray* detectors=(((TObjString*)entryParams->At(kDetectors))->GetString()).Tokenize("-");
if (detectors) {
for (int dix=0; dix<detectors->GetEntriesFast(); dix++) {
if (!(((TObjString*)detectors->At(dix))->GetString()).IsDigit()) {
HLTError("invalid detector list format: trigger class entry %s", entry.Data());
break;
}
pCTPClass->Enable(0x1<<(((TObjString*)detectors->At(dix))->GetString()).Atoi());
}
delete detectors;
}
} else {
}
} else {
HLTError("invalid trigger class entry %s, index width of trigger bitfield exceeded (%d)", entry.Data(), gkNCTPTriggerClasses);
}
} else {
HLTError("invalid trigger class entry %s", entry.Data());
}
delete entryParams;
}
}
delete classEntries;
}
ResetCounters();
ReadMap();
return 0;
}
AliHLTTriggerMask_t AliHLTCTPData::ActiveTriggers(const AliHLTComponentTriggerData& trigData)
{
AliHLTCDHWrapper cdh;
if (AliHLTComponent::ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL) != 0) return 0x0;
if ((cdh.GetL1TriggerMessage() & 0x1) == 0x1) return 0x0;
AliHLTTriggerMask_t triggerLow(cdh.GetTriggerClasses());
AliHLTTriggerMask_t triggerHigh(cdh.GetTriggerClassesNext50());
return triggerLow | (triggerHigh << 50);
}
bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, const AliHLTComponentTriggerData& trigData) const
{
AliHLTCDHWrapper cdh;
if (AliHLTComponent::ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL, true) != 0) return false;
if ((cdh.GetL1TriggerMessage() & 0x1) == 0x1) return false;
AliHLTTriggerMask_t triggerMask(cdh.GetTriggerClasses());
AliHLTTriggerMask_t triggerHigh(cdh.GetTriggerClassesNext50());
triggerMask |= (triggerHigh << 50);
if (fMask!=0 && (triggerMask & fMask)==0) {
AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
HLTWarning("invalid trigger mask %s, unknown CTP trigger, initialized %s",
TriggerMaskToString(triggerMask).c_str(), TriggerMaskToString(fMask).c_str() );
for (int i=0; i<gkAliHLTCommonHeaderCount; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
return false;
}
return EvaluateCTPTriggerClass(expression, triggerMask);
}
bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, AliHLTTriggerMask_t triggerMask) const
{
const vector<unsigned> *pMap=&fMap;
vector<unsigned> tmp;
if (fMap.size()==0 && fClassIds.GetLast()>=0) {
ReadMap(tmp);
pMap=&tmp;
static bool suppressWarning=false;
if (!suppressWarning) HLTWarning("map not yet initialized, creating local map (slow), suppressing further warnings");
suppressWarning=true;
}
vector<Double_t> par;
TString condition=expression;
for (unsigned index=0; index<pMap->size(); index++) {
const char* className=Name((*pMap)[index]);
if (className && strlen(className)>0) {
if (condition.Contains(className)) {
TString replace; replace.Form("[%d]", (int)par.size());
condition.ReplaceAll(className, replace);
if ( triggerMask.test((*pMap)[index]) ) par.push_back(1.0);
else par.push_back(0.0);
}
}
}
TFormula form("trigger expression", condition);
if (form.Compile()!=0) {
HLTError("invalid expression %s", expression);
return false;
}
if (form.EvalPar(&par[0], &par[0])>0.5) return true;
return false;
}
void AliHLTCTPData::ResetCounters()
{
fCounters.Set(gkNCTPTriggerClasses);
fCounters.Reset();
}
int AliHLTCTPData::Index(const char* name) const
{
TObject* obj=fClassIds.FindObject(name);
return obj!=NULL?fClassIds.IndexOf(obj):-1;
}
int AliHLTCTPData::CheckTrigger(const char* name) const
{
int index=Index(name);
if (index<0) return index;
return ( fTriggers.test(index) ? 1 : 0 );
}
void AliHLTCTPData::Increment(const char* classIds)
{
TString string=classIds;
TObjArray* classEntries=string.Tokenize(",");
if (classEntries) {
for (int i=0; i<classEntries->GetEntriesFast(); i++) {
int index=Index(((TObjString*)classEntries->At(i))->GetString().Data());
if (index>=0 && index<fCounters.GetSize()) fCounters[index]++;
}
delete classEntries;
}
}
void AliHLTCTPData::Increment(AliHLTTriggerMask_t triggerPattern)
{
AliHLTTriggerMask_t pattern=triggerPattern&fMask;
for (int i=0; i<fCounters.GetSize(); i++) {
if (!pattern.test(i)) continue;
fCounters[i]++;
}
}
void AliHLTCTPData::Increment(int classIdx)
{
if (classIdx<fCounters.GetSize() &&
fMask.test(classIdx)) {
fCounters[classIdx]++;
}
}
int AliHLTCTPData::Increment(AliHLTComponentTriggerData& trigData)
{
AliHLTCDHWrapper cdh;
int result = AliHLTComponent::ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL, true);
if (result != 0) return result;
if ((cdh.GetL1TriggerMessage() & 0x1) == 0x1) return 0;
AliHLTTriggerMask_t triggerMask(cdh.GetTriggerClasses());
AliHLTTriggerMask_t triggerHigh(cdh.GetTriggerClassesNext50());
triggerMask |= (triggerHigh << 50);
if (fMask.any() && (triggerMask & fMask).none()) {
AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
HLTWarning("invalid trigger mask %s, unknown CTP trigger, initialized %s",
TriggerMaskToString(triggerMask).c_str(), TriggerMaskToString(fMask).c_str());
for (int i=0; i<gkAliHLTCommonHeaderCount; i++)
HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
}
Increment(triggerMask);
return 0;
}
AliHLTUInt64_t AliHLTCTPData::Counter(int index) const
{
if (index>=0 && index<Counters().GetSize()) return Counters()[index];
return 0;
}
AliHLTUInt64_t AliHLTCTPData::Counter(const char* classId) const
{
return Counter(Index(classId));
}
const char* AliHLTCTPData::Name(int index) const
{
if (index>fClassIds.GetLast()) return NULL;
return fClassIds.At(index)->GetName();
}
int AliHLTCTPData::ReadMap(vector<unsigned> &map) const
{
for (int index=0; index<=fClassIds.GetLast(); index++) {
vector<unsigned>::iterator element=map.begin();
for (; element!=map.end(); element++) {
TString name=Name(index);
if (name.Contains(Name(*element))) {
element=map.insert(element, index);
break;
}
}
if (element==map.end()) {
map.push_back(index);
}
}
return 0;
}
AliHLTReadoutList AliHLTCTPData::ReadoutList(const AliHLTComponentTriggerData& trigData) const
{
AliHLTCDHWrapper cdh;
if (AliHLTComponent::ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL, true) != 0) return AliHLTReadoutList();
if ((cdh.GetL1TriggerMessage() & 0x1) == 0x1) return ~ AliHLTReadoutList();
AliHLTTriggerMask_t triggerMask(cdh.GetTriggerClasses());
AliHLTTriggerMask_t triggerHigh(cdh.GetTriggerClassesNext50());
triggerMask |= (triggerHigh << 50);
if (fMask.any() && (triggerMask & fMask).none()) {
AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
HLTWarning("invalid trigger mask %s, unknown CTP trigger, initialized %s",
TriggerMaskToString(triggerMask).c_str(), TriggerMaskToString(fMask).c_str());
for (int i=0; i<gkAliHLTCommonHeaderCount; i++)
HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
}
return ReadoutList(triggerMask);
}
AliHLTReadoutList AliHLTCTPData::ReadoutList(AliHLTTriggerMask_t triggerMask) const
{
AliHLTReadoutList list;
for (int i=0; i<gkNCTPTriggerClasses; i++) {
if (i>fClassIds.GetLast()) break;
if (! triggerMask.test(i)) continue;
AliHLTReadoutList* tcrl=(AliHLTReadoutList*)fClassIds.At(i);
list.OrEq(*tcrl);
}
return list;
}
void AliHLTCTPData::Print(Option_t* ) const
{
cout << GetTitle() << endl;
cout << "\tactive trigger mask: 0x" << hex << fTriggers << dec << endl;
int count=0;
for (int i=0; i<gkNCTPTriggerClasses; i++) {
if (i>=Counters().GetSize()) break;
if (i>fClassIds.GetLast()) break;
if (! fMask.test(i)) continue;
count++;
cout << "\t" << i << "\t" << Name(i) << "\t" << Counter(i) << endl;
}
if (count==0) cout << "\t(none)" << endl;
}
std::string AliHLTCTPData::TriggerMaskToString(AliHLTTriggerMask_t mask) const
{
AliHLTTriggerMask_t max(std::numeric_limits<unsigned long>::max());
int digits = std::numeric_limits<unsigned long>::digits;
int numberOfWords = (mask.size() + digits - 1)/digits;
std::stringstream stream;
stream << "0x";
stream << std::hex << std::right;
for(int i=numberOfWords-1; i>=0; --i){
stream.width(digits/4);
stream.fill('0');
stream << ((mask >> (digits*i)) & max).to_ulong() << " ";
}
return stream.str();
}