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