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