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