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