1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
19 //-----------------------------------------------------------------------------
20 /// \class AliMUONRawStreamTracker
21 /// This class provides access to MUON digits in raw data.
23 /// It loops over all MUON digits in the raw data given by the AliRawReader.
24 /// The Next method goes to the next digit. If there are no digits left
26 /// It can loop also over DDL and store the decoded rawdata in TClonesArray
29 /// Implement for Tracker
31 /// \author Christian Finck & Laurent Aphecetche
32 //-----------------------------------------------------------------------------
34 #include "AliMUONRawStreamTracker.h"
36 #include "AliMUONLogger.h"
37 #include "AliRawReader.h"
38 #include "AliRawDataHeader.h"
41 #include "AliMUONPayloadTracker.h"
42 #include "AliMUONBlockHeader.h"
43 #include "AliMUONDspHeader.h"
44 #include "AliMUONBusStruct.h"
45 #include "AliMUONDDLTracker.h"
46 #include "Riostream.h"
50 ClassImp(AliMUONRawStreamTracker)
53 const Int_t AliMUONRawStreamTracker::fgkMaxDDL = 20;
56 //___________________________________________
57 AliMUONRawStreamTracker::AliMUONRawStreamTracker()
58 : AliMUONVRawStreamTracker(),
59 fPayload(new AliMUONPayloadTracker()),
61 fCurrentDDLIndex(fgkMaxDDL),
62 fCurrentBlockHeader(0),
63 fCurrentBlockHeaderIndex(0),
65 fCurrentDspHeaderIndex(0),
67 fCurrentBusStructIndex(0),
73 /// create an object to read MUON raw digits
74 /// Default ctor for monitoring purposes
80 //_________________________________________________________________
81 AliMUONRawStreamTracker::AliMUONRawStreamTracker(AliRawReader* rawReader)
82 : AliMUONVRawStreamTracker(rawReader),
83 fPayload(new AliMUONPayloadTracker()),
85 fCurrentDDLIndex(fgkMaxDDL),
86 fCurrentBlockHeader(0),
87 fCurrentBlockHeaderIndex(0),
89 fCurrentDspHeaderIndex(0),
91 fCurrentBusStructIndex(0),
97 /// ctor with AliRawReader as argument
98 /// for reconstruction purpose
104 //___________________________________
105 AliMUONRawStreamTracker::~AliMUONRawStreamTracker()
113 //_____________________________________________________________
115 AliMUONRawStreamTracker::Next(Int_t& busPatchId,
116 UShort_t& manuId, UChar_t& manuChannel,
120 /// read the next raw digit (buspatch structure)
121 /// returns kFALSE if there is no digit left
122 /// Should call First() before this method to start the iteration.
125 if ( IsDone() ) return kFALSE;
127 if ( fCurrentDataIndex >= fCurrentBusStruct->GetLength()-1 )
129 Bool_t ok = GetNextBusStruct();
139 busPatchId = fCurrentBusStruct->GetBusPatchId();
140 manuId = fCurrentBusStruct->GetManuId(fCurrentDataIndex);
141 manuChannel = fCurrentBusStruct->GetChannelId(fCurrentDataIndex);
142 adc = fCurrentBusStruct->GetCharge(fCurrentDataIndex);
147 //______________________________________________________
148 UInt_t AliMUONRawStreamTracker::Next(const AliChannelInfo*& channels)
150 /// This method actually just wraps around the single step Next() method
151 /// for now and returns channels one at a time.
153 Int_t busPatchId; UShort_t manuId; UChar_t manuChannel; UShort_t adc;
154 Bool_t ok = Next(busPatchId, manuId, manuChannel, adc);
157 fChannelBuffer = AliChannelInfo(busPatchId, manuId, manuChannel, adc);
158 channels = &fChannelBuffer;
167 //______________________________________________________
169 AliMUONRawStreamTracker::IsDone() const
171 /// Whether the iteration is finished or not
172 return (fCurrentBusStruct==0);
175 //______________________________________________________
177 AliMUONRawStreamTracker::First()
179 /// Initialize the iteration process.
181 fCurrentDDLIndex = -1;
182 // fCurrentDspHeaderIndex = -1; // Not necessary since this gets reset in the GetNextXXX methods.
183 // fCurrentBusStructIndex = -1;
185 // Must reset all the pointers because if we return before calling
186 // GetNextBusStruct() the user might call CurrentDDL(), CurrentBlockHeader(),
187 // CurrentDspHeader() or CurrentBusStruct() which should return reasonable
188 // results in that case.
190 fCurrentBlockHeader = 0;
191 fCurrentDspHeader = 0;
192 fCurrentBusStruct = 0;
194 // Find the first non-empty structure
195 if (not GetNextDDL()) return;
196 if (not GetNextBlockHeader()) return;
197 if (not GetNextDspHeader()) return;
201 //______________________________________________________
203 AliMUONRawStreamTracker::GetNextDDL()
205 /// Returns the next DDL present
207 assert( GetReader() != 0 );
209 Bool_t kFound(kFALSE);
211 while ( fCurrentDDLIndex < fgkMaxDDL-1 && !kFound )
214 GetReader()->Reset();
215 GetReader()->Select("MUONTRK",fCurrentDDLIndex,fCurrentDDLIndex);
216 if ( GetReader()->ReadHeader() )
224 // fCurrentDDLIndex is set to fgkMaxDDL so that we exit the above loop immediately
225 // for a subsequent call to this method, unless NextEvent is called in between.
226 fCurrentDDLIndex = fgkMaxDDL;
227 // We have not actually been able to complete the loading of the new DDL so
228 // we are still on the old one. In this case we do not need to reset fCurrentDDL.
230 if (IsErrorLogger()) AddErrorMessage();
234 Int_t totalDataWord = GetReader()->GetDataSize(); // in bytes
236 AliDebug(3, Form("DDL Number %d totalDataWord %d\n", fCurrentDDLIndex,
239 UInt_t *buffer = new UInt_t[totalDataWord/4];
241 if ( !GetReader()->ReadNext((UChar_t*)buffer, totalDataWord) )
243 // We have not actually been able to complete the loading of the new DDL so
244 // we are still on the old one. In this case we do not need to reset fCurrentDDL.
249 fPayload->ResetDDL();
252 swap(buffer, totalDataWord); // swap needed for mac power pc
255 Bool_t ok = fPayload->Decode(buffer, totalDataWord/4);
259 fCurrentDDL = fPayload->GetDDLTracker();
261 fCurrentBlockHeaderIndex = -1;
266 //______________________________________________________
268 AliMUONRawStreamTracker::GetNextBlockHeader()
270 /// Returns the next block Header present
272 assert( fCurrentDDL != 0 );
274 fCurrentBlockHeader = 0;
276 Int_t i(fCurrentBlockHeaderIndex);
278 while ( fCurrentBlockHeader == 0 && i < fCurrentDDL->GetBlkHeaderEntries()-1 )
281 fCurrentBlockHeader = fCurrentDDL->GetBlkHeaderEntry(i);
284 if ( !fCurrentBlockHeader )
286 Bool_t ok = GetNextDDL();
293 return GetNextBlockHeader();
297 fCurrentBlockHeaderIndex = i;
299 fCurrentDspHeaderIndex = -1;
304 //______________________________________________________
306 AliMUONRawStreamTracker::GetNextDspHeader()
308 /// Returns the next Dsp Header present
310 assert( fCurrentBlockHeader != 0 );
312 fCurrentDspHeader = 0;
314 Int_t i(fCurrentDspHeaderIndex);
316 while ( fCurrentDspHeader == 0 && i < fCurrentBlockHeader->GetDspHeaderEntries()-1 )
319 fCurrentDspHeader = fCurrentBlockHeader->GetDspHeaderEntry(i);
322 if ( !fCurrentDspHeader )
324 Bool_t ok = GetNextBlockHeader();
331 return GetNextDspHeader();
335 fCurrentDspHeaderIndex = i;
337 fCurrentBusStructIndex = -1;
342 //______________________________________________________
344 AliMUONRawStreamTracker::GetNextBusStruct()
346 /// Find the next non-empty busPatch structure
348 assert( fCurrentDspHeader != 0 );
350 fCurrentBusStruct = 0;
352 Int_t i(fCurrentBusStructIndex);
354 while ( fCurrentBusStruct == 0 && i < fCurrentDspHeader->GetBusPatchEntries()-1 )
357 fCurrentBusStruct = fCurrentDspHeader->GetBusPatchEntry(i);
360 if ( !fCurrentBusStruct )
362 Bool_t ok = GetNextDspHeader();
369 return GetNextBusStruct();
373 fCurrentBusStructIndex = i;
375 fCurrentDataIndex = -1;
380 //______________________________________________________
381 Bool_t AliMUONRawStreamTracker::NextDDL()
383 /// reading tracker DDL
385 assert( GetReader() != 0 );
387 fPayload->ResetDDL();
389 while ( fDDL < fgkMaxDDL )
391 GetReader()->Reset();
392 GetReader()->Select("MUONTRK", fDDL, fDDL); //Select the DDL file to be read
393 if (GetReader()->ReadHeader()) break;
394 AliDebug(3,Form("Skipping DDL %d which does not seem to be there",fDDL));
398 if ( fDDL == fgkMaxDDL )
401 if ( IsErrorLogger()) AddErrorMessage();
405 AliDebug(3, Form("DDL Number %d\n", fDDL ));
407 Int_t totalDataWord = GetReader()->GetDataSize(); // in bytes
409 UInt_t *buffer = new UInt_t[totalDataWord/4];
411 if(!GetReader()->ReadNext((UChar_t*)buffer, totalDataWord))
418 swap(buffer, totalDataWord); // swap needed for mac power pc
421 Bool_t ok = fPayload->Decode(buffer, totalDataWord/4);
430 //______________________________________________________
431 void AliMUONRawStreamTracker::SetMaxBlock(Int_t blk)
433 /// set regional card number
434 fPayload->SetMaxBlock(blk);
437 //______________________________________________________
438 void AliMUONRawStreamTracker::AddErrorMessage()
440 /// add message into logger of AliRawReader per event
442 assert( GetReader() != 0 );
445 AliMUONLogger* log = fPayload->GetErrorLogger();
448 while(log->Next(msg, occurance))
450 if (msg.Contains("Parity"))
451 GetReader()->AddMinorErrorLog(kParityErr, msg.Data());
453 if (msg.Contains("Glitch"))
454 GetReader()->AddMajorErrorLog(kGlitchErr, msg.Data());
456 if (msg.Contains("Padding"))
457 GetReader()->AddMinorErrorLog(kPaddingWordErr, msg.Data());
460 log->Clear(); // clear logger after each event
463 //______________________________________________________
464 Bool_t AliMUONRawStreamTracker::IsErrorMessage() const
466 /// true if there is any error/warning
467 if (GetPayLoad()->GetParityErrors() ||
468 GetPayLoad()->GetGlitchErrors() ||
469 GetPayLoad()->GetPaddingErrors())