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