/**************************************************************************
- * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
- * *
- * Author: The ALICE Off-line Project. *
- * Contributors are mentioned in the code where appropriate. *
- * *
- * Permission to use, copy, modify and distribute this software and its *
- * documentation strictly for non-commercial purposes is hereby granted *
- * without fee, provided that the above copyright notice appears in all *
- * copies and that both the copyright notice and this permission notice *
- * appear in the supporting documentation. The authors make no claims *
- * about the suitability of this software for any purpose. It is *
- * provided "as is" without express or implied warranty. *
- **************************************************************************/
-
-
-///////////////////////////////////////////////////////////////////////////////
-///
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+/* $Id$ */
+
+
+//-----------------------------------------------------------------------------
+/// \class AliMUONRawStreamTracker
/// 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)
-/// It can loop also over DDL and store the decoded rawdata in TClonesArray.
+/// it returns kFALSE
+/// It can loop also over DDL and store the decoded rawdata in TClonesArray
+/// in Payload class.
///
-/// First version implement for Tracker
+/// Implement for Tracker
///
-///////////////////////////////////////////////////////////////////////////////
+/// \author Christian Finck & Laurent Aphecetche
+//-----------------------------------------------------------------------------
#include "AliMUONRawStreamTracker.h"
+#include "AliMUONLogger.h"
#include "AliRawReader.h"
#include "AliRawDataHeader.h"
+#include "AliDAQ.h"
#include "AliLog.h"
-
-#include "AliMUONDspHeader.h"
+#include "AliMUONPayloadTracker.h"
#include "AliMUONBlockHeader.h"
+#include "AliMUONDspHeader.h"
#include "AliMUONBusStruct.h"
#include "AliMUONDDLTracker.h"
+#include "Riostream.h"
+#include <cassert>
+/// \cond CLASSIMP
ClassImp(AliMUONRawStreamTracker)
+/// \endcond
+
+const Int_t AliMUONRawStreamTracker::fgkMaxDDL = 20;
+
+//___________________________________________
AliMUONRawStreamTracker::AliMUONRawStreamTracker()
- : TObject(),
- fRawReader(0x0),
- fDDL(0),
- fBusPatchId(0),
- fDspId(0),
- fBlkId(0),
- fNextDDL(kTRUE),
- fMaxDDL(20),
- fMaxBlock(2),
- fMaxDsp(5),
- fMaxBus(5)
+ : AliMUONVRawStreamTracker(),
+ fPayload(new AliMUONPayloadTracker()),
+ fCurrentDDL(0),
+ fCurrentDDLIndex(fgkMaxDDL),
+ fCurrentBlockHeader(0),
+ fCurrentBlockHeaderIndex(0),
+ fCurrentDspHeader(0),
+ fCurrentDspHeaderIndex(0),
+ fCurrentBusStruct(0),
+ fCurrentBusStructIndex(0),
+ fCurrentDataIndex(0),
+ fDDL(0)
{
- //
- // create an object to read MUON raw digits
- // Default ctor for monitoring purposes
- //
- fBusPatchManager = new AliMpBusPatch();
- fBusPatchManager->ReadBusPatchFile();
-
- fDDLTracker = new AliMUONDDLTracker();
- fBusStruct = new AliMUONBusStruct();
- fBlockHeader = new AliMUONBlockHeader();
- fDspHeader = new AliMUONDspHeader();
+ ///
+ /// create an object to read MUON raw digits
+ /// Default ctor for monitoring purposes
+ ///
+
+
}
//_________________________________________________________________
AliMUONRawStreamTracker::AliMUONRawStreamTracker(AliRawReader* rawReader)
- : TObject(),
- fDDL(0),
- fBusPatchId(0),
- fDspId(0),
- fBlkId(0),
- fNextDDL(kTRUE),
- fMaxDDL(20),
- fMaxBlock(2),
- fMaxDsp(5),
- fMaxBus(5)
+: AliMUONVRawStreamTracker(rawReader),
+ fPayload(new AliMUONPayloadTracker()),
+ fCurrentDDL(0),
+ fCurrentDDLIndex(fgkMaxDDL),
+ fCurrentBlockHeader(0),
+ fCurrentBlockHeaderIndex(0),
+ fCurrentDspHeader(0),
+ fCurrentDspHeaderIndex(0),
+ fCurrentBusStruct(0),
+ fCurrentBusStructIndex(0),
+ fCurrentDataIndex(0),
+ fDDL(0)
{
- //
- // ctor with AliRawReader as argument
- // for reconstruction purpose
- //
-
- fRawReader = rawReader;
-
- fBusPatchManager = new AliMpBusPatch();
- fBusPatchManager->ReadBusPatchFile();
-
- fDDLTracker = new AliMUONDDLTracker();
- fBusStruct = new AliMUONBusStruct();
- fBlockHeader = new AliMUONBlockHeader();
- fDspHeader = new AliMUONDspHeader();
-}
-
-//_________________________________________________________________
-AliMUONRawStreamTracker::AliMUONRawStreamTracker(const AliMUONRawStreamTracker& stream) :
- TObject(stream)
-{
- //
- // copy ctor
- //
- AliFatal("copy constructor not implemented");
-}
-
-//______________________________________________________________________
-AliMUONRawStreamTracker& AliMUONRawStreamTracker::operator = (const AliMUONRawStreamTracker&
- /* stream */)
-{
- //
- // assignment operator
- //
- AliFatal("assignment operator not implemented");
- return *this;
+ ///
+ /// ctor with AliRawReader as argument
+ /// for reconstruction purpose
+ ///
+
+
}
-
//___________________________________
AliMUONRawStreamTracker::~AliMUONRawStreamTracker()
{
- //
- // clean up
- //
- delete fBusPatchManager;
- delete fDDLTracker;
- delete fBusStruct;
- delete fBlockHeader;
- delete fDspHeader;
+ ///
+ /// clean up
+ ///
+ delete fPayload;
}
//_____________________________________________________________
-Bool_t AliMUONRawStreamTracker::Next()
+Bool_t
+AliMUONRawStreamTracker::Next(Int_t& busPatchId,
+ UShort_t& manuId, UChar_t& manuChannel,
+ UShort_t& adc)
{
- //
- // read the next raw digit (buspatch structure)
- // returns kFALSE if there is no digit left
- // (under development)
-
- AliMUONDDLTracker* ddlTracker = 0x0;
- AliMUONBlockHeader* blkHeader = 0x0;
- AliMUONDspHeader* dspHeader = 0x0;
- Int_t nBusPatch;
- Int_t nDsp;
- Int_t nBlock;
-
- next:
- if (fNextDDL){
- printf("iDDL %d\n", fDDL+1);
- fBlkId = 0;
- fDspId = 0;
- fBusPatchId = 0;
- if(!NextDDL())
- return kFALSE;
- }
- fNextDDL = kFALSE;
-
- ddlTracker = GetDDLTracker();
-
- nBlock = ddlTracker->GetBlkHeaderEntries();
- if (fBlkId < nBlock) {
-
- blkHeader = ddlTracker->GetBlkHeaderEntry(fBlkId);
- nDsp = blkHeader->GetDspHeaderEntries();
-
- if( fDspId < nDsp) {
- dspHeader = blkHeader->GetDspHeaderEntry(fDspId);
- nBusPatch = dspHeader->GetBusPatchEntries();
-
- if (fBusPatchId < nBusPatch) {
- fBusStructPtr = dspHeader->GetBusPatchEntry(fBusPatchId++);
- return kTRUE;
-
- } else {// iBusPatch
- fDspId++;
- fBusPatchId = 0;
- goto next;
- // Next();
- }
-
- } else {// iDsp
- fBlkId++;
- fDspId = 0;
- fBusPatchId = 0;
- goto next;
- // Next();
- }
-
- } else {// iBlock
- fBlkId = 0;
- fDspId = 0;
- fBusPatchId = 0;
- fNextDDL = kTRUE;
- //return kTRUE;
- goto next;
- }
-
- return kFALSE;
-}
-
-//______________________________________________________
-Bool_t AliMUONRawStreamTracker::NextDDL()
-{
- // reading tracker DDL
- // store buspatch info into Array
- // store only non-empty structures (buspatch info with datalength !=0)
-
- fDDLTracker->GetBlkHeaderArray()->Delete();
- // fDDLTracker->GetBlkHeaderArray()->Clear("C");
-
- //Read Header Size of DDL,Block,DSP and BusPatch
+ ///
+ /// read the next raw digit (buspatch structure)
+ /// returns kFALSE if there is no digit left
+ /// Should call First() before this method to start the iteration.
+ ///
+
+ if ( IsDone() ) return kFALSE;
+
+ if ( fCurrentDataIndex >= fCurrentBusStruct->GetLength()-1 )
+ {
+ Bool_t ok = GetNextBusStruct();
+ if (!ok)
+ {
+ // this is the end
+ return kFALSE;
+ }
+ }
- Int_t kDDLHeaderSize = sizeof(AliRawDataHeader)/4;;
- Int_t kBlockHeaderSize = fBlockHeader->GetHeaderLength();
- Int_t kDspHeaderSize = fDspHeader->GetHeaderLength();
- Int_t kBusPatchHeaderSize = fBusStruct->GetHeaderLength();
+ ++fCurrentDataIndex;
- Int_t totalDDLSize, totalBlockSize, totalDspSize , totalBusPatchSize, dataSize;
+ busPatchId = fCurrentBusStruct->GetBusPatchId();
+ manuId = fCurrentBusStruct->GetManuId(fCurrentDataIndex);
+ manuChannel = fCurrentBusStruct->GetChannelId(fCurrentDataIndex);
+ adc = fCurrentBusStruct->GetCharge(fCurrentDataIndex);
+ return kTRUE;
+}
- Int_t iBusPerDSP[5]; // number of bus patches per DSP
- Int_t iDspMax; // number max of DSP per block
+//______________________________________________________
+Bool_t
+AliMUONRawStreamTracker::IsDone() const
+{
+ /// Whether the iteration is finished or not
+ return (fCurrentBusStruct==0);
+}
- // minimum data size (only header's)
- Int_t blankDDLSize;
- Int_t blankBlockSize;
- Int_t blankDspSize;
+//______________________________________________________
+void
+AliMUONRawStreamTracker::First()
+{
+ /// Initialize the iteration process.
+
+ fCurrentDDLIndex = -1;
+// fCurrentDspHeaderIndex = -1; // Not necessary since this gets reset in the GetNextXXX methods.
+// fCurrentBusStructIndex = -1;
+
+ // Must reset all the pointers because if we return before calling
+ // GetNextBusStruct() the user might call CurrentDDL(), CurrentBlockHeader(),
+ // CurrentDspHeader() or CurrentBusStruct() which should return reasonable
+ // results in that case.
+ fCurrentDDL = 0;
+ fCurrentBlockHeader = 0;
+ fCurrentDspHeader = 0;
+ fCurrentBusStruct = 0;
+
+ // Find the first non-empty structure
+ if (not GetNextDDL()) return;
+ if (not GetNextBlockHeader()) return;
+ if (not GetNextDspHeader()) return;
+ GetNextBusStruct();
+}
- if (fDDL >= 20) {
- fDDL = 0;
+//______________________________________________________
+Bool_t
+AliMUONRawStreamTracker::GetNextDDL()
+{
+ /// Returns the next DDL present
+
+ assert( GetReader() != 0 );
+
+ Bool_t kFound(kFALSE);
+
+ while ( fCurrentDDLIndex < fgkMaxDDL-1 && !kFound )
+ {
+ ++fCurrentDDLIndex;
+ GetReader()->Reset();
+ GetReader()->Select("MUONTRK",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;
}
- AliDebug(3, Form("DDL Number %d\n", fDDL ));
-
- // getting DSP info
- fBusPatchManager->GetDspInfo(fDDL/2, iDspMax, iBusPerDSP);
-
- // Each DDL is made with 2 Blocks each of which consists of 5 DSP's at most
- // and each of DSP has at most 5 buspatches.
- // This information is used to calculate the size of headers (DDL,Block and DSP)
- // which has no interesting data.
- blankDDLSize = kDDLHeaderSize + 2*kBlockHeaderSize + 2*iDspMax*kDspHeaderSize;
- blankBlockSize = kBlockHeaderSize + iDspMax*kDspHeaderSize;
+
+ Int_t totalDataWord = GetReader()->GetDataSize(); // in bytes
+
+ AliDebug(3, Form("DDL Number %d totalDataWord %d\n", fCurrentDDLIndex,
+ totalDataWord));
- for (Int_t i = 0; i < iDspMax; i++) {
- blankDDLSize += 2*iBusPerDSP[i]*kBusPatchHeaderSize;
- blankBlockSize += iBusPerDSP[i]*kBusPatchHeaderSize;
+ UInt_t *buffer = new UInt_t[totalDataWord/4];
+
+ 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;
}
- fRawReader->Reset();
- fRawReader->Select(0X9, fDDL, fDDL); //Select the DDL file to be read
-
- fRawReader->ReadHeader();
-
- // 4 is multiplied to convert 2 bytes words
- totalDDLSize = (fRawReader->GetDataSize() + sizeof(AliRawDataHeader))/4;
-
- // Compare the DDL header with an empty DDL header size to read the file
- if(totalDDLSize > blankDDLSize) {
-
- Int_t totalDataWord = fRawReader->GetDataSize(); // in bytes
- UInt_t *buffer = new UInt_t[totalDataWord/4];
+ fPayload->ResetDDL();
- fRawReader->ReadNext((UChar_t*)buffer, totalDataWord);
-
- // indexes
- Int_t indexDsp;
- Int_t indexBusPatch;
- Int_t index = 0;
-
- for(Int_t iBlock = 0; iBlock < 2 ;iBlock++){ // loop over 2 blocks
-
- // copy within padding words
- memcpy(fBlockHeader->GetHeader(),&buffer[index], (kBlockHeaderSize+1)*4);
-
- totalBlockSize = fBlockHeader->GetTotalLength();
-
- fDDLTracker->AddBlkHeader(*fBlockHeader);
-
- if (fBlockHeader->GetPadding() == 0xDEAD) // skipping padding word
- index++;
-
- if(totalBlockSize > blankBlockSize) { // compare block header
- index += kBlockHeaderSize;
-
- for(Int_t iDsp = 0; iDsp < iDspMax ;iDsp++){ //DSP loop
-
- if (iDsp > fMaxDsp) break;
-
- memcpy(fDspHeader->GetHeader(),&buffer[index], kDspHeaderSize*4);
-
- totalDspSize = fDspHeader->GetTotalLength();
- indexDsp = index;
-
- blankDspSize = kDspHeaderSize + iBusPerDSP[iDsp]*kBusPatchHeaderSize; // no data just header
-
- fDDLTracker->AddDspHeader(*fDspHeader, iBlock);
-
- if(totalDspSize > blankDspSize) { // Compare DSP Header
- index += kDspHeaderSize;
-
- for(Int_t iBusPatch = 0; iBusPatch < iBusPerDSP[iDsp]; iBusPatch++) {
-
- if (iBusPatch > fMaxBus) break;
-
- //copy buffer into header structure
- memcpy(fBusStruct->GetBusPatchHeader(), &buffer[index], kBusPatchHeaderSize*4);
+#ifndef R__BYTESWAP
+ Swap(buffer, totalDataWord / sizeof(UInt_t)); // swap needed for mac power pc
+#endif
- totalBusPatchSize = fBusStruct->GetTotalLength();
- indexBusPatch = index;
-
- //Check Buspatch header, not empty events
- if(totalBusPatchSize > kBusPatchHeaderSize) {
-
- index += kBusPatchHeaderSize;
- dataSize = fBusStruct->GetLength();
- Int_t bufSize = fBusStruct->GetBufSize();
-
- if(dataSize > 0) { // check data present
- if (dataSize > bufSize) fBusStruct->SetAlloc(dataSize);
-
- //copy buffer into data structure
- memcpy(fBusStruct->GetData(), &buffer[index], dataSize*4);
- fBusStruct->SetBlockId(iBlock); // could be usefull in future applications ?
- fBusStruct->SetDspId(iDsp);
- fDDLTracker->AddBusPatch(*fBusStruct, iBlock, iDsp);
+ Bool_t ok = fPayload->Decode(buffer, totalDataWord/4);
+
+ delete[] buffer;
+
+ fCurrentDDL = fPayload->GetDDLTracker();
+
+ fCurrentBlockHeaderIndex = -1;
+
+ return ok;
+}
- } // dataSize test
+//______________________________________________________
+Bool_t
+AliMUONRawStreamTracker::GetNextBlockHeader()
+{
+ /// Returns the next block Header present
+
+ assert( fCurrentDDL != 0 );
- } // testing buspatch
+ fCurrentBlockHeader = 0;
- index = indexBusPatch + totalBusPatchSize;
+ Int_t i(fCurrentBlockHeaderIndex);
+
+ while ( fCurrentBlockHeader == 0 && i < fCurrentDDL->GetBlkHeaderEntries()-1 )
+ {
+ ++i;
+ fCurrentBlockHeader = fCurrentDDL->GetBlkHeaderEntry(i);
+ }
+
+ if ( !fCurrentBlockHeader )
+ {
+ Bool_t ok = GetNextDDL();
+ if (!ok)
+ {
+ return kFALSE;
+ }
+ else
+ {
+ return GetNextBlockHeader();
+ }
+ }
+
+ fCurrentBlockHeaderIndex = i;
+
+ fCurrentDspHeaderIndex = -1;
+
+ return kTRUE;
+}
- } //buspatch loop
-
- } // dsp test
+//______________________________________________________
+Bool_t
+AliMUONRawStreamTracker::GetNextDspHeader()
+{
+ /// Returns the next Dsp Header present
- index = indexDsp + totalDspSize;
-
- } // dsp loop
+ assert( fCurrentBlockHeader != 0 );
+
+ fCurrentDspHeader = 0;
+
+ Int_t i(fCurrentDspHeaderIndex);
+
+ while ( fCurrentDspHeader == 0 && i < fCurrentBlockHeader->GetDspHeaderEntries()-1 )
+ {
+ ++i;
+ fCurrentDspHeader = fCurrentBlockHeader->GetDspHeaderEntry(i);
+ }
+
+ if ( !fCurrentDspHeader )
+ {
+ Bool_t ok = GetNextBlockHeader();
+ if (!ok)
+ {
+ return kFALSE;
+ }
+ else
+ {
+ return GetNextDspHeader();
+ }
+ }
+
+ fCurrentDspHeaderIndex = i;
+
+ fCurrentBusStructIndex = -1;
+
+ return kTRUE;
+}
- } //block test
+//______________________________________________________
+Bool_t
+AliMUONRawStreamTracker::GetNextBusStruct()
+{
+ /// Find the next non-empty busPatch structure
+
+ assert( fCurrentDspHeader != 0 );
+
+ fCurrentBusStruct = 0;
- index = totalBlockSize;
+ Int_t i(fCurrentBusStructIndex);
+
+ while ( fCurrentBusStruct == 0 && i < fCurrentDspHeader->GetBusPatchEntries()-1 )
+ {
+ ++i;
+ fCurrentBusStruct = fCurrentDspHeader->GetBusPatchEntry(i);
+ }
+
+ if ( !fCurrentBusStruct )
+ {
+ Bool_t ok = GetNextDspHeader();
+ if (!ok)
+ {
+ return kFALSE;
+ }
+ else
+ {
+ return GetNextBusStruct();
+ }
+ }
+
+ fCurrentBusStructIndex = i;
+
+ fCurrentDataIndex = -1;
+
+ return kTRUE;
+}
- } //block loop
+//______________________________________________________
+Bool_t AliMUONRawStreamTracker::NextDDL()
+{
+ /// reading tracker DDL
+
+ assert( GetReader() != 0 );
+
+ fPayload->ResetDDL();
+
+ while ( fDDL < fgkMaxDDL )
+ {
+ GetReader()->Reset();
+ GetReader()->Select("MUONTRK", 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
+
+ UInt_t *buffer = new UInt_t[totalDataWord/4];
+ if(!GetReader()->ReadNext((UChar_t*)buffer, totalDataWord))
+ {
delete[] buffer;
- } //loop checking the header size of DDL
+ return kFALSE;
+ }
+#ifndef R__BYTESWAP
+ Swap(buffer, totalDataWord / sizeof(UInt_t)); // swap needed for mac power pc
+#endif
+
+ Bool_t ok = fPayload->Decode(buffer, totalDataWord/4);
+ delete[] buffer;
+
fDDL++;
-
- return kTRUE;
+
+ return ok;
}
+
//______________________________________________________
-void AliMUONRawStreamTracker::ResetDDL()
+void AliMUONRawStreamTracker::SetMaxBlock(Int_t blk)
{
- // reseting TClonesArray
- // after each DDL
- //
- fDDLTracker->GetBlkHeaderArray()->Clear("C");
+ /// set regional card number
+ fPayload->SetMaxBlock(blk);
}
//______________________________________________________
-void AliMUONRawStreamTracker::SetMaxDDL(Int_t ddl)
+void AliMUONRawStreamTracker::AddErrorMessage()
{
- // set DDL number
- if (ddl > 20) ddl = 20;
- fMaxDDL = ddl;
+ /// add message into logger of AliRawReader per event
+
+ assert( GetReader() != 0 );
+ TString msg = 0;
+ Int_t occurance = 0;
+ AliMUONLogger* log = fPayload->GetErrorLogger();
+
+ log->ResetItr();
+ while(log->Next(msg, occurance))
+ {
+ if (msg.Contains("Parity"))
+ GetReader()->AddMinorErrorLog(kParityErr, msg.Data());
+
+ if (msg.Contains("Glitch"))
+ GetReader()->AddMajorErrorLog(kGlitchErr, msg.Data());
+
+ if (msg.Contains("Padding"))
+ GetReader()->AddMinorErrorLog(kPaddingWordErr, msg.Data());
+ }
+
+ log->Clear(); // clear logger after each event
}
//______________________________________________________
-void AliMUONRawStreamTracker::SetMaxBlock(Int_t blk)
+Bool_t AliMUONRawStreamTracker::IsErrorMessage() const
{
- // set regional card number
- if (blk > 2) blk = 2;
- fMaxBlock = blk;
-}
+ /// true if there is any error/warning
+ if (GetPayLoad()->GetParityErrors() ||
+ GetPayLoad()->GetGlitchErrors() ||
+ GetPayLoad()->GetPaddingErrors())
+ return kTRUE;
+
+ return kFALSE;
+}
+
+
+
+
+