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