1 /**************************************************************************
2 * Copyright(c) 1998-2000, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 #include <Riostream.h>
19 #include <TDirectory.h>
23 #include "AliRunDigitizer.h"
24 #include "AliRunLoader.h"
25 #include "AliLoader.h"
27 #include "AliMUONDigitizer.h"
28 #include "AliMUONConstants.h"
29 #include "AliMUONChamber.h"
30 #include "AliMUONHitMapA1.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"
41 /////////////////////////////////////////////////////////////////////////////////////
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.
50 /////////////////////////////////////////////////////////////////////////////////////
52 ClassImp(AliMUONDigitizer)
54 //___________________________________________
55 AliMUONDigitizer::AliMUONDigitizer() :
64 // Default constructor.
65 // Initializes all pointers to NULL.
73 //___________________________________________
74 AliMUONDigitizer::AliMUONDigitizer(AliRunDigitizer* manager) :
75 AliDigitizer(manager),
83 // Constructor which should be used rather than the default constructor.
84 // Initializes all pointers to NULL.
92 //___________________________________________
93 AliMUONDigitizer::~AliMUONDigitizer()
98 //------------------------------------------------------------------------
99 Bool_t AliMUONDigitizer::Init()
105 //------------------------------------------------------------------------
106 void AliMUONDigitizer::Exec(Option_t* option)
108 // The main work loop starts here.
109 // The digitization process is broken up into two steps:
110 // 1) Loop over input streams and create transient digits from the input.
111 // Done in GenerateTransientDigits()
112 // 2) Loop over the generated transient digits and write them to the output
113 // stream. Done in CreateDigits()
115 if (GetDebug() > 0) Info("Exec", "Running digitiser.");
116 ParseOptions(option);
118 if (fManager->GetNinputs() == 0)
120 Warning("Exec", "No inputs set, nothing to do.");
124 if (! FetchLoaders(fManager->GetInputFolderName(0), runloader, gime) ) return;
125 if (! FetchGlobalPointers(runloader) ) return;
129 if (GetDebug() > 1) Info("Exec", "Event Number is %d.", fManager->GetOutputEventNr());
131 // Loop over files to merge and to digitize
133 for (Int_t inputFile = 0; inputFile < fManager->GetNinputs(); inputFile++)
135 fMask = fManager->GetMask(inputFile);
137 Info("Exec", "Digitising folder %d, with fMask = %d: %s", inputFile, fMask,
138 (const char*)fManager->GetInputFolderName(inputFile));
141 // If this is the first file then we already have the loaders loaded.
142 if (! FetchLoaders(fManager->GetInputFolderName(inputFile), runloader, gime) )
145 // If this is not the first file then it is assumed to be background.
148 if (! InitInputData(gime) ) continue;
149 GenerateTransientDigits();
150 CleanupInputData(gime);
153 Bool_t ok = FetchLoaders(fManager->GetOutputFolderName(), runloader, gime);
154 if (ok) ok = InitOutputData(gime);
155 if (ok) CreateDigits();
156 if (ok) CleanupOutputData(gime);
161 //--------------------------------------------------------------------------
162 void AliMUONDigitizer::AddOrUpdateTransientDigit(AliMUONTransientDigit* mTD)
164 // Checks to see if the transient digit exists in the corresponding fHitMap.
165 // If it does then the digit is updated otherwise it is added.
167 if (ExistTransientDigit(mTD))
169 UpdateTransientDigit(mTD);
170 delete mTD; // The new digit can be deleted because it was not added.
173 AddTransientDigit(mTD);
176 //------------------------------------------------------------------------
177 void AliMUONDigitizer::UpdateTransientDigit(AliMUONTransientDigit* mTD)
179 // Update the transient digit that is already in the fTDList by adding the new
180 // transient digits charges and track lists to the existing one.
183 Info("UpdateTransientDigit", "Updating transient digit 0x%X", (void*)mTD);
184 // Choosing the maping of the cathode plane of the chamber:
185 Int_t iNchCpl= mTD->Chamber() + (mTD->Cathode()-1) * AliMUONConstants::NCh();
186 AliMUONTransientDigit *pdigit =
187 static_cast<AliMUONTransientDigit*>( fHitMap[iNchCpl]->GetHit(mTD->PadX(),mTD->PadY()) );
190 pdigit->AddSignal( mTD->Signal() );
191 pdigit->AddPhysicsSignal( mTD->Physics() );
193 // update list of tracks
194 Int_t ntracks = mTD->GetNTracks();
195 if (ntracks > kMAXTRACKS) // Truncate the number of tracks to kMAXTRACKS if we have to.
199 Warning("UpdateTransientDigit",
200 "TransientDigit returned the number of tracks to be %d, which is bigger than kMAXTRACKS.",
202 Warning("UpdateTransientDigit", "Reseting the number of tracks to be %d.", kMAXTRACKS);
204 ntracks = kMAXTRACKS;
207 for (Int_t i = 0; i < ntracks; i++)
209 pdigit->UpdateTrackList( mTD->GetTrack(i), mTD->GetCharge(i) );
213 //------------------------------------------------------------------------
214 void AliMUONDigitizer::AddTransientDigit(AliMUONTransientDigit* mTD)
216 // Adds the transient digit to the fTDList and sets the appropriate entry
217 // in the fHitMap arrays.
220 Info("AddTransientDigit", "Adding transient digit 0x%X", (void*)mTD);
221 // Choosing the maping of the cathode plane of the chamber:
222 Int_t iNchCpl= mTD->Chamber() + (mTD->Cathode()-1) * AliMUONConstants::NCh();
223 fTDList->AddAtAndExpand(mTD, fTDCounter);
224 fHitMap[iNchCpl]->SetHit( mTD->PadX(), mTD->PadY(), fTDCounter);
228 //------------------------------------------------------------------------
229 Bool_t AliMUONDigitizer::ExistTransientDigit(AliMUONTransientDigit* mTD)
231 // Checks if the transient digit already exists on the corresponding fHitMap.
232 // i.e. is there a transient digit on the same chamber, cathode and pad position
233 // as mTD. If yes then kTRUE is returned else kFASLE is returned.
235 // Choosing the maping of the cathode plane of the chamber:
236 Int_t iNchCpl= mTD->Chamber() + (mTD->Cathode()-1) * AliMUONConstants::NCh();
237 return( fHitMap[iNchCpl]->TestHit(mTD->PadX(), mTD->PadY()) );
240 //-----------------------------------------------------------------------
241 void AliMUONDigitizer::CreateDigits()
243 // Loops over the fTDList for each cathode, gets the correct signal for the
244 // digit and adds the new digit to the output stream.
246 if (GetDebug() > 1) Info("CreateDigits", "Creating digits...");
247 for (Int_t icat = 0; icat < 2; icat++)
250 // Filling Digit List
251 Int_t nentries = fTDList->GetEntriesFast();
252 for (Int_t nent = 0; nent < nentries; nent++)
254 AliMUONTransientDigit* td = (AliMUONTransientDigit*)fTDList->At(nent);
255 if (td == NULL) continue;
257 // Must be the same cathode, otherwise we will fill a mixture
258 // of digits from both cathodes.
259 if (icat != td->Cathode() - 1) continue;
262 Info("CreateDigits", "Creating digit from transient digit 0x%X", (void*)td);
264 Int_t q = GetSignalFrom(td);
265 if (q > 0) AddDigit(td, q);
271 //------------------------------------------------------------------------
272 void AliMUONDigitizer::AddDigit(AliMUONTransientDigit* td, Int_t response_charge)
274 // Prepares the digits, track and charge arrays in preparation for a call to
275 // AddDigit(Int_t, Int_t[kMAXTRACKS], Int_t[kMAXTRACKS], Int_t[6])
276 // This method is called by CreateDigits() whenever a new digit needs to be added
277 // to the output stream trees.
278 // The response_charge value is used as the Signal of the new digit.
279 // The OnWriteTransientDigit method is also called just before the adding the
280 // digit to allow inheriting digitizers to be able to do some specific processing
283 Int_t tracks[kMAXTRACKS];
284 Int_t charges[kMAXTRACKS];
287 digits[0] = td->PadX();
288 digits[1] = td->PadY();
289 digits[2] = td->Cathode() - 1;
290 digits[3] = response_charge;
291 digits[4] = td->Physics();
292 digits[5] = td->Hit();
294 Int_t nptracks = td->GetNTracks();
295 if (nptracks > kMAXTRACKS)
300 "TransientDigit returned the number of tracks to be %d, which is bigger than kMAXTRACKS.",
302 Warning("AddDigit", "Reseting the number of tracks to be %d.", kMAXTRACKS);
304 nptracks = kMAXTRACKS;
307 for (Int_t i = 0; i < nptracks; i++)
309 tracks[i] = td->GetTrack(i);
310 charges[i] = td->GetCharge(i);
313 // Sort list of tracks according to charge
314 SortTracks(tracks,charges,nptracks);
316 if (nptracks < kMAXTRACKS )
318 for (Int_t i = nptracks; i < kMAXTRACKS; i++)
325 if (GetDebug() > 3) Info("AddDigit", "Adding digit with charge %d.", response_charge);
327 OnWriteTransientDigit(td);
328 AddDigit(td->Chamber(), tracks, charges, digits);
331 //------------------------------------------------------------------------
332 void AliMUONDigitizer::OnCreateTransientDigit(AliMUONTransientDigit* /*digit*/, TObject* /*source_object*/)
336 // This is derived by Digitisers that want to trace which digits were made from
340 //------------------------------------------------------------------------
341 void AliMUONDigitizer::OnWriteTransientDigit(AliMUONTransientDigit* /*digit*/)
345 // This is derived by Digitisers that want to trace which digits were made from
349 //------------------------------------------------------------------------
350 Bool_t AliMUONDigitizer::FetchLoaders(const char* foldername, AliRunLoader*& runloader, AliMUONLoader*& muonloader)
352 // Fetches the run loader from the current folder, specified by 'foldername'.
353 // The muon loader is then loaded from the fetched run loader.
354 // kTRUE is returned if no error occurred otherwise kFALSE is returned.
357 Info("FetchLoaders", "Fetching run loader and muon loader from folder: %s", foldername);
359 runloader = AliRunLoader::GetRunLoader(foldername);
360 if (runloader == NULL)
362 Error("FetchLoaders", "RunLoader not found in folder: %s", foldername);
365 muonloader = (AliMUONLoader*) runloader->GetLoader("MUONLoader");
366 if (muonloader == NULL)
368 Error("FetchLoaders", "MUONLoader not found in folder: %s", foldername);
374 //------------------------------------------------------------------------
375 Bool_t AliMUONDigitizer::FetchGlobalPointers(AliRunLoader* runloader)
377 // Fetches the AliRun object into the global gAlice pointer from the specified
378 // run loader. The AliRun object is loaded into memory using the run loader if
379 // not yet loaded. The MUON module object is then loaded from gAlice and
380 // AliMUONData fetched from the MUON module.
381 // kTRUE is returned if no error occurred otherwise kFALSE is returned.
384 Info("FetchGlobalPointers", "Fetching gAlice, MUON module and AliMUONData from runloader 0x%X.",
388 if (runloader->GetAliRun() == NULL) runloader->LoadgAlice();
389 gAlice = runloader->GetAliRun();
392 Error("FetchGlobalPointers", "Could not find the AliRun object in runloader 0x%X.", (void*)runloader);
395 pMUON = (AliMUON*) gAlice->GetDetector("MUON");
398 Error("FetchGlobalPointers", "Could not find the MUON module in runloader 0x%X.", (void*)runloader);
401 muondata = pMUON->GetMUONData();
402 if (muondata == NULL)
404 Error("FetchGlobalPointers", "Could not find AliMUONData object in runloader 0x%X.", (void*)runloader);
410 //------------------------------------------------------------------------
411 void AliMUONDigitizer::ParseOptions(Option_t* options)
413 // Called by the Exec method. ParseOptions should parse the option string given to the Exec method.
415 // The following options are defined:
416 // "debug" - Sets the debug level to 99, which will show all debug messages.
417 // "deb" - Same as "debug", implemented for backward comparability.
419 // If an invalid option is specified it is simply ignored.
421 TString optionString = options;
422 if (optionString.Data() == "debug" ||
423 optionString.Data() == "deb" // maintained for compatability.
426 Info("ParseOptions", "Called with option \"debug\".");
431 //------------------------------------------------------------------------
432 void AliMUONDigitizer::InitArrays()
434 // Creates a new fTDList object.
435 // Also creates an array of 2 * chamber_number AliMUONHitMapA1 objects
436 // in the fHitMaps array. Each one is set to a chamber and cathode
437 // specific segmentation model.
439 // Note: the fTDList and fHitMap arrays must be NULL before calling this method.
441 if (GetDebug() > 1) Info("InitArrays", "Initialising internal arrays.");
442 if (GetDebug() > 3) Info("InitArrays", "Creating transient digits list.");
443 fTDList = new TObjArray;
445 // Array of pointer of the AliMUONHitMapA1:
446 // two HitMaps per chamber, or one HitMap per cahtode plane
447 fHitMap = new AliMUONHitMapA1* [2*AliMUONConstants::NCh()];
449 // Loop over chambers for the definition AliMUONHitMap
450 for (Int_t i = 0; i < AliMUONConstants::NCh(); i++)
452 if (GetDebug() > 3) Info("InitArrays", "Creating hit map for chamber %d, cathode 1.", i+1);
453 AliMUONChamber* chamber = &(pMUON->Chamber(i));
454 AliSegmentation* c1Segmentation = chamber->SegmentationModel(1); // Cathode plane 1
455 fHitMap[i] = new AliMUONHitMapA1(c1Segmentation, fTDList);
456 if (GetDebug() > 3) Info("InitArrays", "Creating hit map for chamber %d, cathode 2.", i+1);
457 AliSegmentation* c2Segmentation = chamber->SegmentationModel(2); // Cathode plane 2
458 fHitMap[i+AliMUONConstants::NCh()] = new AliMUONHitMapA1(c2Segmentation, fTDList);
462 //------------------------------------------------------------------------
463 void AliMUONDigitizer::CleanupArrays()
465 // The arrays fTDList and fHitMap are deleted and the pointers set to NULL.
467 if (GetDebug() > 1) Info("CleanupArrays", "Deleting internal arrays.");
468 for(Int_t i = 0; i < 2*AliMUONConstants::NCh(); i++)
470 if (GetDebug() > 3) Info("CleanupArrays", "Deleting hit map for chamber %d, cathode %d.",
471 i%AliMUONConstants::NCh()+1, i/AliMUONConstants::NCh()+1);
477 if (GetDebug() > 3) Info("CleanupArrays", "Deleting transient digits list.");
483 //------------------------------------------------------------------------
484 void AliMUONDigitizer::SortTracks(Int_t *tracks, Int_t *charges, Int_t ntr)
487 // Sort the list of tracks contributing to a given digit
488 // Only the 3 most significant tracks are actually sorted
491 if (ntr <= 1) return;
494 // Loop over signals, only 3 times
499 Int_t idx[3] = {-2,-2,-2};
500 Int_t jch[3] = {-2,-2,-2};
501 Int_t jtr[3] = {-2,-2,-2};
504 if (ntr < 3) imax = ntr;
507 for(i = 0; i < imax; i++)
512 for(j = 0; j < ntr; j++)
514 if ( (i == 1 && j == idx[i-1]) ||
515 (i == 2 && (j == idx[i-1] || j == idx[i-2]))
519 if(charges[j] > qmax)
529 jch[i] = charges[jmax];
530 jtr[i] = tracks[jmax];
535 for(i = 0; i < 3; i++)