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