Intrinsic chamber efficiency calculation performed during reconstruction (Diego)
[u/mrichter/AliRoot.git] / MUON / AliMUONReconstructor.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 /* $Id$ */
16
17 /// \class AliMUONReconstructor
18 ///
19 /// Implementation of AliReconstructor for MUON subsystem.
20 ///
21 /// The behavior of the MUON reconstruction can be changed, besides
22 /// the usual methods found in AliReconstruction (e.g. to disable tracking)
23 /// by using AliReconstruction::SetOption("MUON",options)
24 /// where options should be a space separated string.
25 ///
26 /// Valid options are :
27 ///
28 /// SAVEDIGITS : if you want to save in the TreeD the *calibrated* digits
29 ///     that are used for the clustering
30 ///
31 /// SIMPLEFIT : use the AliMUONClusterFinderSimpleFit clusterizer
32 ///
33 /// AZ : use the AliMUONClusterFinderAZ clusterizer (default)
34 ///
35 /// PRECLUSTER : use only AliMUONPreClusterFinder. Only for debug as
36 /// the produced clusters do not have a position, hence the tracking will not
37 /// work
38 ///
39 /// COG : use AliMUONClusterFinderCOG clusterizer. Not really a production
40 /// option either, as center-of-gravity is generally not a good estimate
41 /// of the cluster position...
42 ///
43 /// NOCLUSTERING : bypass completely the clustering stage
44 ///
45 /// NOSTATUSMAP : disable the computation and usage of the pad status map. Only
46 /// for debug !
47 ///
48 /// NOLOCALRECONSTRUCTION : for debug, to disable local reconstruction (and hence
49 /// "recover" old behavior)
50 ///
51 /// TRIGGERDISABLE : disable the treatment of MUON trigger
52 ///
53 /// \author Laurent Aphecetche, Subatech
54
55 #include "AliMUONReconstructor.h"
56
57 #include "AliCDBManager.h"
58 #include "AliLoader.h"
59 #include "AliLog.h"
60 #include "AliRunLoader.h"
61 #include "AliMUONCalibrationData.h"
62 #include "AliMUONClusterFinderCOG.h"
63 #include "AliMUONClusterFinderMLEM.h"
64 #include "AliMUONClusterFinderSimpleFit.h"
65 #include "AliMUONClusterFinderAZ.h"
66 #include "AliMUONClusterReconstructor.h"
67 #include "AliMUONClusterStoreV1.h"
68 #include "AliMUONConstants.h"
69 #include "AliMUONDigitCalibrator.h"
70 #include "AliMUONDigitMaker.h"
71 #include "AliMUONDigitStoreV1.h"
72 #include "AliMUONGeometryTransformer.h"
73 #include "AliMUONPreClusterFinder.h"
74 #include "AliMUONTracker.h"
75 #include "AliMUONVTrackStore.h"
76 #include "AliMUONTriggerChamberEff.h"
77 #include "AliMUONTriggerCircuit.h"
78 #include "AliMUONTriggerCrateStore.h"
79 #include "AliMUONTriggerStoreV1.h"
80 #include "AliMUONVClusterFinder.h"
81 #include "AliRawReader.h"
82 #include "AliMUONStopwatchGroup.h"
83 #include "AliMUONStopwatchGroupElement.h"
84 #include <Riostream.h>
85 #include <TClonesArray.h>
86 #include <TString.h>
87 #include <TTree.h>
88
89 /// \cond CLASSIMP
90 ClassImp(AliMUONReconstructor)
91 /// \endcond 
92
93 //_____________________________________________________________________________
94 AliMUONReconstructor::AliMUONReconstructor() : 
95 AliReconstructor(),
96 fCrateManager(0x0),
97 fDigitMaker(0x0),
98 fTransformer(new AliMUONGeometryTransformer(kTRUE)),
99 fDigitStore(0x0),
100 fTriggerCircuit(0x0),
101 fCalibrationData(0x0),
102 fDigitCalibrator(0x0),
103 fClusterReconstructor(0x0),
104 fClusterStore(0x0),
105 fTriggerStore(0x0),
106 fTrackStore(0x0),
107 fTrigChamberEff(0x0),
108 fTimers(new AliMUONStopwatchGroup)
109 {
110   /// normal ctor
111   fTransformer->ReadGeometryData("volpath.dat", "geometry.root");
112 }
113
114 //_____________________________________________________________________________
115 AliMUONReconstructor::~AliMUONReconstructor()
116 {
117   /// dtor
118   delete fDigitMaker;
119   delete fDigitStore;
120   delete fTransformer;
121   delete fCrateManager;
122   delete fTriggerCircuit;
123   delete fCalibrationData;
124   delete fDigitCalibrator;
125   delete fClusterReconstructor;
126   delete fClusterStore;
127   delete fTriggerStore;
128   delete fTrackStore;
129   delete fTrigChamberEff;
130   AliInfo("Timers:");
131   fTimers->Print();
132   delete fTimers;
133 }
134
135 //_____________________________________________________________________________
136 void
137 AliMUONReconstructor::Calibrate(AliMUONVDigitStore& digitStore) const
138 {
139   /// Calibrate the digitStore
140   if (!fDigitCalibrator)
141   {
142     CreateCalibrator();
143   }
144   AliMUONStopwatchGroupElement timer(fTimers,"MUON",Form("%s::Calibrate(AliMUONVDigitStore*)",fDigitCalibrator->ClassName()));
145   fDigitCalibrator->Calibrate(digitStore);  
146 }
147
148 //_____________________________________________________________________________
149 void
150 AliMUONReconstructor::Clusterize(const AliMUONVDigitStore& digitStore,
151                                  AliMUONVClusterStore& clusterStore) const
152 {
153   /// Creates clusters from digits.
154
155   TString sopt(GetOption());
156   sopt.ToUpper();
157   if ( sopt.Contains("NOCLUSTERING") ) return;
158   
159   if  (!fClusterReconstructor)
160   {
161     CreateClusterReconstructor();
162   }
163   
164   AliMUONStopwatchGroupElement timer(fTimers,"MUON",Form("%s::Digits2Clusters(const AliMUONVDigitStore&,AliMUONVClusterStore&)",
165                                                      fClusterReconstructor->ClassName()));
166   fClusterReconstructor->Digits2Clusters(digitStore,clusterStore);  
167 }
168
169 //_____________________________________________________________________________
170 AliMUONVClusterStore*
171 AliMUONReconstructor::ClusterStore() const
172 {
173   /// Return (and create if necessary) the cluster container
174   if (!fClusterStore) 
175   {
176     fClusterStore = new AliMUONClusterStoreV1;
177   }
178   return fClusterStore;
179 }
180
181 //_____________________________________________________________________________
182 void
183 AliMUONReconstructor::ConvertDigits(AliRawReader* rawReader, 
184                                     AliMUONVDigitStore* digitStore,
185                                     AliMUONVTriggerStore* triggerStore) const
186 {
187   /// Convert raw data into digit and trigger stores
188   CreateDigitMaker();
189   AliMUONStopwatchGroupElement timer(fTimers,"MUON",Form("%s::Raw2Digits(AliRawReader*,AliMUONVDigitStore*,AliMUONVTriggerStore*)",
190                                                      fDigitMaker->ClassName()));
191   fDigitMaker->Raw2Digits(rawReader,digitStore,triggerStore);
192   Calibrate(*digitStore);
193 }
194
195 //_____________________________________________________________________________
196 void 
197 AliMUONReconstructor::ConvertDigits(AliRawReader* rawReader, TTree* digitsTree) const
198 {
199    /// convert raw data into a digit tree
200
201   Bool_t alone = ( TriggerStore() == 0 );
202   
203   Bool_t ok = DigitStore()->Connect(*digitsTree,alone);
204   if ( TriggerStore() ) 
205   {
206     ok = ok && TriggerStore()->Connect(*digitsTree,kFALSE);
207   }
208   
209   if (!ok)
210   {
211     AliError("Could not make branches on TreeD");
212   }
213   else
214   {
215     ConvertDigits(rawReader,DigitStore(),TriggerStore());
216     digitsTree->Fill();
217     DigitStore()->Clear();
218   }
219 }
220
221 //_____________________________________________________________________________
222 AliMUONTriggerCrateStore*
223 AliMUONReconstructor::CrateManager() const
224 {
225   /// Return (and create if necessary) the trigger crate store
226   if (fCrateManager) return fCrateManager;
227   fCrateManager = new AliMUONTriggerCrateStore;
228   fCrateManager->ReadFromFile();
229   return fCrateManager;
230 }
231
232 //_____________________________________________________________________________
233 void
234 AliMUONReconstructor::CreateDigitMaker() const
235 {
236   /// Create (and create if necessary) the digit maker
237   if (fDigitMaker) return;
238
239   AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::CreateDigitMaker()");
240
241   fDigitMaker = new AliMUONDigitMaker;
242 }
243
244 //_____________________________________________________________________________
245 void 
246 AliMUONReconstructor::CreateTriggerCircuit() const
247 {
248   /// Return (and create if necessary) the trigger circuit object
249   if (fTriggerCircuit) return;
250
251   AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::CreateTriggerCircuit()");
252
253   fTriggerCircuit = new AliMUONTriggerCircuit(fTransformer);
254
255 }
256
257 //_____________________________________________________________________________
258 void
259 AliMUONReconstructor::CreateTriggerChamberEff() const
260 {
261   /// Create (and create if necessary) the trigger chamber efficiency class
262   if (fTrigChamberEff) return;
263
264   AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::CreateTriggerChamberEff()");
265
266   fTrigChamberEff = new AliMUONTriggerChamberEff(fTransformer,fDigitMaker,kTRUE);
267   //fTrigChamberEff->SetDebugLevel(1);
268 }
269
270 //_____________________________________________________________________________
271 AliTracker* 
272 AliMUONReconstructor::CreateTracker(AliRunLoader* runLoader) const
273 {
274   /// Create the MUONTracker object
275   /// The MUONTracker is passed the GetOption(), i.e. our own options
276   
277   CreateTriggerCircuit();
278   CreateDigitMaker();
279   CreateTriggerChamberEff();
280   
281   AliLoader* loader = runLoader->GetDetectorLoader("MUON");
282   if (!loader)
283   {
284     AliError("Cannot get MUONLoader, so cannot create MUONTracker");
285     return 0x0;
286   }
287   AliMUONTracker* tracker = new AliMUONTracker(loader,fDigitMaker,fTransformer,fTriggerCircuit,fTrigChamberEff);
288   tracker->SetOption(GetOption());
289   
290   return tracker;
291 }
292
293 //_____________________________________________________________________________
294 void
295 AliMUONReconstructor::CreateClusterReconstructor() const
296 {
297   /// Create cluster reconstructor, depending on GetOption()
298   
299   AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::CreateClusterReconstructor()");
300
301   AliDebug(1,"");
302   
303   AliMUONVClusterFinder* clusterFinder(0x0);
304   
305   TString opt(GetOption());
306   opt.ToUpper();
307   
308   if ( strstr(opt,"PRECLUSTER") )
309   {
310     clusterFinder = new AliMUONPreClusterFinder;
311   }  
312   else if ( strstr(opt,"COG") )
313   {
314     clusterFinder = new AliMUONClusterFinderCOG;
315   }  
316   else if ( strstr(opt,"SIMPLEFIT") )
317   {
318     clusterFinder = new AliMUONClusterFinderSimpleFit;
319   }
320   else if ( strstr(opt,"MLEM:DRAW") )
321   {
322     clusterFinder = new AliMUONClusterFinderMLEM(kTRUE);
323   }
324   else if ( strstr(opt,"MLEM") )
325   {
326     clusterFinder = new AliMUONClusterFinderMLEM(kFALSE);
327   } 
328   else if ( strstr(opt,"AZ") )
329   {
330     clusterFinder = new AliMUONClusterFinderAZ;
331   }
332   else
333   {
334     clusterFinder = new AliMUONClusterFinderAZ;
335   }
336   
337   if ( clusterFinder ) 
338   {
339     AliInfo(Form("Will use %s for clusterizing",clusterFinder->ClassName()));
340   }
341   
342   fClusterReconstructor = new AliMUONClusterReconstructor(clusterFinder,fTransformer);
343 }
344
345 //_____________________________________________________________________________
346 void
347 AliMUONReconstructor::CreateCalibrator() const
348 {
349   /// Create the calibrator
350   
351   AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::CreateCalibrator()");
352   
353   Int_t runNumber = AliCDBManager::Instance()->GetRun();
354
355   AliInfo("Calibration will occur.");
356   
357   fCalibrationData = new AliMUONCalibrationData(runNumber);
358   if ( !fCalibrationData->IsValid() )
359   {
360     AliError("Could not retrieve calibrations !");
361     delete fCalibrationData;
362     fCalibrationData = 0x0;
363     return;
364   }    
365   
366   // Check that we get all the calibrations we'll need
367   if ( !fCalibrationData->Pedestals() ||
368        !fCalibrationData->Gains() ||
369        !fCalibrationData->HV() )
370   {
371     AliFatal("Could not access all required calibration data");
372   }
373   
374   TString opt(GetOption());
375   opt.ToUpper();
376   Bool_t statusMap(kTRUE);
377   
378   if ( strstr(opt,"NOSTATUSMAP") )
379   {
380     AliWarning("Disconnecting status map : SHOULD BE USED FOR DEBUG ONLY. NOT FOR PRODUCTION !!!");
381     statusMap = kFALSE; 
382   }
383   fDigitCalibrator = new AliMUONDigitCalibrator(*fCalibrationData,statusMap);
384 }
385
386 //_____________________________________________________________________________
387 AliMUONVDigitStore*
388 AliMUONReconstructor::DigitStore() const
389 {
390   /// Return (and create if necessary) the digit container
391   if (!fDigitStore) 
392   {
393     fDigitStore = new AliMUONDigitStoreV1;
394   }
395   return fDigitStore;
396 }
397
398 //_____________________________________________________________________________
399 void
400 AliMUONReconstructor::FillTreeR(AliMUONVTriggerStore* triggerStore,
401                                 AliMUONVClusterStore* clusterStore,
402                                 TTree& clustersTree) const
403 {
404   /// Write the trigger and cluster information into TreeR
405   
406   AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::FillTreeR()");
407
408   AliDebug(1,"");
409   
410   Bool_t ok(kFALSE);
411   if ( triggerStore ) 
412   {
413     Bool_t alone = ( clusterStore ? kFALSE : kTRUE );
414     ok = triggerStore->Connect(clustersTree,alone);
415     if (!ok)
416     {
417       AliError("Could not create triggerStore branches in TreeR");
418     }
419   }
420   
421   if ( clusterStore ) 
422   {
423     Bool_t alone = ( triggerStore ? kFALSE : kTRUE );
424     ok = clusterStore->Connect(clustersTree,alone);
425     if (!ok)
426     {
427       AliError("Could not create triggerStore branches in TreeR");
428     }    
429   }
430   
431   if (ok) // at least one type of branches created successfully
432   {
433     clustersTree.Fill();
434   }
435 }
436
437 //_____________________________________________________________________________
438 Bool_t 
439 AliMUONReconstructor::HasDigitConversion() const
440 {
441   /// We *do* have digit conversion, but we might advertise it only 
442   /// if we want to save the digits.
443   
444   TString opt(GetOption());
445   opt.ToUpper();
446   if ( opt.Contains("SAVEDIGITS" ) && !opt.Contains("NOLOCALRECONSTRUCTION") )
447   {
448     return kTRUE;
449   }
450   else
451   {
452     return kFALSE;
453   }
454 }
455
456 //_____________________________________________________________________________
457 Bool_t 
458 AliMUONReconstructor::HasLocalReconstruction() const
459 {
460   /// Whether or not we have local reconstruction
461   TString opt(GetOption());
462   opt.ToUpper();
463   if ( opt.Contains("NOLOCALRECONSTRUCTION" ) )
464   {
465     return kFALSE;
466   }
467   else
468   {
469     return kTRUE;
470   }
471 }
472
473 //_____________________________________________________________________________
474 void 
475 AliMUONReconstructor::Reconstruct(AliRawReader* rawReader, TTree* clustersTree) const
476 {
477   /// This method is called by AliReconstruction if HasLocalReconstruction()==kTRUE AND
478   /// HasDigitConversion()==kFALSE
479   
480   if ( !clustersTree ) 
481   {
482     AliError("clustersTree is 0x0 !");
483     return;
484   }
485   
486   if ( DigitStore() ) 
487   {
488     ConvertDigits(rawReader,DigitStore(),TriggerStore());
489     Clusterize(*(DigitStore()),*(ClusterStore()));
490   }
491     
492   FillTreeR(TriggerStore(),ClusterStore(),*clustersTree);
493 }
494
495 //_____________________________________________________________________________
496 void 
497 AliMUONReconstructor::Reconstruct(AliRunLoader* runLoader) const
498 {
499   /// Reconstruct simulated data
500   
501   AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::Reconstruct(AliRunLoader*)");
502   
503   AliLoader* loader = runLoader->GetDetectorLoader("MUON");
504   if (!loader) 
505   {
506     AliError("Could not get MUON loader");
507     return;
508   }
509   
510   Int_t nEvents = runLoader->GetNumberOfEvents();
511   
512   for ( Int_t i = 0; i < nEvents; ++i ) 
513   {
514     runLoader->GetEvent(i);
515     
516     loader->LoadRecPoints("update");
517     loader->CleanRecPoints();
518     loader->MakeRecPointsContainer();
519     TTree* clustersTree = loader->TreeR();
520     
521     loader->LoadDigits("read");
522     TTree* digitsTree = loader->TreeD();
523
524     Reconstruct(digitsTree,clustersTree);
525     
526     loader->UnloadDigits();
527     loader->WriteRecPoints("OVERWRITE");
528     loader->UnloadRecPoints();    
529   }
530 }
531
532 //_____________________________________________________________________________
533 void 
534 AliMUONReconstructor::Reconstruct(AliRunLoader* runLoader, AliRawReader* rawReader) const
535 {
536   /// This method is called by AliReconstruction if HasLocalReconstruction()==kFALSE
537   
538   AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::Reconstruct(AliRunLoader*, AliRawReader*)");
539   
540   AliLoader* loader = runLoader->GetDetectorLoader("MUON");
541   if (!loader) 
542   {
543     AliError("Could not get MUON loader");
544     return;
545   }
546
547   Int_t i(0);
548   
549   while (rawReader->NextEvent()) 
550   {
551     runLoader->GetEvent(i++);
552     
553     loader->LoadRecPoints("update");
554     loader->CleanRecPoints();
555     loader->MakeRecPointsContainer();
556     TTree* clustersTree = loader->TreeR();
557     
558     loader->LoadDigits("update");
559     loader->CleanDigits();
560     loader->MakeDigitsContainer();
561     TTree* digitsTree = loader->TreeD();
562     ConvertDigits(rawReader, digitsTree);
563     loader->WriteDigits("OVERWRITE");
564     
565     Reconstruct(digitsTree,clustersTree);
566     
567     loader->UnloadDigits();
568     loader->WriteRecPoints("OVERWRITE");
569     loader->UnloadRecPoints();    
570   }
571 }
572
573 //_____________________________________________________________________________
574 void 
575 AliMUONReconstructor::Reconstruct(TTree* digitsTree, TTree* clustersTree) const
576 {
577   /// This method is called by AliReconstruction if HasLocalReconstruction()==kTRUE
578   /// AND HasDigitConversion()==kTRUE
579   
580   AliDebug(1,"");
581   
582   if (!digitsTree || !clustersTree) 
583   {
584     AliError(Form("Tree is null : digitsTree=%p clustersTree=%p",
585                   digitsTree,clustersTree));
586     return;
587   }
588
589   if (!fDigitStore)
590   {
591     fDigitStore = AliMUONVDigitStore::Create(*digitsTree);
592     if (!fDigitStore)
593     {
594       AliError(Form("Could not get DigitStore from %s",digitsTree->GetName()));
595     }
596     else
597     {
598       AliInfo(Form("Created %s from %s",fDigitStore->ClassName(),digitsTree->GetName()));
599     }
600   }
601   if (!fTriggerStore)
602   {
603     fTriggerStore = AliMUONVTriggerStore::Create(*digitsTree);
604     if (!fTriggerStore)
605     {
606       AliError(Form("Could not get TriggerStore from %s",digitsTree->GetName()));
607     }
608     else
609     {
610       AliInfo(Form("Created %s from %s",fTriggerStore->ClassName(),digitsTree->GetName()));
611     }
612   }
613   
614   if (!fTriggerStore && !fDigitStore)
615   {
616     AliError("No store at all. Nothing to do.");
617     return;
618   }
619   
620   // insure we start with empty stores
621   if ( fDigitStore ) 
622   {
623     fDigitStore->Clear(); 
624     Bool_t alone = ( fTriggerStore ? kFALSE : kTRUE );
625     Bool_t ok = fDigitStore->Connect(*digitsTree,alone);
626     if (!ok)
627     {
628       AliError("Could not connect digitStore to digitsTree");
629       return;
630     }
631   }
632   if ( fTriggerStore ) 
633   {
634     fTriggerStore->Clear();
635     Bool_t alone = ( fDigitStore ? kFALSE : kTRUE );
636     Bool_t ok = fTriggerStore->Connect(*digitsTree,alone);
637     if (!ok)
638     {
639       AliError("Could not connect triggerStore to digitsTree");
640       return;
641     }
642   }
643   
644   digitsTree->GetEvent(0);
645   
646   if ( fDigitStore ) 
647   {
648     Clusterize(*fDigitStore,*(ClusterStore()));
649   }
650     
651   FillTreeR(fTriggerStore,ClusterStore(),*clustersTree);
652 }
653
654 //_____________________________________________________________________________
655 AliMUONVTriggerStore*
656 AliMUONReconstructor::TriggerStore() const
657 {
658   /// Return (and create if necessary and allowed) the trigger container
659   TString sopt(GetOption());
660   sopt.ToUpper();
661   
662   if (sopt.Contains("TRIGGERDISABLE"))
663   {
664     delete fTriggerStore;
665     fTriggerStore = 0x0;
666   }
667   else
668   {
669     if (!fTriggerStore)
670     {
671       fTriggerStore = new AliMUONTriggerStoreV1;
672     }
673   }
674   return fTriggerStore;
675 }