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