a5b0caf2d33cc38a953453da18fd50b7dd91e255
[u/mrichter/AliRoot.git] / MUON / AliMUONDigitizerV3.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, 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 "AliMUONDigitizerV3.h"
19
20 #include "AliLog.h"
21 #include "AliMUONCalibrationData.h"
22 #include "AliMUONChamber.h"
23 #include "AliMUONConstants.h"
24 #include "AliMUONData.h"
25 #include "AliMUONDigit.h"
26 #include "AliMUONTriggerDecisionV1.h"
27 #include "AliMUONTriggerElectronics.h"
28 #include "AliMUONCalibParam.h"
29 #include "AliMpDEManager.h"
30 #include "AliMpStationType.h"
31 #include "AliRun.h"
32 #include "AliRunDigitizer.h"
33 #include "AliRunLoader.h"
34 #include "Riostream.h"
35 #include "TRandom.h"
36 #include "TString.h"
37
38 ClassImp(AliMUONDigitizerV3)
39
40 //_____________________________________________________________________________
41 AliMUONDigitizerV3::AliMUONDigitizerV3(AliRunDigitizer* manager, 
42                                        ETriggerCodeVersion triggerCodeVersion)
43 : AliDigitizer(manager),
44 fZeroSuppression(6),
45 fSaturation(3000),
46 fIsInitialized(kFALSE),
47 fOutputData(0x0),
48 fCalibrationData(0x0),
49 fTriggerProcessor(0x0),
50 fTriggerCodeVersion(triggerCodeVersion)
51 {
52   AliDebug(1,Form("AliRunDigitizer=%p",fManager));
53 }
54
55 //_____________________________________________________________________________
56 AliMUONDigitizerV3::~AliMUONDigitizerV3()
57 {
58   AliDebug(1,"dtor");
59   delete fOutputData;
60   delete fCalibrationData;
61   delete fTriggerProcessor;
62 }
63
64 //_____________________________________________________________________________
65 void 
66 AliMUONDigitizerV3::ApplyResponseToDigit(AliMUONDigit& digit)
67 {
68   // For trigger digits, simply sets the digit's charge to 0 or 1.
69   //
70   // For tracking digits, starting from an ideal digit's charge, we :
71   //
72   // - add some noise (thus leading to a realistic charge)
73   // - divide by a gain (thus decalibrating the digit)
74   // - add a pedestal (thus decalibrating the digit)
75   // - sets the signal to zero if below ZeroSuppression() level (thus simulating
76   //   zero suppression).
77   //
78   
79   Int_t detElemId = digit.DetElemId();
80   AliMpStationType stationType = AliMpDEManager::GetStationType(detElemId);
81   if ( stationType == kStationTrigger )
82   {
83     if ( digit.Signal() > 0  )
84     {
85       digit.SetSignal(1);
86     }
87     else
88     {
89       digit.SetSignal(0);
90     }
91     return;    
92   }
93   
94   // The following is for tracking digits only.
95   
96   Int_t manuId = digit.ManuId();
97   Int_t manuChannel = digit.ManuChannel();
98   
99   AliMUONCalibParam* pedestal = fCalibrationData->Pedestal(detElemId,manuId,manuChannel);
100   if (!pedestal)
101   {
102     AliFatal(Form("Could not get pedestal for DE=%d manuId=%d manuChannel=%d",
103                   detElemId,manuId,manuChannel));    
104   }
105   Float_t adc_noise = gRandom->Gaus(0.0,pedestal->Sigma());
106   
107   AliMUONCalibParam* gain = fCalibrationData->Gain(detElemId,manuId,manuChannel);
108   if (!gain)
109   {
110     AliFatal(Form("Could not get gain for DE=%d manuId=%d manuChannel=%d",
111                   detElemId,manuId,manuChannel));    
112   }
113   
114   Float_t signal_noise = adc_noise*gain->Mean();
115   
116   Float_t signal = digit.Signal() + signal_noise;
117   Int_t adc;
118   
119   if ( signal > fSaturation )
120   {
121     adc = fSaturation;
122     digit.Saturated(kTRUE);
123   }
124   else
125   {
126     if ( gain->Mean() < 1E-6 )
127     {
128       AliFatal(Form("Got a too small gain %e for DE=%d manuId=%d manuChannel=%d",
129                     gain->Mean(),detElemId,manuId,manuChannel));
130     }
131     adc = TMath::Nint( signal / gain->Mean() + pedestal->Mean() );
132     
133     if ( adc <= pedestal->Mean() + 3.0*pedestal->Sigma() ) 
134     {
135       adc = 0;
136     }
137   }
138   digit.SetPhysicsSignal(TMath::Nint(signal));
139   digit.SetSignal(adc);
140   digit.SetADC(adc);
141 }
142
143 //_____________________________________________________________________________
144 void
145 AliMUONDigitizerV3::ApplyResponse()
146 {
147   for ( Int_t ich = 0; ich < AliMUONConstants::NCh(); ++ich )
148         {
149     TClonesArray* digits = fOutputData->Digits(ich);
150     Int_t n = digits->GetEntriesFast();
151     for ( Int_t i = 0; i < n; ++i )
152     {
153       AliMUONDigit* d = static_cast<AliMUONDigit*>(digits->UncheckedAt(i));
154       ApplyResponseToDigit(*d);
155       if ( d->Signal() <= 0 )
156       {
157         digits->RemoveAt(i);
158       }
159     }
160   }    
161   
162   for ( Int_t ich = 0; ich < AliMUONConstants::NCh(); ++ich )
163         {
164     fOutputData->Digits(ich)->Compress();
165   }
166 }
167
168 //_____________________________________________________________________________
169 void
170 AliMUONDigitizerV3::AddOrUpdateDigit(TClonesArray& array, 
171                                      const AliMUONDigit& digit)
172 {
173   Int_t ix = FindDigitIndex(array,digit);
174   
175   if (ix>=0)
176   {
177     AliMUONDigit* d = static_cast<AliMUONDigit*>(array.UncheckedAt(ix));
178     Bool_t ok = MergeDigits(digit,*d);
179     if (!ok)
180     {
181       AliError("Digits are not mergeable !");
182     }
183     else
184     {
185       new(array[ix]) AliMUONDigit(*d);
186     }
187   }
188   else
189   {
190     ix = array.GetLast() + 1;
191     new(array[ix]) AliMUONDigit(digit);
192   }
193   
194 }
195
196 //_____________________________________________________________________________
197 void
198 AliMUONDigitizerV3::Exec(Option_t*)
199 {
200   AliDebug(1, "Running digitizer.");
201   
202   if ( fManager->GetNinputs() == 0 )
203   {
204     AliWarning("No input set. Nothing to do.");
205     return;
206   }
207   
208   if ( !fIsInitialized )
209   {
210     AliError("Not initialized. Cannot perform the work. Sorry");
211     return;
212   }
213   
214   Int_t nInputFiles = fManager->GetNinputs();
215   
216   if ( fOutputData->TreeD() == 0x0 )
217   {
218     AliDebug(1,"Calling MakeDigitsContainer");
219     fOutputData->GetLoader()->MakeDigitsContainer();
220   }
221   fOutputData->MakeBranch("D,GLT");
222   fOutputData->SetTreeAddress("D,GLT");
223   
224   // Loop over all the input files, and merge the sdigits found in those
225   // files.
226   for ( Int_t iFile = 0; iFile < nInputFiles; ++iFile )
227   {    
228     AliMUONData* inputData = GetDataAccess(fManager->GetInputFolderName(iFile));
229     if (!inputData)
230     {
231       AliFatal(Form("Could not get access to input file #%d",iFile));
232     }
233     AliDebug(1,Form("inputData=%p",inputData));
234     //FIXME: what about the fMask ???
235     inputData->GetLoader()->LoadSDigits("READ");
236     TTree* treeS = inputData->GetLoader()->TreeS();
237     AliDebug(1,Form("TreeS=%p",treeS));
238     inputData->SetTreeAddress("S");
239     inputData->GetSDigits();
240     MergeWithSDigits(*fOutputData,*inputData);
241     inputData->ResetSDigits();
242     inputData->GetLoader()->UnloadSDigits();
243     delete inputData;
244   }
245   
246   // At this point, we do have digit arrays (one per chamber) which contains 
247   // the merging of all the sdigits of the input file(s).
248   // We now massage them to apply the detector response, i.e. this
249   // is here that we do the "digitization" work.
250   
251   ApplyResponse();
252   
253   // 
254   
255   // We generate the global and local trigger decisions.
256   fTriggerProcessor->ExecuteTask();
257   
258   // Fill the output treeD
259   fOutputData->Fill("D,GLT");
260   
261   // Write to the output tree(D).
262   // Please note that as GlobalTrigger, LocalTrigger and Digits are in the same
263   // tree (=TreeD) in different branches, this WriteDigits in fact writes all of 
264   // the 3 branches.
265   fOutputData->GetLoader()->WriteDigits("OVERWRITE");
266   
267   // Finally, we clean up after ourselves.
268   fOutputData->ResetDigits();
269   fOutputData->ResetTrigger();
270   fOutputData->GetLoader()->UnloadDigits();
271 }
272
273 //_____________________________________________________________________________
274 Int_t
275 AliMUONDigitizerV3::FindDigitIndex(TClonesArray& array, const AliMUONDigit& digit)
276 {
277   // FIXME: this is of course not the best implementation you can think of.
278   // Reconsider the use of hit/digit map...
279   Int_t n = array.GetEntriesFast();
280   for ( Int_t i = 0; i < n; ++i )
281   {
282     AliMUONDigit* d = static_cast<AliMUONDigit*>(array.UncheckedAt(i));
283     if ( d->DetElemId() == digit.DetElemId() &&
284          d->PadX() == digit.PadX() &&
285          d->PadY() == digit.PadY() && 
286          d->Cathode() == digit.Cathode() )
287     {
288       return i;
289     }
290   }
291   return -1;
292 }
293
294 //_____________________________________________________________________________
295 AliMUONData* 
296 AliMUONDigitizerV3::GetDataAccess(const TString& folderName)
297 {
298   AliDebug(1,Form("Getting access to folder %s",folderName.Data()));
299   AliRunLoader* runLoader = AliRunLoader::GetRunLoader(folderName);
300   if (!runLoader)
301   {
302     AliError(Form("Could not get RunLoader from folder %s",folderName.Data()));
303     return 0x0;
304   }
305   AliLoader* loader = static_cast<AliLoader*>(runLoader->GetLoader("MUONLoader"));
306   if (!loader)
307   {
308     AliError(Form("Could not get MuonLoader from folder %s",folderName.Data()));
309     return 0x0;
310   }
311   AliMUONData* data = new AliMUONData(loader,"MUON","MUONDataForDigitOutput");
312   AliDebug(1,Form("AliMUONData=%p loader=%p",data,loader));
313   return data;
314 }
315
316 //_____________________________________________________________________________
317 Bool_t
318 AliMUONDigitizerV3::Init()
319 {
320   AliDebug(1,"");
321   
322   if ( fIsInitialized )
323   {
324     AliError("Object already initialized.");
325     return kFALSE;
326   }
327   
328   if (!fManager)
329   {
330     AliError("fManager is null !");
331     return kFALSE;
332   }
333   
334   fOutputData = GetDataAccess(fManager->GetOutputFolderName());
335   if (!fOutputData)
336   {
337     AliError("Can not perform digitization. I'm sorry");
338     return kFALSE;
339   }
340   AliDebug(1,Form("fOutputData=%p",fOutputData));
341   
342   AliRunLoader* runLoader = fOutputData->GetLoader()->GetRunLoader();
343   AliRun* galice = runLoader->GetAliRun();  
344   Int_t runnumber = galice->GetRunNumber();
345   
346   fCalibrationData = new AliMUONCalibrationData(runnumber);
347   
348   switch (fTriggerCodeVersion)
349   {
350     case kTriggerDecision:
351       fTriggerProcessor = new AliMUONTriggerDecisionV1(fOutputData);
352       break;
353     case kTriggerElectronics:
354       fTriggerProcessor = new AliMUONTriggerElectronics(fOutputData);
355       break;
356     default:
357       AliFatal("Unknown trigger processor type");
358       break;
359   }
360   AliDebug(1,Form("Using the following trigger code %s - %s",
361                   fTriggerProcessor->GetName(),fTriggerProcessor->GetTitle()));
362   fIsInitialized = kTRUE;
363   return kTRUE;
364 }
365
366 //_____________________________________________________________________________
367 Bool_t
368 AliMUONDigitizerV3::MergeDigits(const AliMUONDigit& src, AliMUONDigit& srcAndDest)
369 {
370   AliDebug(1,"Merging the following digits:");
371   StdoutToAliDebug(1,src.Print(););
372   StdoutToAliDebug(1,srcAndDest.Print(););
373   
374   Bool_t check = ( src.DetElemId() == srcAndDest.DetElemId() &&
375                    src.PadX() == srcAndDest.PadX() &&
376                    src.PadY() == srcAndDest.PadY() &&
377                    src.Cathode() == srcAndDest.Cathode() );
378   if (!check)
379   {
380     return kFALSE;
381   }
382   
383  
384   srcAndDest.AddSignal(src.Signal());
385   srcAndDest.AddPhysicsSignal(src.Physics());
386   StdoutToAliDebug(1,cout << "result:"; srcAndDest.Print(););
387   return kTRUE;
388 }
389
390 //_____________________________________________________________________________
391 void 
392 AliMUONDigitizerV3::MergeWithSDigits(AliMUONData& outputData, 
393                                      const AliMUONData& inputData)
394 {
395   AliDebug(1,"");
396   
397         for ( Int_t ich = 0; ich < AliMUONConstants::NCh(); ++ich )
398         {
399     TClonesArray* iDigits = inputData.SDigits(ich); 
400     TClonesArray* oDigits = outputData.Digits(ich);
401     if (!iDigits)
402     {
403       AliError(Form("Could not get sdigits for ich=%d",ich));
404       return;
405     }
406     Int_t nSDigits = iDigits->GetEntriesFast();
407     for ( Int_t k = 0; k < nSDigits; ++k )
408                 {
409                         AliMUONDigit* sdigit = static_cast<AliMUONDigit*>(iDigits->UncheckedAt(k));
410       // FIXME: Merging logic should go here.
411       // For testing, only put the digit in the output.
412       if (!sdigit)
413       {
414         AliError(Form("Could not get sdigit for ich=%d and k=%d",ich,k));
415       }
416       else
417       {
418         AddOrUpdateDigit(*oDigits,*sdigit);
419       }
420                 }   
421   }
422 }
423
424 //------------------------------------------------------------------------
425 //void AliMUONDigitizerv2::FillTriggerOutput()
426 //{
427 //  // Derived to fill TreeD and resets the trigger array in fMUONData.
428 //  
429 //      AliDebug(3,"Filling trees with trigger.");
430 //      fMUONData->Fill("GLT");
431 //      fMUONData->ResetTrigger();
432 //}
433 //
434 //------------------------------------------------------------------------
435 //void AliMUONDigitizerv2::CreateTrigger()
436 //{
437 //  fMUONData->MakeBranch("GLT");
438 //  fMUONData->SetTreeAddress("GLT");
439 //  fTrigDec->Digits2Trigger(); 
440 //  FillTriggerOutput();        
441 //  
442 //}
443