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