]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONDigitizer.cxx
Updated for replacement of AliMpReader with AliMpSectorReader
[u/mrichter/AliRoot.git] / MUON / AliMUONDigitizer.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2000, 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 #include <assert.h>
19
20 #include "AliRun.h"
21 #include "AliRunDigitizer.h"
22 #include "AliRunLoader.h"
23
24 #include "AliMUONDigitizer.h"
25 #include "AliMUONConstants.h"
26 #include "AliMUONChamber.h"
27 #include "AliMUONHitMapA1.h"
28 #include "AliMUON.h"
29 #include "AliMUONLoader.h"
30 #include "AliMUONConstants.h"
31 #include "AliMUONTransientDigit.h"
32 #include "AliMUONTriggerDecision.h"
33 #include "AliLog.h"
34 #include "AliMUONGeometryModule.h"
35 #include "AliMUONGeometryStore.h"
36
37 /////////////////////////////////////////////////////////////////////////////////////
38 //
39 // AliMUONDigitizer should be base abstract class of all digitisers in the MUON 
40 // module. It implements the common functionality of looping over input streams
41 // filling the fTDList and writing the fTDList to the output stream. 
42 // Inheriting digitizers need to override certain methods to choose and initialize
43 // the correct input and output trees, apply the correct detector response if any
44 // and implement how the transient digits are generated from the input stream.
45 //
46 /////////////////////////////////////////////////////////////////////////////////////
47
48 ClassImp(AliMUONDigitizer)
49
50 //___________________________________________
51 AliMUONDigitizer::AliMUONDigitizer() : 
52         AliDigitizer(),
53         fHitMap(0),
54         fTDList(0),
55         fTDCounter(0),
56         fMask(0),
57         fSignal(0)
58 {
59 // Default constructor.
60 // Initializes all pointers to NULL.
61
62         fRunLoader = NULL;
63         fGime = NULL;
64         fMUON = NULL;
65         fMUONData = NULL;
66         fTrigDec = NULL;
67 }
68
69 //___________________________________________
70 AliMUONDigitizer::AliMUONDigitizer(AliRunDigitizer* manager) : 
71         AliDigitizer(manager),
72         fHitMap(0),
73         fTDList(0),
74         fTDCounter(0),
75         fMask(0),
76         fSignal(0)
77 {
78 // Constructor which should be used rather than the default constructor.
79 // Initializes all pointers to NULL.
80
81         fRunLoader = NULL;
82         fGime = NULL;
83         fMUON = NULL;
84         fMUONData = NULL;
85         fTrigDec = NULL;
86 }
87
88 //___________________________________________
89 AliMUONDigitizer::AliMUONDigitizer(const AliMUONDigitizer& rhs)
90   : AliDigitizer(rhs)
91 {
92 // Protected copy constructor
93
94   AliFatal("Not implemented.");
95 }
96
97 //___________________________________________
98 AliMUONDigitizer::~AliMUONDigitizer() 
99 {
100 // Destructor
101   if (fMUONData)
102     delete fMUONData;
103
104   if (fTrigDec)
105     delete fTrigDec;
106 }
107
108 //-------------------------------------------------------------------
109 AliMUONDigitizer&  
110 AliMUONDigitizer::operator=(const AliMUONDigitizer& rhs)
111 {
112 // Protected assignement operator
113
114   if (this == &rhs) return *this;
115
116   AliFatal("Not implemented.");
117     
118   return *this;  
119 }    
120          
121 //------------------------------------------------------------------------
122 Bool_t AliMUONDigitizer::Init()
123 {
124 // Does nothing. 
125         return kTRUE;
126 }
127
128 //------------------------------------------------------------------------
129 void AliMUONDigitizer::Exec(Option_t* /*option*/)
130 {
131 // The main work loop starts here. 
132 // The digitization process is broken up into two steps: 
133 // 1) Loop over input streams and create transient digits from the input.
134 //    Done in GenerateTransientDigits()
135 // 2) Loop over the generated transient digits and write them to the output
136 //    stream. Done in CreateDigits()
137
138         AliDebug(1, "Running digitiser.");
139
140         if (fManager->GetNinputs() == 0)
141         {
142                 AliWarning("No inputs set, nothing to do.");
143                 return;
144         }
145
146         if (!FetchLoaders(fManager->GetInputFolderName(0), fRunLoader, fGime) ) return;
147         if (! FetchGlobalPointers(fRunLoader) ) return;
148         if (! FetchTriggerPointer(fGime) ) return;
149
150         InitArrays();
151         
152         AliDebug(2, Form("Event Number is %d.", fManager->GetOutputEventNr()));
153
154         // Loop over files to merge and to digitize
155         fSignal = kTRUE;
156         for (Int_t inputFile = 0; inputFile < fManager->GetNinputs(); inputFile++)
157         {
158                 fMask = fManager->GetMask(inputFile);
159                 AliDebug(2, Form("Digitising folder %d, with fMask = %d: %s", inputFile, fMask,
160                              (const char*)fManager->GetInputFolderName(inputFile)));
161
162                 if (inputFile != 0)
163                         // If this is the first file then we already have the loaders loaded.
164                         if (! FetchLoaders(fManager->GetInputFolderName(inputFile), fRunLoader, fGime) )
165                                 continue;
166                 else
167                         // If this is not the first file then it is assumed to be background.
168                         fSignal = kFALSE;
169
170                 if (! InitInputData(fGime) ) continue;
171                 GenerateTransientDigits();
172                 CleanupInputData(fGime);
173         }
174
175         Bool_t ok = FetchLoaders(fManager->GetOutputFolderName(), fRunLoader, fGime);
176         if (ok) ok = InitOutputData(fGime);
177         if (ok) CreateDigits();
178         if (ok) CreateTrigger();
179         if (ok) CleanupOutputData(fGime);
180
181         CleanupArrays();
182         CleanupTriggerArrays();
183 }
184
185 //--------------------------------------------------------------------------
186 void AliMUONDigitizer::AddOrUpdateTransientDigit(AliMUONTransientDigit* mTD)
187 {
188 // Checks to see if the transient digit exists in the corresponding fHitMap.
189 // If it does then the digit is updated otherwise it is added. 
190
191         if (ExistTransientDigit(mTD)) 
192         {
193                 UpdateTransientDigit(mTD);
194                 delete mTD;  // The new digit can be deleted because it was not added.
195         }
196         else 
197                 AddTransientDigit(mTD);
198 }
199
200 //------------------------------------------------------------------------
201 void AliMUONDigitizer::UpdateTransientDigit(AliMUONTransientDigit* mTD)
202 {
203 // Update the transient digit that is already in the fTDList by adding the new
204 // transient digits charges and track lists to the existing one.
205
206         AliDebug(4,Form( "Updating transient digit 0x%X", (void*)mTD));
207         // Choosing the maping of the cathode plane of the chamber:
208         Int_t detElemId =  mTD->DetElemId();
209
210         Int_t iNchCpl= fNDetElemId[detElemId] + (mTD->Cathode()-1) * AliMUONConstants::NDetElem();
211
212         AliMUONTransientDigit *pdigit = 
213                 static_cast<AliMUONTransientDigit*>( fHitMap[iNchCpl]->GetHit(mTD->PadX(),mTD->PadY()) );
214
215         // update charge
216         pdigit->AddSignal( mTD->Signal() );
217         pdigit->AddPhysicsSignal( mTD->Physics() );  
218         
219         // update list of tracks
220         Int_t ntracks = mTD->GetNTracks();
221         if (ntracks > kMAXTRACKS)  // Truncate the number of tracks to kMAXTRACKS if we have to.
222         {
223                 AliDebug(1,Form( 
224                         "TransientDigit returned the number of tracks to be %d, which is bigger than kMAXTRACKS.",
225                         ntracks));
226                 AliDebug(1,Form( "Reseting the number of tracks to be %d.", kMAXTRACKS));
227                 ntracks = kMAXTRACKS;
228         }
229         
230         for (Int_t i = 0; i < ntracks; i++)
231         {
232                 pdigit->UpdateTrackList( mTD->GetTrack(i), mTD->GetCharge(i) );
233         }
234 }
235
236 //------------------------------------------------------------------------
237 void AliMUONDigitizer::AddTransientDigit(AliMUONTransientDigit* mTD)
238 {
239 // Adds the transient digit to the fTDList and sets the appropriate entry
240 // in the fHitMap arrays. 
241
242         AliDebug(4,Form( "Adding transient digit 0x%X", (void*)mTD));
243         // Choosing the maping of the cathode plane of the chamber:
244
245         Int_t detElemId =  mTD->DetElemId();
246         Int_t iNchCpl= fNDetElemId[detElemId] + (mTD->Cathode()-1) * AliMUONConstants::NDetElem();
247
248         fTDList->AddAtAndExpand(mTD, fTDCounter);
249         if (iNchCpl>-1 && iNchCpl<2*AliMUONConstants::NDetElem()) {
250           fHitMap[iNchCpl]->SetHit( mTD->PadX(), mTD->PadY(), fTDCounter);
251           fTDCounter++;
252         }
253 }
254
255 //------------------------------------------------------------------------
256 Bool_t AliMUONDigitizer::ExistTransientDigit(AliMUONTransientDigit* mTD)
257 {
258 // Checks if the transient digit already exists on the corresponding fHitMap.
259 // i.e. is there a transient digit on the same chamber, cathode and pad position 
260 // as mTD. If yes then kTRUE is returned else kFASLE is returned.
261
262         // Choosing the maping of the cathode plane of the chamber:
263         Int_t detElemId =  mTD->DetElemId();
264
265         Int_t iNchCpl= fNDetElemId[detElemId] + (mTD->Cathode()-1) *AliMUONConstants::NDetElem() ;
266
267         //      Int_t iNchCpl= mTD->Chamber() + (mTD->Cathode()-1) * AliMUONConstants::NCh();
268         if (iNchCpl>-1 && iNchCpl<2*AliMUONConstants::NDetElem())
269           return( fHitMap[iNchCpl]->TestHit(mTD->PadX(), mTD->PadY()) );
270         else return kFALSE;
271 }
272
273 //-----------------------------------------------------------------------
274 void AliMUONDigitizer::CreateDigits()
275 {
276 // Loops over the fTDList for each cathode, gets the correct signal for the 
277 // digit and adds the new digit to the output stream.
278
279         fTDList->Sort(); // sort by idDE
280         AliDebug(2, "Creating digits...");
281         //      for (Int_t icat = 0; icat < 2; icat++) {
282
283           Int_t digitindex[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
284
285           //
286           // Filling Digit List
287           Int_t nentries = fTDList->GetEntriesFast();
288           for (Int_t nent = 0; nent < nentries; nent++) {
289
290             AliMUONTransientDigit* td = (AliMUONTransientDigit*)fTDList->At(nent);
291             if (td == NULL) continue; 
292                         
293             // Must be the same cathode, otherwise we will fill a mixture
294             // of digits from both cathodes.
295             //if (icat != td->Cathode() - 1) continue;
296                         
297             AliDebug(3,Form( "Creating digit from transient digit 0x%X", (void*)td));
298
299             Int_t q = GetSignalFrom(td);
300             assert( 0 <= td->Chamber() && td->Chamber() <= 13 );
301             if (q > 0) AddDigit(td, q, digitindex[td->Chamber()]++);
302           }
303           FillOutputData();
304           //    }
305           fTDCounter = 0;
306 }
307
308 //------------------------------------------------------------------------
309 void AliMUONDigitizer::AddDigit(
310                 AliMUONTransientDigit* td, Int_t responseCharge,
311                 Int_t digitindex
312         )
313 {
314 // Prepares the digits, track and charge arrays in preparation for a call to
315 // AddDigit(Int_t, Int_t[kMAXTRACKS], Int_t[kMAXTRACKS], Int_t[6])
316 // This method is called by CreateDigits() whenever a new digit needs to be added
317 // to the output stream trees.
318 // The responseCharge value is used as the Signal of the new digit. 
319 // The OnWriteTransientDigit method is also called just before the adding the 
320 // digit to allow inheriting digitizers to be able to do some specific processing 
321 // at this point. 
322
323         Int_t tracks[kMAXTRACKS];
324         Int_t charges[kMAXTRACKS];
325         Int_t digits[7];
326       
327         digits[0] = td->PadX();
328         digits[1] = td->PadY();
329         digits[2] = td->Cathode() - 1;
330         digits[3] = responseCharge;
331         digits[4] = td->Physics();
332         digits[5] = td->Hit();
333         digits[6] =  td->DetElemId();
334
335         Int_t nptracks = td->GetNTracks();
336         if (nptracks > kMAXTRACKS) {
337
338           AliDebug(1, Form(
339                            "TransientDigit returned the number of tracks to be %d, which is bigger than kMAXTRACKS.",
340                            nptracks));
341           AliDebug(1, Form("Reseting the number of tracks to be %d.", kMAXTRACKS));
342           nptracks = kMAXTRACKS;
343         }
344         
345         for (Int_t i = 0; i < nptracks; i++) {
346
347           tracks[i]   = td->GetTrack(i);
348           charges[i]  = td->GetCharge(i);
349         }
350
351         // Sort list of tracks according to charge
352         SortTracks(tracks,charges,nptracks);
353
354         if (nptracks < kMAXTRACKS ) {
355
356           for (Int_t i = nptracks; i < kMAXTRACKS; i++) {
357             tracks[i]  = -1;
358             charges[i] = 0;
359           }
360         }
361
362         AliDebug(4,Form( "Adding digit with charge %d.", responseCharge));
363
364         OnWriteTransientDigit(td);
365         AddDigit(td->Chamber(), tracks, charges, digits);
366         AddDigitTrigger(td->Chamber(), tracks, charges, digits, digitindex);
367 }
368
369 //------------------------------------------------------------------------
370 void AliMUONDigitizer::OnCreateTransientDigit(AliMUONTransientDigit* /*digit*/, TObject* /*source_object*/)
371 {
372         // Does nothing.
373         //
374         // This is derived by Digitisers that want to trace which digits were made from
375         // which hits.
376 }
377
378 //------------------------------------------------------------------------
379 void AliMUONDigitizer::OnWriteTransientDigit(AliMUONTransientDigit* /*digit*/)
380 {
381         // Does nothing.
382         //
383         // This is derived by Digitisers that want to trace which digits were made from
384         // which hits.
385 }
386
387 //------------------------------------------------------------------------
388 Bool_t AliMUONDigitizer::FetchLoaders(const char* foldername, AliRunLoader*& runloader, AliMUONLoader*& muonloader)
389 {
390 // Fetches the run loader from the current folder, specified by 'foldername'. 
391 // The muon loader is then loaded from the fetched run loader. 
392 // kTRUE is returned if no error occurred otherwise kFALSE is returned. 
393
394         AliDebug(3, Form("Fetching run loader and muon loader from folder: %s", foldername));
395
396         runloader = AliRunLoader::GetRunLoader(foldername);
397         if (runloader == NULL)
398         {
399                 AliError(Form("RunLoader not found in folder: %s", foldername));
400                 return kFALSE; 
401         }                                                                                       
402         muonloader = (AliMUONLoader*) runloader->GetLoader("MUONLoader");
403         if (muonloader == NULL) 
404         {
405                 AliError(Form("MUONLoader not found in folder: %s", foldername));
406                 return kFALSE; 
407         }
408         return kTRUE;
409
410 }
411
412 //------------------------------------------------------------------------
413 Bool_t AliMUONDigitizer::FetchGlobalPointers(AliRunLoader* runloader)
414 {
415 // Fetches the AliRun object into the global gAlice pointer from the specified
416 // run loader. The AliRun object is loaded into memory using the run loader if 
417 // not yet loaded. The MUON module object is then loaded from gAlice and 
418 // AliMUONData fetched from the MUON module. 
419 // kTRUE is returned if no error occurred otherwise kFALSE is returned. 
420
421         AliDebug(3, Form("Fetching gAlice, MUON module and AliMUONData from runloader 0x%X.",
422                         (void*)runloader
423                     ));
424
425         if (runloader->GetAliRun() == NULL) runloader->LoadgAlice();
426         gAlice = runloader->GetAliRun();
427         if (gAlice == NULL)
428         {
429                 AliError(Form("Could not find the AliRun object in runloader 0x%X.", (void*)runloader));
430                 return kFALSE;
431         }
432         fMUON = (AliMUON*) gAlice->GetDetector("MUON");
433         if (fMUON == NULL)
434         {
435                 AliError(Form("Could not find the MUON module in runloader 0x%X.", (void*)runloader));
436                 return kFALSE;
437         }
438
439         AliMUONLoader *muonloader = (AliMUONLoader*) runloader->GetLoader("MUONLoader");
440         if (muonloader == NULL) 
441         {
442                 AliError( "MUONLoader not found ");
443                 return kFALSE; 
444         }
445
446
447         if (fMUONData == NULL) fMUONData = new AliMUONData(muonloader,"MUON","MUON");
448         if (fMUONData == NULL)
449         {
450                 AliError(Form("Could not find AliMUONData object in runloader 0x%X.", (void*)runloader));
451                 return kFALSE;
452         }
453
454         return kTRUE;
455 }
456 //-----------------------------------------------------------------------
457 Bool_t  AliMUONDigitizer::FetchTriggerPointer(AliMUONLoader* loader)
458 {
459   if (fMUONData == NULL) {
460     AliError("MUONData not found");
461     return kFALSE;
462   }
463
464   if (fTrigDec == NULL) 
465       fTrigDec = new AliMUONTriggerDecision(loader,0,fMUONData);
466   
467   return kTRUE;
468 }
469
470 //------------------------------------------------------------------------
471 void AliMUONDigitizer::InitArrays()
472 {
473 // Creates a new fTDList object. 
474 // Also creates an array of 2 * chamber_number AliMUONHitMapA1 objects
475 // in the fHitMaps array. Each one is set to a chamber and cathode
476 // specific segmentation model. 
477 //
478 // Note: the fTDList and fHitMap arrays must be NULL before calling this method.
479
480     AliDebug(2, "Initialising internal arrays.");
481     AliDebug(4, "Creating transient digits list.");
482     fTDList = new TObjArray;
483         
484     // Array of pointer of the AliMUONHitMapA1:
485     //  two HitMaps per chamber, or one HitMap per cahtode plane
486     fHitMap = new AliMUONHitMapA1* [2*AliMUONConstants::NDetElem()];
487     for (Int_t i=0; i<2*AliMUONConstants::NDetElem(); i++) fHitMap[i] = 0x0;
488
489     Int_t k = 0;
490     Int_t idDE;
491
492     for (Int_t i = 0; i < AliMUONConstants::NCh(); i++) {
493
494
495       AliDebug(4,Form( "Creating hit map for chamber %d, cathode 1.", i+1));
496       AliMUONChamber* chamber = &(fMUON->Chamber(i));
497       AliMUONGeometrySegmentation* c1Segmentation = chamber->SegmentationModel2(1); // Cathode plane 1
498       AliDebug(4,Form( "Creating hit map for chamber %d, cathode 2.", i+1));
499       AliMUONGeometrySegmentation* c2Segmentation = chamber->SegmentationModel2(2); // Cathode plane 2
500
501       AliMUONGeometryModule* geometry    = fMUON->Chamber(i).GetGeometry();
502       AliMUONGeometryStore*  detElements = geometry->GetDetElementStore();
503     
504
505     // Loop over detection elements
506       for (Int_t j=0; j<detElements->GetNofEntries(); j++) {
507        
508         idDE = detElements->GetEntry(j)->GetUniqueID();
509         fNDetElemId[idDE] = k;
510
511         fHitMap[k] = new AliMUONHitMapA1(idDE,c1Segmentation, fTDList); 
512      
513         fHitMap[k+AliMUONConstants::NDetElem()] = new AliMUONHitMapA1(idDE,c2Segmentation, fTDList);
514         k++;
515       }
516     }
517 }
518 //------------------------------------------------------------------------
519 void AliMUONDigitizer::CleanupArrays()
520 {
521 // The arrays fTDList and fHitMap are deleted and the pointers set to NULL.
522
523         AliDebug(2, "Deleting internal arrays.");
524         for(Int_t i = 0; i < 2*AliMUONConstants::NDetElem(); i++) {
525                 delete fHitMap[i];
526         }
527         delete [] fHitMap;
528         fHitMap = NULL;
529         
530         AliDebug(4, "Deleting transient digits list.");
531         fTDList->Delete();
532         delete fTDList;
533         fTDList = NULL;
534
535 }
536
537 //------------------------------------------------------------------------
538 void AliMUONDigitizer::SortTracks(Int_t *tracks, Int_t *charges, Int_t ntr) const
539 {
540 //
541 // Sort the list of tracks contributing to a given digit
542 // Only the 3 most significant tracks are actually sorted
543 //
544
545        if (ntr <= 1) return;
546
547        //
548        //  Loop over signals, only 3 times
549        //
550
551        Int_t qmax;
552        Int_t jmax;
553        Int_t idx[3] = {-2,-2,-2};
554        Int_t jch[3] = {-2,-2,-2};
555        Int_t jtr[3] = {-2,-2,-2};
556        Int_t i, j, imax;
557
558        if (ntr < 3) imax = ntr;
559        else imax=3;
560         
561        for(i = 0; i < imax; i++)
562          {
563            qmax=0;
564            jmax=0;
565
566            for(j = 0; j < ntr; j++)
567              {
568                if (     (i == 1 && j == idx[i-1]) || 
569                         (i == 2 && (j == idx[i-1] || j == idx[i-2]))
570                         ) 
571                  continue;
572
573                if(charges[j] > qmax) 
574                  {
575                    qmax = charges[j];
576                    jmax = j;
577                  }       
578              } 
579
580            if(qmax > 0)
581              {
582                idx[i] = jmax;
583                jch[i] = charges[jmax]; 
584                jtr[i] = tracks[jmax]; 
585              }
586
587          } 
588
589        for(i = 0; i < 3; i++)
590          {
591            if (jtr[i] == -2) 
592              {
593                charges[i] = 0;
594                tracks[i] = 0;
595              } 
596            else 
597              {
598                charges[i] = jch[i];
599                tracks[i] = jtr[i];
600              }
601          }
602 }