Update responsibles for MCH, MTR, HMP
[u/mrichter/AliRoot.git] / RAW / AliRawReader.cxx
index 6833844..fc05290 100644 (file)
 #include <TClass.h>
 #include <TPluginManager.h>
 #include <TROOT.h>
+#include <TInterpreter.h>
+#include <TSystem.h>
+#include <TPRegexp.h>
+#include <THashList.h>
 
 #include <Riostream.h>
 #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)
 
 
@@ -56,6 +62,7 @@ AliRawReader::AliRawReader() :
   fEquipmentIdsOut(NULL),
   fRequireHeader(kTRUE),
   fHeader(NULL),
+  fHeaderV3(NULL),
   fCount(0),
   fSelectEquipmentType(-1),
   fSelectMinEquipmentId(-1),
@@ -63,15 +70,20 @@ AliRawReader::AliRawReader() :
   fSkipInvalid(kFALSE),
   fSelectEventType(-1),
   fSelectTriggerMask(0),
+  fSelectTriggerExpr(),
   fErrorCode(0),
   fEventNumber(-1),
   fErrorLogs("AliRawDataErrorLog",100),
-  fHeaderSwapped(NULL)
+  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
 }
 
@@ -113,6 +125,7 @@ AliRawReader::AliRawReader(const AliRawReader& rawReader) :
   fEquipmentIdsOut(rawReader.fEquipmentIdsOut),
   fRequireHeader(rawReader.fRequireHeader),
   fHeader(rawReader.fHeader),
+  fHeaderV3(rawReader.fHeaderV3),
   fCount(rawReader.fCount),
   fSelectEquipmentType(rawReader.fSelectEquipmentType),
   fSelectMinEquipmentId(rawReader.fSelectMinEquipmentId),
@@ -120,25 +133,32 @@ AliRawReader::AliRawReader(const AliRawReader& rawReader) :
   fSkipInvalid(rawReader.fSkipInvalid),
   fSelectEventType(rawReader.fSelectEventType),
   fSelectTriggerMask(rawReader.fSelectTriggerMask),
+  fSelectTriggerExpr(rawReader.fSelectTriggerExpr),
   fErrorCode(0),
   fEventNumber(-1),
   fErrorLogs("AliRawDataErrorLog",100),
-  fHeaderSwapped(NULL)
+  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;
@@ -147,12 +167,16 @@ AliRawReader& AliRawReader::operator = (const AliRawReader& rawReader)
   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;
 }
 
@@ -165,6 +189,7 @@ AliRawReader::~AliRawReader()
   if (fEquipmentIdsOut) delete fEquipmentIdsOut;
   fErrorLogs.Delete();
   if (fHeaderSwapped) delete fHeaderSwapped;
+  if (fHeaderSwappedV3) delete fHeaderSwappedV3;
 }
 
 AliRawReader* AliRawReader::Create(const char *uri)
@@ -188,18 +213,8 @@ AliRawReader* AliRawReader::Create(const char *uri)
   TString &fileURI = ((TObjString*)fields->At(0))->String();
 
   AliRawReader *rawReader = NULL;
-  if (!fileURI.BeginsWith("mem://")) {
-    AliInfoClass(Form("Creating raw-reader in order to read raw-data file: %s",fileURI.Data()));
-    if (fileURI.EndsWith("/")) {
-      rawReader = new AliRawReaderFile(fileURI);
-    } else if (fileURI.EndsWith(".root")) {
-      rawReader = new AliRawReaderRoot(fileURI);
-    } else {
-      rawReader = new AliRawReaderDate(fileURI);
-    }
-  }
-  else {
-    fileURI.ReplaceAll("mem://","");
+  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();
@@ -215,14 +230,58 @@ AliRawReader* AliRawReader::Create(const char *uri)
       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();
@@ -233,17 +292,21 @@ AliRawReader* AliRawReader::Create(const char *uri)
       }
       if (option.BeginsWith("Trigger=",TString::kIgnoreCase)) {
        option.ReplaceAll("Trigger=","");
-       triggerMask = option.Atoll();
+       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",
-                eventType,triggerMask));
-    rawReader->SelectEvents(eventType,triggerMask);
+    AliInfoClass(Form("Event selection criteria specified:   eventype=%d   trigger mask=%llx   trigger expression=%s",
+                eventType,triggerMask,triggerExpr.Data()));
+    rawReader->SelectEvents(eventType,triggerMask,triggerExpr.Data());
   }
 
-  fields->Delete();
   delete fields;
 
   return rawReader;
@@ -345,14 +408,91 @@ void AliRawReader::SelectEquipment(Int_t equipmentType,
   fSelectMaxEquipmentId = maxEquipmentId;
 }
 
-void AliRawReader::SelectEvents(Int_t type, ULong64_t triggerMask)
+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 a value < 0 is used.
+// 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<TNamed*>(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; i<nAliases; i++){
+
+      TObjString *alias = (TObjString*) arrAliases->At(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<TNamed*>(iter1.Next()))){
+    fSelectTriggerExpr.ReplaceAll(nmd->GetName(),nmd->GetTitle());
+  }
 }
 
 Bool_t AliRawReader::IsSelected() const
@@ -395,6 +535,27 @@ Bool_t AliRawReader::IsEventSelected() const
     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;
 }
 
@@ -474,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
 {
@@ -578,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++;
@@ -629,3 +804,25 @@ void AliRawReader::AddErrorLog(AliRawDataErrorLog::ERawDataErrorLevel level,
     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;
+}
+