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