X-Git-Url: http://git.uio.no/git/?p=u%2Fmrichter%2FAliRoot.git;a=blobdiff_plain;f=RAW%2FAliRawReader.cxx;h=fc0529058a4853dd9e28ca6e4a3fa338d22589a9;hp=2fcdc13b8cf2a1e0229709564e10f51f03882150;hb=47791468b84db3988e4115a27693750a86b571b6;hpb=bea6b2a48b987c82a6e6c8efd8bc0ac1cac9aa0a diff --git a/RAW/AliRawReader.cxx b/RAW/AliRawReader.cxx index 2fcdc13b8cf..fc0529058a4 100644 --- a/RAW/AliRawReader.cxx +++ b/RAW/AliRawReader.cxx @@ -36,56 +36,346 @@ /// /////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include + +#include #include "AliRawReader.h" - - +#include "AliRawReaderFile.h" +#include "AliRawReaderDate.h" +#include "AliRawReaderRoot.h" +#include "AliRawReaderChain.h" +#include "AliDAQ.h" +#include "AliLog.h" + +using std::ifstream; ClassImp(AliRawReader) AliRawReader::AliRawReader() : + fEquipmentIdsIn(NULL), + fEquipmentIdsOut(NULL), + fRequireHeader(kTRUE), fHeader(NULL), + fHeaderV3(NULL), fCount(0), fSelectEquipmentType(-1), fSelectMinEquipmentId(-1), fSelectMaxEquipmentId(-1), fSkipInvalid(kFALSE), - fErrorCode(0) + fSelectEventType(-1), + fSelectTriggerMask(0), + fSelectTriggerExpr(), + fErrorCode(0), + fEventNumber(-1), + fErrorLogs("AliRawDataErrorLog",100), + fHeaderSwapped(NULL), + fHeaderSwappedV3(NULL), + fIsValid(kTRUE), + fIsTriggerClassLoaded(kFALSE) { // default constructor: initialize data members +// Allocate the swapped header in case of Mac +#ifndef R__BYTESWAP + fHeaderSwapped=new AliRawDataHeader(); + fHeaderSwappedV3=new AliRawDataHeaderV3(); +#endif +} +Bool_t AliRawReader::LoadEquipmentIdsMap(const char *fileName) +{ + // Open the mapping file + // and load the mapping data + ifstream input(fileName); + if (input.is_open()) { + Warning("AliRawReader","Equipment ID mapping file is found !"); + const Int_t kMaxDDL = 256; + fEquipmentIdsIn = new TArrayI(kMaxDDL); + fEquipmentIdsOut = new TArrayI(kMaxDDL); + Int_t equipIn, equipOut; + Int_t nIds = 0; + while (input >> equipIn >> equipOut) { + if (nIds >= kMaxDDL) { + Error("AliRawReader","Too many equipment Id mappings found ! Truncating the list !"); + break; + } + fEquipmentIdsIn->AddAt(equipIn,nIds); + fEquipmentIdsOut->AddAt(equipOut,nIds); + nIds++; + } + fEquipmentIdsIn->Set(nIds); + fEquipmentIdsOut->Set(nIds); + input.close(); + return kTRUE; + } + else { + Error("AliRawReader","equipment id map file is not found ! Skipping the mapping !"); + return kFALSE; + } } AliRawReader::AliRawReader(const AliRawReader& rawReader) : TObject(rawReader), + fEquipmentIdsIn(rawReader.fEquipmentIdsIn), + fEquipmentIdsOut(rawReader.fEquipmentIdsOut), + fRequireHeader(rawReader.fRequireHeader), fHeader(rawReader.fHeader), + fHeaderV3(rawReader.fHeaderV3), fCount(rawReader.fCount), fSelectEquipmentType(rawReader.fSelectEquipmentType), fSelectMinEquipmentId(rawReader.fSelectMinEquipmentId), fSelectMaxEquipmentId(rawReader.fSelectMaxEquipmentId), fSkipInvalid(rawReader.fSkipInvalid), - fErrorCode(0) + fSelectEventType(rawReader.fSelectEventType), + fSelectTriggerMask(rawReader.fSelectTriggerMask), + fSelectTriggerExpr(rawReader.fSelectTriggerExpr), + fErrorCode(0), + fEventNumber(-1), + fErrorLogs("AliRawDataErrorLog",100), + fHeaderSwapped(NULL), + fHeaderSwappedV3(NULL), + fIsValid(rawReader.fIsValid), + fIsTriggerClassLoaded(rawReader.fIsTriggerClassLoaded) { // copy constructor - +// Allocate the swapped header in case of Mac +#ifndef R__BYTESWAP + fHeaderSwapped=new AliRawDataHeader(*rawReader.fHeaderSwapped); + fHeaderSwappedV3=new AliRawDataHeader(*rawReader.fHeaderSwappedV3); +#endif } AliRawReader& AliRawReader::operator = (const AliRawReader& rawReader) { // assignment operator + if(&rawReader == this) return *this; + fEquipmentIdsIn = rawReader.fEquipmentIdsIn; + fEquipmentIdsOut = rawReader.fEquipmentIdsOut; fHeader = rawReader.fHeader; + fHeaderV3 = rawReader.fHeaderV3; fCount = rawReader.fCount; fSelectEquipmentType = rawReader.fSelectEquipmentType; fSelectMinEquipmentId = rawReader.fSelectMinEquipmentId; fSelectMaxEquipmentId = rawReader.fSelectMaxEquipmentId; fSkipInvalid = rawReader.fSkipInvalid; + fSelectEventType = rawReader.fSelectEventType; + fSelectTriggerMask = rawReader.fSelectTriggerMask; + fSelectTriggerExpr = rawReader.fSelectTriggerExpr; fErrorCode = rawReader.fErrorCode; + fEventNumber = rawReader.fEventNumber; + fErrorLogs = *((TClonesArray*)rawReader.fErrorLogs.Clone()); + + fIsValid = rawReader.fIsValid; + fIsTriggerClassLoaded = rawReader.fIsTriggerClassLoaded; + return *this; } +AliRawReader::~AliRawReader() +{ + // destructor + // delete the mapping arrays if + // initialized + if (fEquipmentIdsIn) delete fEquipmentIdsIn; + if (fEquipmentIdsOut) delete fEquipmentIdsOut; + fErrorLogs.Delete(); + if (fHeaderSwapped) delete fHeaderSwapped; + if (fHeaderSwappedV3) delete fHeaderSwappedV3; +} + +AliRawReader* AliRawReader::Create(const char *uri) +{ + // RawReader's factory + // It instantiate corresponding raw-reader implementation class object + // depending on the URI provided + // Normal URIs point to files, while the URI starting with + // 'mem://:' or 'mem://' will create + // AliRawReaderDateOnline object which is supposed to be used + // in the online reconstruction + + TString strURI = uri; + + if (strURI.IsNull()) { + AliWarningClass("No raw-reader created"); + return NULL; + } + + TObjArray *fields = strURI.Tokenize("?"); + TString &fileURI = ((TObjString*)fields->At(0))->String(); + + AliRawReader *rawReader = NULL; + if (fileURI.BeginsWith("mem://") || fileURI.BeginsWith("^")) { + if (fileURI.BeginsWith("mem://")) fileURI.ReplaceAll("mem://",""); + AliInfoClass(Form("Creating raw-reader in order to read events in shared memory (option=%s)",fileURI.Data())); + + TPluginManager* pluginManager = gROOT->GetPluginManager(); + TString rawReaderName = "AliRawReaderDateOnline"; + TPluginHandler* pluginHandler = pluginManager->FindHandler("AliRawReader", "online"); + // if not, add a plugin for it + if (!pluginHandler) { + pluginManager->AddHandler("AliRawReader", "online", + "AliRawReaderDateOnline", "RAWDatarecOnline", "AliRawReaderDateOnline(const char*)"); + pluginHandler = pluginManager->FindHandler("AliRawReader", "online"); + } + if (pluginHandler && (pluginHandler->LoadPlugin() == 0)) { + rawReader = (AliRawReader*)pluginHandler->ExecPlugin(1,fileURI.Data()); + } + else { + delete fields; + return NULL; + } + } + else if (fileURI.BeginsWith("amore://")) { + // A special raw-data URL used in case + // the raw-data reading is steered from + // ouside, i.e. from AMORE + fileURI.ReplaceAll("amore://",""); + AliInfoClass("Creating raw-reader in order to read events sent by AMORE"); + rawReader = new AliRawReaderDate((void *)NULL); + } + else if (fileURI.BeginsWith("collection://")) { + fileURI.ReplaceAll("collection://",""); + AliInfoClass(Form("Creating raw-reader in order to read raw-data files collection defined in %s",fileURI.Data())); + rawReader = new AliRawReaderChain(fileURI); + } + else if (fileURI.BeginsWith("raw://run")) { + fileURI.ReplaceAll("raw://run",""); + if (fileURI.IsDigit()) { + rawReader = new AliRawReaderChain(fileURI.Atoi()); + } + else { + AliErrorClass(Form("Invalid syntax: %s",fileURI.Data())); + delete fields; + return NULL; + } + } + else { + AliInfoClass(Form("Creating raw-reader in order to read raw-data file: %s",fileURI.Data())); + TString filename(gSystem->ExpandPathName(fileURI.Data())); + if (filename.EndsWith("/")) { + rawReader = new AliRawReaderFile(filename); + } else if (filename.EndsWith(".root")) { + rawReader = new AliRawReaderRoot(filename); + } else { + rawReader = new AliRawReaderDate(filename); + } + } + + if (!rawReader->IsRawReaderValid()) { + AliErrorClass(Form("Raw-reader is invalid - check the input URI (%s)",fileURI.Data())); + delete rawReader; + delete fields; + return NULL; + } + + // Now apply event selection criteria (if specified) + if (fields->GetEntries() > 1) { + Int_t eventType = -1; + ULong64_t triggerMask = 0; + TString triggerExpr; + for(Int_t i = 1; i < fields->GetEntries(); i++) { + if (!fields->At(i)) continue; + TString &option = ((TObjString*)fields->At(i))->String(); + if (option.BeginsWith("EventType=",TString::kIgnoreCase)) { + option.ReplaceAll("EventType=",""); + eventType = option.Atoi(); + continue; + } + if (option.BeginsWith("Trigger=",TString::kIgnoreCase)) { + option.ReplaceAll("Trigger=",""); + if (option.IsDigit()) { + triggerMask = option.Atoll(); + } + else { + triggerExpr = option.Data(); + } + continue; + } + AliWarningClass(Form("Ignoring invalid event selection option: %s",option.Data())); + } + AliInfoClass(Form("Event selection criteria specified: eventype=%d trigger mask=%llx trigger expression=%s", + eventType,triggerMask,triggerExpr.Data())); + rawReader->SelectEvents(eventType,triggerMask,triggerExpr.Data()); + } + + delete fields; + + return rawReader; +} + +Int_t AliRawReader::GetMappedEquipmentId() const +{ + if (!fEquipmentIdsIn || !fEquipmentIdsOut) { + Error("AliRawReader","equipment Ids mapping is not initialized !"); + return GetEquipmentId(); + } + Int_t equipmentId = GetEquipmentId(); + for(Int_t iId = 0; iId < fEquipmentIdsIn->GetSize(); iId++) { + if (equipmentId == fEquipmentIdsIn->At(iId)) { + equipmentId = fEquipmentIdsOut->At(iId); + break; + } + } + return equipmentId; +} + +Int_t AliRawReader::GetDetectorID() const +{ + // Get the detector ID + // The list of detector IDs + // can be found in AliDAQ.h + Int_t equipmentId; + if (fEquipmentIdsIn && fEquipmentIdsIn) + equipmentId = GetMappedEquipmentId(); + else + equipmentId = GetEquipmentId(); + + if (equipmentId >= 0) { + Int_t ddlIndex; + return AliDAQ::DetectorIDFromDdlID(equipmentId,ddlIndex); + } + else + return -1; +} + +Int_t AliRawReader::GetDDLID() const +{ + // Get the DDL ID (within one sub-detector) + // The list of detector IDs + // can be found in AliDAQ.h + Int_t equipmentId; + if (fEquipmentIdsIn && fEquipmentIdsIn) + equipmentId = GetMappedEquipmentId(); + else + equipmentId = GetEquipmentId(); + + if (equipmentId >= 0) { + Int_t ddlIndex; + AliDAQ::DetectorIDFromDdlID(equipmentId,ddlIndex); + return ddlIndex; + } + else + return -1; +} + +void AliRawReader::Select(const char *detectorName, Int_t minDDLID, Int_t maxDDLID) +{ +// read only data of the detector with the given name and in the given +// range of DDLs (minDDLID <= DDLID <= maxDDLID). +// no selection is applied if a value < 0 is used. + Int_t detectorID = AliDAQ::DetectorID(detectorName); + if(detectorID >= 0) + Select(detectorID,minDDLID,maxDDLID); +} void AliRawReader::Select(Int_t detectorID, Int_t minDDLID, Int_t maxDDLID) { @@ -93,11 +383,17 @@ void AliRawReader::Select(Int_t detectorID, Int_t minDDLID, Int_t maxDDLID) // range of DDLs (minDDLID <= DDLID <= maxDDLID). // no selection is applied if a value < 0 is used. - fSelectEquipmentType = 0; - if (minDDLID < 0) minDDLID = 0; - fSelectMinEquipmentId = (detectorID << 8) + minDDLID; - if (maxDDLID < 0) maxDDLID = 0xFF; - fSelectMaxEquipmentId = (detectorID << 8) + maxDDLID; + fSelectEquipmentType = -1; + + if (minDDLID < 0) + fSelectMinEquipmentId = AliDAQ::DdlIDOffset(detectorID); + else + fSelectMinEquipmentId = AliDAQ::DdlID(detectorID,minDDLID); + + if (maxDDLID < 0) + fSelectMaxEquipmentId = AliDAQ::DdlID(detectorID,AliDAQ::NumberOfDdls(detectorID)-1); + else + fSelectMaxEquipmentId = AliDAQ::DdlID(detectorID,maxDDLID); } void AliRawReader::SelectEquipment(Int_t equipmentType, @@ -112,25 +408,171 @@ void AliRawReader::SelectEquipment(Int_t equipmentType, fSelectMaxEquipmentId = maxEquipmentId; } +void AliRawReader::SelectEvents(Int_t type, ULong64_t triggerMask, + const char *triggerExpr) +{ +// read only events with the given type and optionally +// trigger mask. +// no selection is applied if value = 0 is used. +// Trigger selection can be done via string (triggerExpr) +// which defines the trigger logic to be used. It works only +// after LoadTriggerClass() method is called for all involved +// trigger classes. + + fSelectEventType = type; + fSelectTriggerMask = triggerMask; + if (triggerExpr) fSelectTriggerExpr = triggerExpr; +} + +void AliRawReader::LoadTriggerClass(const char* name, Int_t index) +{ + // Loads the list of trigger classes defined. + // Used in conjunction with IsEventSelected in the + // case when the trigger selection is given by + // fSelectedTriggerExpr + + if (fSelectTriggerExpr.IsNull()) return; + + fIsTriggerClassLoaded = kTRUE; + + if (index >= 0) + fSelectTriggerExpr.ReplaceAll(name,Form("[%d]",index)); + else + fSelectTriggerExpr.ReplaceAll(name,"0"); +} + +void AliRawReader::LoadTriggerAlias(const THashList *lst) +{ + // Loads the list of trigger aliases defined. + // Replaces the alias by the OR of the triggers included in it. + // The subsiquent call to LoadTriggerClass is needed + // to obtain the final expression in + // fSelectedTriggerExpr + + if (fSelectTriggerExpr.IsNull()) return; + + // Make a THashList alias -> trigger classes + + THashList alias2trig; + TIter iter(lst); + TNamed *nmd = 0; + + // Loop on triggers + + while((nmd = dynamic_cast(iter.Next()))){ + + TString aliasList(nmd->GetTitle()); + TObjArray* arrAliases = aliasList.Tokenize(','); + Int_t nAliases = arrAliases->GetEntries(); + + // Loop on aliases for the current trigger + for(Int_t i=0; iAt(i); + + // Find the current alias in the hash list. If it is not there, add TNamed entry + TNamed * inlist = (TNamed*)alias2trig.FindObject((alias->GetString()).Data()); + if (!inlist) { + inlist = new TNamed((alias->GetString()).Data(),nmd->GetName()); + alias2trig.Add(inlist); + } + else { + TString tt(inlist->GetTitle()); + tt += " || "; + tt += nmd->GetName(); + inlist->SetTitle(tt.Data()); + } + } + + delete arrAliases; + } + alias2trig.Sort(kSortDescending); + + // Replace all the aliases by the OR of triggers + TIter iter1(&alias2trig); + while((nmd = dynamic_cast(iter1.Next()))){ + fSelectTriggerExpr.ReplaceAll(nmd->GetName(),nmd->GetTitle()); + } +} + Bool_t AliRawReader::IsSelected() const { // apply the selection (if any) if (fSkipInvalid && !IsValid()) return kFALSE; - if (fSelectEquipmentType >= 0) { + if (fSelectEquipmentType >= 0) if (GetEquipmentType() != fSelectEquipmentType) return kFALSE; - if ((fSelectMinEquipmentId >= 0) && - (GetEquipmentId() < fSelectMinEquipmentId)) - return kFALSE; - if ((fSelectMaxEquipmentId >= 0) && - (GetEquipmentId() > fSelectMaxEquipmentId)) + + Int_t equipmentId; + if (fEquipmentIdsIn && fEquipmentIdsIn) + equipmentId = GetMappedEquipmentId(); + else + equipmentId = GetEquipmentId(); + + if ((fSelectMinEquipmentId >= 0) && + (equipmentId < fSelectMinEquipmentId)) + return kFALSE; + if ((fSelectMaxEquipmentId >= 0) && + (equipmentId > fSelectMaxEquipmentId)) + return kFALSE; + + return kTRUE; +} + +Bool_t AliRawReader::IsEventSelected() const +{ + // apply the event selection (if any) + + // First check the event type + if (fSelectEventType >= 0) { + if (GetType() != (UInt_t) fSelectEventType) return kFALSE; + } + + // Then check the trigger pattern and compared it + // to the required trigger mask + if (fSelectTriggerMask != 0) { + if ((GetClassMask() & fSelectTriggerMask) != fSelectTriggerMask) return kFALSE; + } + + if ( fIsTriggerClassLoaded && !fSelectTriggerExpr.IsNull()) { + TString expr(fSelectTriggerExpr); + ULong64_t mask = GetClassMask(); + for(Int_t itrigger = 0; itrigger < 50; itrigger++) { + if (mask & ((ULong64_t)1 << itrigger)) { + expr.ReplaceAll(Form("[%d]",itrigger),"1"); + } + else { + expr.ReplaceAll(Form("[%d]",itrigger),"0"); + } + } + // Possibility to introduce downscaling + TPRegexp("(%\\s*\\d+)").Substitute(expr,Form("&& !(%d$1)",GetEventIndex()),"g"); + Int_t error; + Bool_t result = gROOT->ProcessLineFast(expr.Data(),&error); + if ( error == TInterpreter::kNoError) + return result; + else return kFALSE; } return kTRUE; } +UInt_t AliRawReader::SwapWord(UInt_t x) const +{ + // Swap the endianess of the integer value 'x' + + return (((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) << 8) | + ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24)); +} + +UShort_t AliRawReader::SwapShort(UShort_t x) const +{ + // Swap the endianess of the short value 'x' + + return (((x & 0x00ffU) << 8) | ((x & 0xff00U) >> 8)) ; +} Bool_t AliRawReader::ReadNextInt(UInt_t& data) { @@ -149,6 +591,9 @@ Bool_t AliRawReader::ReadNextInt(UInt_t& data) Error("ReadNextInt", "could not read data!"); return kFALSE; } +#ifndef R__BYTESWAP + data=SwapWord(data); +#endif return kTRUE; } @@ -169,6 +614,9 @@ Bool_t AliRawReader::ReadNextShort(UShort_t& data) Error("ReadNextShort", "could not read data!"); return kFALSE; } +#ifndef R__BYTESWAP + data=SwapShort(data); +#endif return kTRUE; } @@ -187,6 +635,20 @@ Bool_t AliRawReader::ReadNextChar(UChar_t& data) return kTRUE; } +Bool_t AliRawReader::GotoEvent(Int_t event) +{ + // Random access to certain + // event index. Could be very slow + // for some non-root raw-readers. + // So it should be reimplemented there. + if (event < fEventNumber) RewindEvents(); + + while (fEventNumber < event) { + if (!NextEvent()) return kFALSE; + } + + return kTRUE; +} Int_t AliRawReader::CheckData() const { @@ -291,7 +753,7 @@ void AliRawReader::DumpData(Int_t limit) line[pos+offset] = '.'; } char hex[3]; - sprintf(hex, "%2.2x", byte); + snprintf(hex, 3, "%2.2x", byte); line[max+max/4+3+2*pos+offset] = hex[0]; line[max+max/4+4+2*pos+offset] = hex[1]; pos++; @@ -302,3 +764,65 @@ void AliRawReader::DumpData(Int_t limit) } while (ReadHeader()); } + +void AliRawReader::AddErrorLog(AliRawDataErrorLog::ERawDataErrorLevel level, + Int_t code, + const char *message) +{ + // Add a raw data error message to the list + // of raw-data decoding errors + if (fEventNumber < 0) { + return; + } + Int_t ddlId = GetEquipmentId(); + if (ddlId < 0) { + AliError("No ddl raw data have been read so far! Impossible to add a raw data error log!"); + return; + } + + Int_t prevEventNumber = -1; + Int_t prevDdlId = -1; + Int_t prevErrorCode = -1; + AliRawDataErrorLog *prevLog = (AliRawDataErrorLog *)fErrorLogs.Last(); + if (prevLog) { + prevEventNumber = prevLog->GetEventNumber(); + prevDdlId = prevLog->GetDdlID(); + prevErrorCode = prevLog->GetErrorCode(); + } + + if ((prevEventNumber != fEventNumber) || + (prevDdlId != ddlId) || + (prevErrorCode != code)) { + new (fErrorLogs[fErrorLogs.GetEntriesFast()]) + AliRawDataErrorLog(fEventNumber, + ddlId, + level, + code, + message); + } + else + if (prevLog) prevLog->AddCount(); + +} + +Bool_t AliRawReader::GotoEventWithID(Int_t event, + UInt_t period, + UInt_t orbitID, + UShort_t bcID) +{ + // Go to certain event number by + // checking the event ID. + // Useful in case event-selection + // is applied and the 'event' is + // relative + if (!GotoEvent(event)) return kFALSE; + + while (GetBCID() != period || + GetOrbitID() != orbitID || + GetPeriod() != bcID) { + if (!NextEvent()) return kFALSE; + } + + return kTRUE; +} +