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