- extend the range of "numbered" boards from 234 to 242 by adding the 8
[u/mrichter/AliRoot.git] / MUON / AliMUONDigitMaker.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
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  **************************************************************************/
15
16 // $Id$
17
18 //-----------------------------------------------------------------------------
19 /// \class AliMUONDigitMaker
20 /// MUON Digit maker from rawdata.
21 ///
22 /// Raw2Digits:
23 /// Using real mapping  for tracker
24 /// Indranil Das (Adapted for runloader: Ch. Finck) july 05
25 ///
26 /// Implemented non-constant buspatch numbers for tracking
27 /// with correct DDL id.
28 /// (Ch. Finck, dec 05)
29 ///
30 /// Add reader for scaler trigger events
31 /// Use memcpy instead of assignment elt by elt
32 /// (Ch. Finck, Jan 06)
33 ///
34 /// Using new interface with AliMUONRawStreamTracker(Trigger)
35 /// (New interface of AliMUONRawReader class)
36 /// (further details could be found in Alice-note)
37 /// (Ch. Finck, March 06)
38 ///
39 /// Add (S)Digit maker tracker (for free)
40 /// and for trigger. Create trigger inverse mapping.
41 ///
42 /// \author Ch. Finck, oct 06 
43 //-----------------------------------------------------------------------------
44
45 #include "AliMUONDigitMaker.h"
46
47 #include "AliMUONDDLTrigger.h"
48 #include "AliMUONDarcHeader.h"
49 #include "AliMUONVDigit.h"
50 #include "AliMUONVDigitStore.h"
51 #include "AliMUONGlobalTrigger.h"
52 #include "AliMUONLocalStruct.h"
53 #include "AliMUONLocalTrigger.h"
54 #include "AliMUONLogger.h"
55 #include "AliMUONRawStreamTrackerHP.h"
56 #include "AliMUONRawStreamTriggerHP.h"
57 #include "AliMUONRegHeader.h"
58 #include "AliMUONVTriggerStore.h"
59 #include "AliMpCDB.h"
60 #include "AliMpDetElement.h"
61 #include "AliMpTriggerCrate.h"
62 #include "AliMpLocalBoard.h"
63 #include "AliMpCathodType.h"
64 #include "AliMpDDLStore.h"
65 #include "AliMpDEManager.h"
66 #include "AliMpPad.h"
67 #include "AliMpSegmentation.h"
68 #include "AliMpVSegmentation.h"
69 #include "AliCodeTimer.h"
70 #include "AliLog.h"
71 #include "AliRawReader.h"
72 #include <TArrayS.h>
73
74 using std::endl;
75 using std::cout;
76 /// \cond CLASSIMP
77 ClassImp(AliMUONDigitMaker) // Class implementation in ROOT context
78 /// \endcond
79
80 //__________________________________________________________________________
81 AliMUONDigitMaker::AliMUONDigitMaker(Bool_t enableErrorLogger, Bool_t a, Bool_t b) :
82 TObject(),
83 fScalerEvent(kFALSE),
84 fMakeTriggerDigits(kFALSE),
85 fRawStreamTracker(new AliMUONRawStreamTrackerHP),
86 fRawStreamTrigger(new AliMUONRawStreamTriggerHP),
87 fDigitStore(0x0),
88 fTriggerStore(0x0),
89 fLogger(new AliMUONLogger(10000)){
90   /// ctor 
91   
92   if  ( !a || !b ) AliFatal("no longer supported");
93   
94   AliDebug(1,"");
95   
96   // Standard Constructor
97   if (enableErrorLogger) 
98   {
99     fRawStreamTracker->EnabbleErrorLogger();
100     fRawStreamTrigger->EnabbleErrorLogger();
101   }
102   else
103   {
104     fRawStreamTracker->DisableWarnings();
105   }
106   
107   SetMakeTriggerDigits();
108   
109   // Load mapping
110   if ( ! AliMpCDB::LoadDDLStore() ) {
111     AliFatal("Could not access mapping from OCDB !");
112   }
113 }
114
115 //__________________________________________________________________________
116 AliMUONDigitMaker::AliMUONDigitMaker(Bool_t enableErrorLogger) :
117 TObject(),
118     fScalerEvent(kFALSE),
119     fMakeTriggerDigits(kFALSE),
120     fRawStreamTracker(new AliMUONRawStreamTrackerHP),
121     fRawStreamTrigger(new AliMUONRawStreamTriggerHP),
122     fDigitStore(0x0),
123     fTriggerStore(0x0),
124   fLogger(new AliMUONLogger(10000))
125 {
126   /// ctor 
127
128   AliDebug(1,"");
129   
130   // Standard Constructor
131   if (enableErrorLogger) 
132   {
133     fRawStreamTracker->EnabbleErrorLogger();
134     fRawStreamTrigger->EnabbleErrorLogger();
135   }
136   else
137   {
138     fRawStreamTracker->DisableWarnings();
139   }
140
141   SetMakeTriggerDigits();
142
143   // Load mapping
144   if ( ! AliMpCDB::LoadDDLStore() ) {
145     AliFatal("Could not access mapping from OCDB !");
146   }
147 }
148
149 //__________________________________________________________________________
150 AliMUONDigitMaker::~AliMUONDigitMaker()
151 {
152   /// clean up
153   /// and time processing measure
154
155   delete fRawStreamTracker;
156   delete fRawStreamTrigger;
157   delete fLogger;
158 }
159
160 //____________________________________________________________________
161 void
162 AliMUONDigitMaker::Print(Option_t*) const
163 {
164   /// Printout
165
166   cout << "RawStreamerTracker class=" << fRawStreamTracker->ClassName()
167        << " MakeTriggerDigits=" << fMakeTriggerDigits
168        << " ScalerEvent=" << fScalerEvent
169        << " DigitStore=" << fDigitStore
170        << " TriggerStore=" << fTriggerStore << endl;
171
172   if ( fLogger ) fLogger->Print();
173 }
174
175 //____________________________________________________________________
176 Int_t
177 AliMUONDigitMaker::Raw2Digits(AliRawReader* rawReader, 
178                                         AliMUONVDigitStore* digitStore,
179                                         AliMUONVTriggerStore* triggerStore)
180 {
181   /// Main method to creates digit
182   /// for tracker 
183   /// and trigger
184
185   AliDebug(1,Form("rawReader=%p digitStore=%p triggerStore=%p",
186                   rawReader,digitStore,triggerStore));
187   
188   fDigitStore = digitStore;
189   fTriggerStore = triggerStore;
190   
191   if (!fDigitStore && !fTriggerStore)
192   {
193     fLogger->Log("No digit or trigger store given. Nothing to do...");
194     return kTriggerBAD & kTrackerBAD;
195   }
196   
197   Int_t tracker(kOK);
198   Int_t trigger(kOK);
199   
200   if ( fDigitStore ) 
201   {
202     fDigitStore->Clear(); // insure we start with an empty container
203     tracker = ReadTrackerDDL(rawReader);
204   }
205   
206   if ( fTriggerStore || fMakeTriggerDigits ) 
207   {
208     if ( fTriggerStore ) fTriggerStore->Clear();
209     if ( fMakeTriggerDigits && !fDigitStore ) 
210     {
211       fLogger->Log("Asking for trigger digits but digitStore is null");
212     }
213     else
214     {
215       trigger = ReadTriggerDDL(rawReader);
216     }
217   }
218   
219   return tracker | trigger;
220 }
221
222 //____________________________________________________________________
223 Int_t
224 AliMUONDigitMaker::ReadTrackerDDL(AliRawReader* rawReader)
225 {
226   /// Reading tracker DDL
227   /// filling the fDigitStore container, which must not be null
228
229   AliDebug(1,"");
230   
231   AliCodeTimerAuto("",0);
232
233   // elex info
234   Int_t    buspatchId;
235   UChar_t  channelId;
236   UShort_t manuId;
237   UShort_t charge; 
238
239   fRawStreamTracker->SetReader(rawReader);
240   fRawStreamTracker->First();
241   
242   while ( fRawStreamTracker->Next(buspatchId,manuId,channelId,charge,kTRUE) )
243   {    
244     // getting DE from buspatch
245     Int_t detElemId = AliMpDDLStore::Instance()->GetDEfromBus(buspatchId);
246
247     AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
248
249     if (!de)
250       {
251         fLogger->Log(Form("DE %04d does not exist !", detElemId));
252         continue;
253       }
254
255     if (!de->IsConnectedChannel(manuId,channelId))
256       {
257         // non connected pad, do nothing (this is not an error !)
258         continue;
259       }
260
261     const AliMpVSegmentation* seg 
262       = AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(detElemId, 
263                                                                       manuId);  
264
265     if (!seg)
266     {
267       fLogger->Log(Form("(DE,MANUID)=(%04d,%04d) is not valid",detElemId,manuId));
268       continue;
269     }
270     
271     AliMp::CathodType cathodeType = de->GetCathodType(seg->PlaneType());
272
273     AliMpPad pad = seg->PadByLocation(manuId,channelId,kFALSE);
274
275     if (!pad.IsValid())
276     {
277       fLogger->Log(Form("No pad for detElemId: %d, manuId: %d, channelId: %d",
278                     detElemId, manuId, channelId));
279       continue;
280     } 
281
282     AliMUONVDigit* digit = fDigitStore->Add(detElemId,manuId,channelId,cathodeType,
283                                             AliMUONVDigitStore::kDeny);
284
285     if (!digit)
286     {
287       fLogger->Log(Form("Digit DE %04d Manu %04d Channel %02d could not be added",
288                     detElemId, manuId, channelId));
289       continue;
290     }
291     
292     digit->SetPadXY(pad.GetIx(),pad.GetIy());
293     
294     digit->SetADC(charge);
295
296   }
297   
298   if ( fRawStreamTracker->IsErrorMessage() ) 
299   {
300     return kTrackerBAD;
301   }
302   
303   return kOK;
304 }
305
306 //____________________________________________________________________
307 Int_t
308 AliMUONDigitMaker::ReadTriggerDDL(AliRawReader* rawReader)
309 {
310   /// reading tracker DDL like ReadTriggerDDL but with fast decoder interface.
311   /// filling the fTriggerStore container, which must not be null
312
313   const AliMUONRawStreamTriggerHP::AliHeader*          darcHeader  = 0x0;
314   const AliMUONRawStreamTriggerHP::AliRegionalHeader*  regHeader   = 0x0;
315   const AliMUONRawStreamTriggerHP::AliLocalStruct*     localStruct = 0x0;
316
317   Int_t loCircuit;
318
319   fRawStreamTrigger->SetReader(rawReader);
320
321   while (fRawStreamTrigger->NextDDL())
322   {
323     darcHeader = fRawStreamTrigger->GetHeaders();
324     
325     // fill global trigger information
326     if (fTriggerStore) 
327     {
328       if (darcHeader->GetGlobalFlag()) 
329       {
330           AliMUONGlobalTrigger globalTrigger;
331           globalTrigger.SetFromGlobalResponse(darcHeader->GetGlobalOutput());
332           globalTrigger.SetFromGlobalInput(darcHeader->GetGlobalHeader()->fInput);
333           fTriggerStore->SetGlobal(globalTrigger);
334       }
335     }
336     
337     Int_t nReg = fRawStreamTrigger->GetRegionalHeaderCount();
338     
339     for(Int_t iReg = 0; iReg < nReg ;iReg++)
340     {   //reg loop
341       
342
343       // crate info  
344       AliMpTriggerCrate* crate = AliMpDDLStore::Instance()->
345                                 GetTriggerCrate(fRawStreamTrigger->GetDDL(), iReg);
346       
347       if (!crate) {
348         fLogger->Log(Form("Missing crate number %d in DDL %d\n", iReg, fRawStreamTrigger->GetDDL()));
349         continue;
350       }
351       
352       regHeader =  fRawStreamTrigger->GetRegionalHeader(iReg);
353       
354       Int_t nLocal = regHeader->GetLocalStructCount();
355       for(Int_t iLocal = 0; iLocal < nLocal; iLocal++) 
356       {
357         
358         localStruct = regHeader->GetLocalStruct(iLocal);
359         
360         // if card exist
361         if (localStruct) {
362           
363           loCircuit = crate->GetLocalBoardId(localStruct->GetId());
364           
365           if ( !loCircuit ) continue; // empty slot
366           
367           
368           if (fTriggerStore)
369           {
370             // fill local trigger
371             AliMUONLocalTrigger localTrigger;
372             localTrigger.SetLocalStruct(loCircuit, *localStruct);
373             fTriggerStore->Add(localTrigger);
374           }
375           
376           if ( fMakeTriggerDigits )
377           {
378             //FIXEME should find something better than a TArray
379             TArrayS xyPattern[2];
380             
381             localStruct->GetXPattern(xyPattern[0]);
382             localStruct->GetYPattern(xyPattern[1]);
383             
384             TriggerDigits(loCircuit, xyPattern, *fDigitStore);
385           }
386         } // if triggerY
387       } // iLocal
388     } // iReg
389   } // NextDDL
390   
391   return kOK;
392 }
393
394 //____________________________________________________________________
395 Int_t AliMUONDigitMaker::TriggerDigits(Int_t nBoard, 
396                                        const TArrayS* xyPattern,
397                                        AliMUONVDigitStore& digitStore, Bool_t warn) const
398 {
399   /// make digits for trigger from pattern, and add them to digitStore
400
401   AliCodeTimerAuto("",0);
402   
403   Int_t detElemId;
404
405   AliMpLocalBoard* localBoard = AliMpDDLStore::Instance()->GetLocalBoard(nBoard);
406   
407   if ( ! localBoard->IsNotified() ) {
408     // Copy board
409     // The mapping is not correct for copy boards
410     // Use the one of corresponding phyiscal board
411     nBoard = localBoard->GetInputXfrom();
412   }
413
414   Int_t n,b;
415
416   // loop over x1-4 and y1-4
417   for (Int_t iChamber = 0; iChamber < 4; ++iChamber)
418   {
419     for (Int_t iCath = 0; iCath < 2; ++iCath)
420     {
421       Int_t pattern = (Int_t)xyPattern[iCath].At(iChamber); 
422       if (!pattern) continue;
423       
424       // get detElemId
425       detElemId = AliMpDDLStore::Instance()->GetDEfromLocalBoard(nBoard, iChamber);
426         
427         const AliMpVSegmentation* seg 
428           = AliMpSegmentation::Instance()
429           ->GetMpSegmentation(detElemId, AliMp::GetCathodType(iCath));  
430         
431         // loop over the 16 bits of pattern
432         for (Int_t ibitxy = 0; ibitxy < 16; ++ibitxy) 
433         {
434           if ((pattern >> ibitxy) & 0x1) 
435           {            
436             // not quite sure about this
437             Int_t offset = 0;
438             if (iCath && localBoard->GetSwitch(AliMpLocalBoard::kZeroAllYLSB)) offset = -8;
439             
440             AliMpPad pad = seg->PadByLocation(nBoard,ibitxy+offset,warn);
441                         
442             if (!pad.IsValid()) 
443             {
444               fLogger->Log(Form("No pad for detElemId: %d, nboard %d, ibitxy: %d\n",
445                               detElemId, nBoard, ibitxy));
446               continue;
447             }
448
449             n = pad.GetLocalBoardId(0); // always take first location so that digits are not inserted several times
450             b = pad.GetLocalBoardChannel(0);
451
452             AliDebug(1,Form("Using localBoard %d ixy %d instead of %d,%d",
453                             n,b,nBoard,ibitxy));
454
455             AliMUONVDigit* digit = digitStore.Add(detElemId,n,b,iCath,AliMUONVDigitStore::kDeny);
456             
457             if (!digit)
458             {
459                 AliDebug(1, Form("Digit DE %04d LocalBoard %03d ibitxy %02d cath %d already in store",
460                                  detElemId,nBoard,ibitxy,iCath));
461                 continue;
462             }
463             
464             Int_t padX = pad.GetIx();
465             Int_t padY = pad.GetIy();
466             
467             // fill digit
468             digit->SetPadXY(padX,padY);
469             digit->SetCharge(1.);
470           }// xyPattern
471         }// ibitxy
472     }// cath
473   } // ichamber
474   
475   return kTRUE;
476 }
477
478 //______________________________________________________________________________
479 Bool_t 
480 AliMUONDigitMaker::TriggerToDigitsStore(const AliMUONVTriggerStore& triggerStore,
481                                         AliMUONVDigitStore& digitStore) const
482 {
483   //
484   /// make (S)Digit for trigger
485   //
486   
487   digitStore.Clear();
488   
489   AliMUONLocalTrigger* locTrg;
490   TIter next(triggerStore.CreateLocalIterator());
491   
492   while ( ( locTrg = static_cast<AliMUONLocalTrigger*>(next()) ) ) 
493   {
494     if (locTrg->IsNull()) continue;
495    
496     TArrayS xyPattern[2];
497     locTrg->GetXPattern(xyPattern[0]);
498     locTrg->GetYPattern(xyPattern[1]);
499
500     Int_t nBoard = locTrg->LoCircuit();
501     TriggerDigits(nBoard, xyPattern, digitStore);
502   }
503   return kTRUE;
504 }
505
506 //______________________________________________________________________________
507 void 
508 AliMUONDigitMaker::SetTryRecover(Bool_t flag) 
509 {
510   /// Instruct the decoder to try to recover corrupted raw data.
511   /// Only use for specific cases for which you know it will work...
512   fRawStreamTracker->TryRecover(flag);
513 }