* provided "as is" without express or implied warranty. *
**************************************************************************/
+/* $Id$ */
-///////////////////////////////////////////////////////////////////////////////
-///
+//-----------------------------------------------------------------------------
+/// \class AliMUONRawStreamTrigger
/// This class provides access to MUON digits in raw data.
///
/// It loops over all MUON digits in the raw data given by the AliRawReader.
-/// The Next method goes to the next digit. If there are no digits left
-/// it returns kFALSE(under develpment).
+/// The Next method goes to the next local response. If there are no local response left
+/// it returns kFALSE.
/// It can loop also over DDL and store the decoded rawdata in TClonesArrays
+/// in payload class.
///
-/// First version implement for Trigger
-///
-///////////////////////////////////////////////////////////////////////////////
+/// Version implement for Trigger
+/// \author Christian Finck
+//-----------------------------------------------------------------------------
+
+#include <TArrayS.h>
#include "AliMUONRawStreamTrigger.h"
+#include "AliMUONDarcHeader.h"
+#include "AliMUONRegHeader.h"
+#include "AliMUONLocalStruct.h"
+#include "AliMUONDDLTrigger.h"
+#include "AliMUONLogger.h"
#include "AliRawReader.h"
#include "AliRawDataHeader.h"
+#include "AliDAQ.h"
#include "AliLog.h"
-#include "AliMUONDarcHeader.h"
-#include "AliMUONRegHeader.h"
-#include "AliMUONLocalStruct.h"
-#include "AliMUONDDLTrigger.h"
+#include <cassert>
+/// \cond CLASSIMP
ClassImp(AliMUONRawStreamTrigger)
+/// \endcond
+
+const Int_t AliMUONRawStreamTrigger::fgkMaxDDL = 2;
+
+//___________________________________________
+AliMUONRawStreamTrigger::AliMUONRawStreamTrigger(TRootIOCtor* /*dummy*/)
+: AliMUONVRawStreamTrigger(),
+fPayload(0x0),
+fCurrentDDL(0x0),
+fCurrentDDLIndex(fgkMaxDDL),
+fCurrentDarcHeader(0x0),
+fCurrentRegHeader(0x0),
+fCurrentRegHeaderIndex(0),
+fCurrentLocalStruct(0x0),
+fCurrentLocalStructIndex(0),
+fLocalStructRead(kFALSE),
+fDDL(0),
+fNextDDL(kFALSE)
+{
+ ///
+ /// create an object to read MUON raw digits
+ /// Default ctor with no mem allocation for I/O
+ ///
+}
+//___________________________________________
AliMUONRawStreamTrigger::AliMUONRawStreamTrigger()
- : TObject(),
- fRawReader(0x0),
+: AliMUONVRawStreamTrigger(),
+ fPayload(new AliMUONPayloadTrigger()),
+ fCurrentDDL(0x0),
+ fCurrentDDLIndex(fgkMaxDDL),
+ fCurrentDarcHeader(0x0),
+ fCurrentRegHeader(0x0),
+ fCurrentRegHeaderIndex(0),
+ fCurrentLocalStruct(0x0),
+ fCurrentLocalStructIndex(0),
+ fLocalStructRead(kFALSE),
fDDL(0),
- fSubEntries(0),
- fNextDDL(kTRUE),
- fMaxDDL(2),
- fMaxReg(8),
- fMaxLoc(16)
+ fNextDDL(kFALSE)
{
- //
- // create an object to read MUON raw digits
- // Default ctor for monitoring purposes
- //
+ ///
+ /// create an object to read MUON raw digits
+ /// Default ctor for monitoring purposes
+ ///
- fDDLTrigger = new AliMUONDDLTrigger();
- fRegHeader = new AliMUONRegHeader();
- fLocalStruct = new AliMUONLocalStruct();
}
//_________________________________________________________________
AliMUONRawStreamTrigger::AliMUONRawStreamTrigger(AliRawReader* rawReader)
- : TObject(),
+ : AliMUONVRawStreamTrigger(rawReader),
+ fPayload(new AliMUONPayloadTrigger()),
+ fCurrentDDL(0x0),
+ fCurrentDDLIndex(fgkMaxDDL),
+ fCurrentDarcHeader(0x0),
+ fCurrentRegHeader(0x0),
+ fCurrentRegHeaderIndex(0),
+ fCurrentLocalStruct(0x0),
+ fCurrentLocalStructIndex(0),
+ fLocalStructRead(kFALSE),
fDDL(0),
- fSubEntries(0),
- fNextDDL(kTRUE),
- fMaxDDL(2),
- fMaxReg(8),
- fMaxLoc(16)
+ fNextDDL(kFALSE)
{
- //
- // ctor with AliRawReader as argument
- // for reconstruction purpose
- //
+ ///
+ /// ctor with AliRawReader as argument
+ /// for reconstruction purpose
+ ///
- fRawReader = rawReader;
-
- fDDLTrigger = new AliMUONDDLTrigger();
- fRegHeader = new AliMUONRegHeader();
- fLocalStruct = new AliMUONLocalStruct();
-
-}
-
-//_________________________________________________________________
-AliMUONRawStreamTrigger::AliMUONRawStreamTrigger(const AliMUONRawStreamTrigger& stream) :
- TObject(stream)
-{
- //
- // copy ctor
- //
- AliFatal("copy constructor not implemented");
-}
-
-//______________________________________________________________________
-AliMUONRawStreamTrigger& AliMUONRawStreamTrigger::operator = (const AliMUONRawStreamTrigger&
- /* stream */)
-{
- //
- // assignment operator
- //
- AliFatal("assignment operator not implemented");
- return *this;
}
//___________________________________
AliMUONRawStreamTrigger::~AliMUONRawStreamTrigger()
{
- //
- // clean up
- //
- delete fDDLTrigger;
- delete fLocalStruct;
- delete fRegHeader;
+ ///
+ /// clean up
+ ///
+ delete fPayload;
}
//_____________________________________________________________
-Bool_t AliMUONRawStreamTrigger::Next()
+Bool_t AliMUONRawStreamTrigger::Next(UChar_t& id, UChar_t& dec, Bool_t& trigY,
+ UChar_t& yPos, UChar_t& sXDev, UChar_t& xDev,
+ UChar_t& xPos, Bool_t& triggerY, Bool_t& triggerX,
+ TArrayS& xPattern, TArrayS& yPattern)
{
-// read the next raw digit (buspatch structure)
-// returns kFALSE if there is no digit left
-
-// if (fNextDDL){
-// if(!NextDDL()) return kFALSE;
-// }
-// Int_t nEntries = fDDLTrigger->GetBusPatchEntries();
-
-// if (fSubEntries < nEntries) {
-// fLocalStruct = (AliMUONLocalStruct*)fDDLTrigger->GetBusPatchEntry(fSubEntries);
-// fSubEntries++;
-// fNextDDL = kFALSE;
-// return kTRUE;
-// } else {
-// fDDLTrigger->GetBusPatchArray()->Delete();
-// fSubEntries = 0;
-// fNextDDL = kTRUE;
-// return Next();
-// }
-
- return kFALSE;
+ ///
+ /// read the next raw digit (local structure)
+ /// returns kFALSE if there is no digit left
+ /// Should call First() before this method to start the iteration.
+ ///
+
+ if ( IsDone() ) return kFALSE;
+
+ if ( fLocalStructRead ) {
+
+ Bool_t ok = GetNextLocalStruct();
+ if (!ok)
+ {
+ // this is the end
+ return kFALSE;
+ }
+ }
+
+ fLocalStructRead = kTRUE;
+
+ id = fCurrentLocalStruct->GetId();
+ dec = fCurrentLocalStruct->GetDec();
+ trigY = fCurrentLocalStruct->GetTrigY();
+ yPos = fCurrentLocalStruct->GetYPos();
+ sXDev = fCurrentLocalStruct->GetSXDev();
+ xDev = fCurrentLocalStruct->GetXDev();
+ xPos = fCurrentLocalStruct->GetXPos();
+
+ triggerX = fCurrentLocalStruct->GetTriggerX();
+ triggerY = fCurrentLocalStruct->GetTriggerY();
+
+ fCurrentLocalStruct->GetXPattern(xPattern);
+ fCurrentLocalStruct->GetYPattern(yPattern);
+
+ return kTRUE;
}
//______________________________________________________
-Bool_t AliMUONRawStreamTrigger::NextDDL()
+Bool_t AliMUONRawStreamTrigger::IsDone() const
{
- // reading tracker DDL
- // store buspatch info into Array
- // store only non-empty structures (buspatch info with datalength !=0)
-
- // reading DDL for trigger
-
- AliMUONDarcHeader* darcHeader = fDDLTrigger->GetDarcHeader();
+ /// Whether the iteration is finished or not
+ return (fCurrentLocalStruct==0);
+}
- Int_t kDarcHeaderSize = darcHeader->GetHeaderLength();
- Int_t kRegHeaderSize = fRegHeader->GetHeaderLength() ;
- Bool_t scalerEvent = kFALSE;
+//______________________________________________________
+void AliMUONRawStreamTrigger::First()
+{
+ /// Initialize the iteration process.
+
+ fCurrentDDLIndex = -1;
+ // Must reset all the pointers because if we return before calling
+ // GetNextLocalStruct() the user might call CurrentDDL(), CurrentBlockHeader(),
+ // CurrentRegHeader() or CurrentLocalStruct() which should return reasonable
+ // results in that case.
+ fCurrentDDL = 0;
+ fCurrentDarcHeader = 0;
+ fCurrentRegHeader = 0;
+ fCurrentLocalStruct = 0;
+
+ // Find the first non-empty structure
+ if (not GetNextDDL()) return;
+ if (not GetNextRegHeader()) return;
+ GetNextLocalStruct();
+}
- // reset TClones
- darcHeader->GetRegHeaderArray()->Delete();
- //darcHeader->GetRegHeaderArray()->Clear("C");
+//______________________________________________________
+Bool_t AliMUONRawStreamTrigger::GetNextDDL()
+{
+ /// Returns the next DDL present
+
+ assert( GetReader() != 0 );
- // loop over the two ddl's
- if (fDDL >= fMaxDDL) {
- fDDL = 0;
+
+ Bool_t kFound(kFALSE);
+
+ while ( fCurrentDDLIndex < fgkMaxDDL-1 && !kFound )
+ {
+ ++fCurrentDDLIndex;
+ GetReader()->Reset();
+ GetReader()->Select("MUONTRG",fCurrentDDLIndex,fCurrentDDLIndex);
+ if ( GetReader()->ReadHeader() )
+ {
+ kFound = kTRUE;
+ }
+ }
+
+ if ( !kFound )
+ {
+ // fCurrentDDLIndex is set to fgkMaxDDL so that we exit the above loop immediately
+ // for a subsequent call to this method, unless NextEvent is called in between.
+ fCurrentDDLIndex = fgkMaxDDL;
+ // We have not actually been able to complete the loading of the new DDL so
+ // we are still on the old one. In this case we do not need to reset fCurrentDDL.
+ //fCurrentDDL = 0;
+ if (IsErrorLogger()) AddErrorMessage();
return kFALSE;
}
+
+ Int_t totalDataWord = GetReader()->GetDataSize(); // in bytes
+
+ Bool_t scalerEvent = GetReader()->GetDataHeader()->GetL1TriggerMessage() & 0x1;
- fRawReader->Reset();
- fRawReader->Select(0XA,fDDL,fDDL); //Select the DDL file to be read
-
- fRawReader->ReadHeader();
+ AliDebug(3, Form("DDL Number %d totalDataWord %d\n", fCurrentDDLIndex,
+ totalDataWord));
- Int_t totalDataWord = fRawReader->GetDataSize(); // in bytes
UInt_t *buffer = new UInt_t[totalDataWord/4];
- fRawReader->ReadNext((UChar_t*)buffer, totalDataWord);
-
- Int_t index = 0;
- darcHeader->SetWord(buffer[index++]);
-
- if(darcHeader->GetEventType() == 2) {
- scalerEvent = kTRUE;
- } else
- scalerEvent = kFALSE;
-
- if(scalerEvent) {
- // 6 DARC scaler words
- memcpy(darcHeader->GetDarcScalers(), &buffer[index], darcHeader->GetDarcScalerLength()*4);
- index += darcHeader->GetDarcScalerLength();
+ if ( !GetReader()->ReadNext((UChar_t*)buffer, totalDataWord) )
+ {
+ // We have not actually been able to complete the loading of the new DDL so
+ // we are still on the old one. In this case we do not need to reset fCurrentDDL.
+ //fCurrentDDL = 0;
+ delete [] buffer;
+ return kFALSE;
}
- if (buffer[index++] != darcHeader->GetEndOfDarc())
- AliWarning(Form("Wrong end of Darc word %x instead of %x\n",buffer[index-1], darcHeader->GetEndOfDarc()));
+#ifndef R__BYTESWAP
+ Swap(buffer, totalDataWord / sizeof(UInt_t)); // swap needed for mac power pc
+#endif
- // 4 words of global board input + Global board output
- memcpy(darcHeader->GetGlobalInput(), &buffer[index], (kDarcHeaderSize-1)*4);
- index += kDarcHeaderSize- 1; // kind tricky cos scaler info in-between Darc header
+ fPayload->ResetDDL();
+
- if(scalerEvent) {
- // 10 Global scaler words
- memcpy(darcHeader->GetGlobalScalers(), &buffer[index], darcHeader->GetGlobalScalerLength()*4);
- index += darcHeader->GetGlobalScalerLength();
- }
- if (buffer[index++] != darcHeader->GetEndOfGlobal())
- AliWarning(Form("Wrong end of Global word %d instead of %d\n",buffer[index-1], darcHeader->GetEndOfGlobal()));
-
- // 8 regional boards
- for (Int_t iReg = 0; iReg < fMaxReg; iReg++) { //loop over regeonal card
+ Bool_t ok = fPayload->Decode(buffer, scalerEvent);
- memcpy(fRegHeader->GetHeader(), &buffer[index], kRegHeaderSize*4);
- index += kRegHeaderSize;
+ delete[] buffer;
+
+ fCurrentDDL = fPayload->GetDDLTrigger();
+
+ fCurrentDarcHeader = fCurrentDDL->GetDarcHeader();
+
+ fCurrentRegHeaderIndex = -1;
- fDDLTrigger->AddRegHeader(*fRegHeader);
- // 11 regional scaler word
- if(scalerEvent) {
- memcpy(fRegHeader->GetScalers(), &buffer[index], fRegHeader->GetScalerLength()*4);
- index += fRegHeader->GetScalerLength();
- }
- if (buffer[index++] != fRegHeader->GetEndOfReg())
- AliWarning(Form("Wrong end of Reg word %x instead of %x\n",buffer[index-1], fRegHeader->GetEndOfReg()));
-
- // 16 local cards per regional board
- for (Int_t iLoc = 0; iLoc < fMaxLoc; iLoc++) { //loop over local card
-
- Int_t dataSize = fLocalStruct->GetLength();;
-
- // 5 word trigger information
- memcpy(fLocalStruct->GetData(), &buffer[index], dataSize*4);
- index += dataSize;
-
- // 45 regional scaler word
- if(scalerEvent) {
- memcpy(fLocalStruct->GetScalers(), &buffer[index], fLocalStruct->GetScalerLength()*4);
- index += fLocalStruct->GetScalerLength();
- }
-
- if (buffer[index++] != fLocalStruct->GetEndOfLocal())
- AliWarning(Form("Wrong end of local word %x instead of %x\n",buffer[index-1], fLocalStruct->GetEndOfLocal()));
-
- fDDLTrigger->AddLocStruct(*fLocalStruct, iReg);
-
- } // local card loop
-
- } // regional card loop
-
- delete [] buffer;
+ return ok;
+}
- fDDL++;
+//______________________________________________________
+Bool_t AliMUONRawStreamTrigger::GetNextRegHeader()
+{
+ /// Returns the next Reg Header present
+ assert( fCurrentDarcHeader != 0 );
+ assert( fCurrentDDL != 0 );
+
+ fCurrentRegHeader = 0;
+
+ Int_t i = fCurrentRegHeaderIndex;
+
+ while ( fCurrentRegHeader == 0 && i < fCurrentDarcHeader->GetRegHeaderEntries()-1 )
+ {
+ ++i;
+ fCurrentRegHeader = fCurrentDarcHeader->GetRegHeaderEntry(i);
+ }
+
+ if ( !fCurrentRegHeader )
+ {
+ Bool_t ok = GetNextDDL();
+ if (!ok)
+ {
+ return kFALSE;
+ }
+ else
+ {
+ return GetNextRegHeader();
+ }
+ }
+
+ fCurrentRegHeaderIndex = i;
+
+ fCurrentLocalStructIndex = -1;
+
return kTRUE;
}
//______________________________________________________
-void AliMUONRawStreamTrigger::ResetDDL()
+Bool_t AliMUONRawStreamTrigger::GetNextLocalStruct()
{
- // reseting TClonesArray
- // after each DDL
- //
- AliMUONDarcHeader* darcHeader = fDDLTrigger->GetDarcHeader();
- darcHeader->GetRegHeaderArray()->Clear("C");
+ /// Find the next non-empty local structure
+
+ assert( fCurrentRegHeader != 0 );
+
+ fCurrentLocalStruct = 0;
+
+ Int_t i = fCurrentLocalStructIndex;
+
+ while ( fCurrentLocalStruct == 0 && i < fCurrentRegHeader->GetLocalEntries()-1 )
+ {
+ ++i;
+ fCurrentLocalStruct = fCurrentRegHeader->GetLocalEntry(i);
+ }
+
+ if ( !fCurrentLocalStruct )
+ {
+ Bool_t ok = GetNextRegHeader();
+ if (!ok)
+ {
+ return kFALSE;
+ }
+ else
+ {
+ return GetNextLocalStruct();
+ }
+ }
+
+ fCurrentLocalStructIndex = i;
+
+ fLocalStructRead = kFALSE;
+
+ return kTRUE;
}
//______________________________________________________
-void AliMUONRawStreamTrigger::SetMaxDDL(Int_t ddl)
+Bool_t AliMUONRawStreamTrigger::NextDDL()
{
- // set DDL number
- if (ddl > 2) ddl = 2;
- fMaxDDL = ddl;
+ /// reading tracker DDL
+ /// store local info into Array
+ /// store only non-empty structures
+
+ // reset TClones
+ fPayload->ResetDDL();
+
+
+ // loop over the two ddl's
+
+ while ( fDDL < fgkMaxDDL ) {
+ GetReader()->Reset();
+ GetReader()->Select("MUONTRG", fDDL, fDDL); //Select the DDL file to be read
+ if (GetReader()->ReadHeader()) break;
+ AliDebug(3,Form("Skipping DDL %d which does not seem to be there",fDDL));
+ ++fDDL;
+ }
+
+ if (fDDL >= fgkMaxDDL) {
+ fDDL = 0;
+ if (IsErrorLogger()) AddErrorMessage();
+ return kFALSE;
+ }
+
+ AliDebug(3, Form("DDL Number %d\n", fDDL ));
+
+ Int_t totalDataWord = GetReader()->GetDataSize(); // in bytes
+
+ Bool_t scalerEvent = GetReader()->GetDataHeader() && GetReader()->GetDataHeader()->GetL1TriggerMessage() & 0x1;
+
+
+ UInt_t *buffer = new UInt_t[totalDataWord/4];
+
+ // check not necessary yet, but for future developments
+ if (!GetReader()->ReadNext((UChar_t*)buffer, totalDataWord)) return kFALSE;
+
+#ifndef R__BYTESWAP
+ Swap(buffer, totalDataWord / sizeof(UInt_t)); // swap needed for mac power pc
+#endif
+
+ fPayload->Decode(buffer, scalerEvent);
+
+
+ fDDL++;
+
+ delete [] buffer;
+
+
+ return kTRUE;
}
+// //______________________________________________________
+// void AliMUONRawStreamTrigger::SetMaxReg(Int_t reg)
+// {
+// /// set regional card number
+// fPayload->SetMaxReg(reg);
+// }
+
//______________________________________________________
-void AliMUONRawStreamTrigger::SetMaxReg(Int_t reg)
+void AliMUONRawStreamTrigger::SetMaxLoc(Int_t loc)
{
- // set regional card number
- if (reg > 8) reg = 8;
- fMaxReg = reg;
+ /// set local card number
+ fPayload->SetMaxLoc(loc);
}
//______________________________________________________
-void AliMUONRawStreamTrigger::SetMaxLoc(Int_t loc)
+void AliMUONRawStreamTrigger::AddErrorMessage()
{
- // set local card number
- if (loc > 16) loc = 16;
- fMaxLoc = loc;
+/// add message into logger of AliRawReader per event
+
+ TString msg;
+ Int_t occurance = 0;
+ AliMUONLogger* log = fPayload->GetErrorLogger();
+
+ log->ResetItr();
+ while(log->Next(msg, occurance))
+ {
+ if (msg.Contains("Darc"))
+ GetReader()->AddMajorErrorLog(kDarcEoWErr, msg.Data());
+
+ if (msg.Contains("Global"))
+ GetReader()->AddMajorErrorLog(kGlobalEoWErr, msg.Data());
+
+ if (msg.Contains("Regional"))
+ GetReader()->AddMajorErrorLog(kRegEoWErr, msg.Data());
+
+ if (msg.Contains("Local"))
+ GetReader()->AddMajorErrorLog(kLocalEoWErr, msg.Data());
+ }
+
+ log->Clear(); // clear after each event
}