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