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