]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/MUONrec/AliMUONReconstructor.cxx
Resolving all symbols in the library
[u/mrichter/AliRoot.git] / MUON / MUONrec / 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 clustering mode and the associated parameters can be changed through the
23 /// AliMUONRecoParam object set in the reconstruction macro or read from the CDB
24 /// (see methods in AliMUONRecoParam.h file for details)
25 ///
26 /// Valid modes are :
27 ///
28 /// SIMPLEFIT : use the AliMUONClusterFinderSimpleFit clusterizer
29 ///
30 /// SIMPLEFITV3 : SIMPLEFIT with preclustering=PRECLUSTERV3
31 ///
32 /// MLEM : use AliMUONClusterFinderMLEM and AliMUONPreClusterFinder for preclustering (default)
33 /// MLEMV2 : MLEM with preclustering=PRECLUSTERV2
34 /// MLEMV3 : MLEM with preclustering=PRECLUSTERV3
35 ///
36 /// PRECLUSTER : use only AliMUONPreClusterFinder. Only for debug as
37 /// the produced clusters do not have a position, hence the tracking will not
38 /// work
39 /// PRECLUSTERV2 : another version of the preclustering
40 /// PRECLUSTERV3 : yet another version of the preclustering
41 ///
42 /// COG : use AliMUONClusterFinderCOG clusterizer. Not really a production
43 /// option either, as center-of-gravity is generally not a good estimate
44 /// of the cluster position...
45 ///
46 /// PEAKCOG : COG cluster finder around local maxima
47 /// PEAKFIT : fit around local maxima with up to 3 peaks, COG otherwise
48 ///
49 /// NOCLUSTERING : bypass completely the clustering stage
50 ///
51 /// ------
52 ///
53 /// The behavior of the MUON reconstruction can also be changed, besides
54 /// the usual methods found in AliReconstruction (e.g. to disable tracking)
55 /// by using AliReconstruction::SetOption("MUON",options)
56 /// where options should be a space separated string.
57 ///
58 /// Valid options are :
59 ///
60 /// SAVEDIGITS : if you want to save in the TreeD the *calibrated* digits
61 ///     that are used for the clustering
62 ///
63 /// DIGITSTOREV1 : use the V1 implementation of the digitstore 
64 /// DIGITSTOREV2R : use the V2R implementation of the digitstore 
65 ///
66 /// NOLOCALRECONSTRUCTION : for debug, to disable local reconstruction (and hence
67 /// "recover" old behavior)
68 ///
69 /// TRIGGERDISABLE : disable the treatment of MUON trigger
70 ///
71 /// ENABLEERRORLOGGING : enable error logging (this activates also warnings in RawStreamTracker)
72 ///
73 /// \author Laurent Aphecetche, Subatech
74 //-----------------------------------------------------------------------------
75
76 #include "AliMUONReconstructor.h"
77
78 #include "AliMUONCalibrationData.h"
79 #include "AliMUONClusterFinderCOG.h"
80 #include "AliMUONClusterFinderMLEM.h"
81 #include "AliMUONClusterFinderSimpleFit.h"
82 #include "AliMUONClusterFinderPeakCOG.h"
83 #include "AliMUONClusterFinderPeakFit.h"
84 #include "AliMUONClusterStoreV1.h"
85 #include "AliMUONClusterStoreV2.h"
86 #include "AliMUONConstants.h"
87 #include "AliMUONDigitCalibrator.h"
88 #include "AliMUONDigitMaker.h"
89 #include "AliMUONDigitStoreV1.h"
90 #include "AliMUONDigitStoreV2R.h"
91 #include "AliMUONGeometryTransformer.h"
92 #include "AliMUONPadStatusMaker.h"
93 #include "AliMUONPreClusterFinder.h"
94 #include "AliMUONPreClusterFinderV2.h"
95 #include "AliMUONPreClusterFinderV3.h"
96 #include "AliMUONSimpleClusterServer.h"
97 #include "AliMUONTracker.h"
98 #include "AliMUONTriggerCircuit.h"
99 #include "AliMUONTriggerStoreV1.h"
100 #include "AliMUONVClusterFinder.h"
101 #include "AliMUONVClusterServer.h"
102 #include "AliMUONVTrackStore.h"
103 #include "AliMUONTriggerElectronics.h"
104 #include "AliMUONTriggerUtilities.h"
105
106 #include "AliMpArea.h"
107 #include "AliMpCDB.h"
108 #include "AliMpConstants.h"
109 #include "AliMpDDLStore.h"
110 #include "AliMpSegmentation.h"
111
112 #include "AliRawReader.h"
113 #include "AliCDBManager.h"
114 #include "AliCodeTimer.h"
115 #include "AliLog.h"
116 #include "AliRunInfo.h"
117
118 #include <Riostream.h>
119 #include <TObjArray.h>
120 #include <TClonesArray.h>
121 #include <TString.h>
122 #include <TTree.h>
123
124 /// \cond CLASSIMP
125 ClassImp(AliMUONReconstructor)
126 /// \endcond 
127
128 //_____________________________________________________________________________
129 AliMUONReconstructor::AliMUONReconstructor() : 
130 AliReconstructor(),
131 fDigitMaker(0x0),
132 fTransformer(new AliMUONGeometryTransformer()),
133 fDigitStore(0x0),
134 fTriggerCircuit(0x0),
135 fCalibrationData(0x0),
136 fDigitCalibrator(0x0),
137 fTriggerStore(0x0),
138 fTrackStore(0x0),
139 fClusterStore(0x0),
140 fTriggerProcessor(0x0),
141 fTriggerUtilities(0x0),
142 fClusterServers(),
143 fTrackers(),
144 fShouldCalibrate(kTRUE)
145 {
146   /// normal ctor
147
148   AliDebug(1,"");
149   
150   // Unload mapping objects
151   // if they have been loaded from the obsolete OCDB mapping objects
152
153   if ( AliMpDDLStore::Instance(false) ) {
154     AliCDBManager::Instance()->UnloadFromCache("MUON/Calib/DDLStore");
155     delete AliMpDDLStore::Instance();
156   }  
157
158   if ( AliMpSegmentation::Instance(false) ) { 
159     AliCDBManager::Instance()->UnloadFromCache("MUON/Calib/Mapping");
160     delete AliMpSegmentation::Instance();
161   }  
162
163   // Load mapping
164   if ( ! AliMpCDB::LoadDDLStore() ) {
165     AliFatal("Could not access mapping from OCDB !");
166   }
167   
168   // Load geometry data
169   fTransformer->LoadGeometryData();
170  
171   fClusterServers.SetOwner(kTRUE);
172   fTrackers.SetOwner(kTRUE);
173 }
174
175 //_____________________________________________________________________________
176 AliMUONReconstructor::~AliMUONReconstructor()
177 {
178   /// dtor
179
180   AliDebug(1,"");
181
182   delete fDigitCalibrator;
183
184   delete fDigitMaker;
185   delete fDigitStore;
186   delete fTransformer;
187   delete fTriggerCircuit;
188   delete fTriggerStore;
189   delete fTrackStore;
190   delete fClusterStore;
191   delete fTriggerProcessor;
192   delete fTriggerUtilities;
193
194   delete AliMpSegmentation::Instance(false);
195   delete AliMpDDLStore::Instance(false);  
196
197   delete fCalibrationData;  
198 }
199
200 //_____________________________________________________________________________
201 void
202 AliMUONReconstructor::Calibrate(AliMUONVDigitStore& digitStore) const
203 {
204   /// Calibrate the digitStore
205   if (!fDigitCalibrator)
206   {
207     CreateCalibrator();
208   }
209     
210   if ( fShouldCalibrate )
211   {
212     AliCodeTimerAuto(Form("%s::Calibrate(AliMUONVDigitStore*)",fDigitCalibrator->ClassName()),0)
213     fDigitCalibrator->Calibrate(digitStore);
214   }
215 }
216
217 //_____________________________________________________________________________
218 void
219 AliMUONReconstructor::ConvertDigits(AliRawReader* rawReader, 
220                                     AliMUONVDigitStore* digitStore,
221                                     AliMUONVTriggerStore* triggerStore) const
222 {
223   /// Convert raw data into digit and trigger stores
224   CreateDigitMaker();
225
226   // Skip reconstruction if event is Calibration
227   if ( GetRecoParam()->GetEventSpecie() == AliRecoParam::kCalib ) {
228     digitStore->Clear(); // Remove possible digits from previous event
229     triggerStore->Clear(); // Remove possible triggers from previous event
230     AliInfo("Calibration event: do not convert digits");
231     return;
232   }
233   
234   AliCodeTimerStart(Form("%s::Raw2Digits(AliRawReader*,AliMUONVDigitStore*,AliMUONVTriggerStore*)",
235                     fDigitMaker->ClassName()))
236   fDigitMaker->Raw2Digits(rawReader,digitStore,triggerStore);
237   AliCodeTimerStop(Form("%s::Raw2Digits(AliRawReader*,AliMUONVDigitStore*,AliMUONVTriggerStore*)",
238                          fDigitMaker->ClassName()))
239   Calibrate(*digitStore);
240 }
241
242 //_____________________________________________________________________________
243 void 
244 AliMUONReconstructor::ConvertDigits(AliRawReader* rawReader, TTree* digitsTree) const
245 {
246    /// convert raw data into a digit tree
247   AliCodeTimerAuto("",0)
248
249   Bool_t alone = ( TriggerStore() == 0 );
250   
251   Bool_t ok = DigitStore()->Connect(*digitsTree,alone);
252   if ( TriggerStore() ) 
253   {
254     ok = ok && TriggerStore()->Connect(*digitsTree,kFALSE);
255   }
256   
257   if (!ok)
258   {
259     AliError("Could not make branches on TreeD");
260   }
261   else
262   {
263     ConvertDigits(rawReader,DigitStore(),TriggerStore());
264     AliCodeTimerStart("Fill digits")
265     digitsTree->Fill();
266     AliCodeTimerStop("Fill digits")
267     DigitStore()->Clear();
268   }
269 }
270
271 //_____________________________________________________________________________
272 void
273 AliMUONReconstructor::CreateDigitMaker() const
274 {
275   /// Create (and create if necessary) the digit maker
276   if (fDigitMaker) return;
277
278   AliCodeTimerAuto("",0)
279
280   TString option = GetOption();
281   
282   Bool_t enableErrorLogging = kFALSE;
283
284   if (option.Contains("ENABLEERRORLOGGING"))
285   {
286     enableErrorLogging = kTRUE;
287   }
288
289   fDigitMaker = new AliMUONDigitMaker(enableErrorLogging);
290   option.ToUpper();
291
292   // Always make trigger digits
293   // (needed when calculating trigger chamber efficiency)
294   fDigitMaker->SetMakeTriggerDigits(kTRUE);
295
296   if ( GetRecoParam()->TryRecover() )
297   {
298     fDigitMaker->SetTryRecover(kTRUE);
299   }
300   else
301   {
302     fDigitMaker->SetTryRecover(kFALSE);    
303   }
304 }
305
306 //_____________________________________________________________________________
307 void 
308 AliMUONReconstructor::CreateTriggerCircuit() const
309 {
310   /// Return (and create if necessary) the trigger circuit object
311   if (fTriggerCircuit) return;
312
313   AliCodeTimerAuto("",0)
314
315   fTriggerCircuit = new AliMUONTriggerCircuit(fTransformer);
316
317 }
318
319 //_____________________________________________________________________________
320 void 
321 AliMUONReconstructor::CreateTriggerUtilities() const
322 {
323   /// Return (and create if necessary) the trigger utilities object
324   if ( fTriggerUtilities ) return;
325   
326   AliCodeTimerAuto("",0)
327   
328   if ( ! fCalibrationData ) CreateCalibrationData();
329   
330   fTriggerUtilities = new AliMUONTriggerUtilities(fCalibrationData);
331 }
332
333 //_____________________________________________________________________________
334 AliTracker* 
335 AliMUONReconstructor::CreateTracker() const
336 {
337   /// Create the MUONTracker object
338   
339   CreateTriggerCircuit();
340   CreateTriggerUtilities();
341   
342   const AliMUONRecoParam* rp = GetRecoParam();
343   
344   Int_t es = rp->GetEventSpecie();
345   
346   AliTracker* tracker = static_cast<AliTracker*>(fTrackers.At(es));
347   
348   if (!tracker ) 
349   {
350     if ( ! rp->CombineClusterTrackReco() )
351     {
352       tracker = new AliMUONTracker(rp,
353                                    0x0,
354                                    *DigitStore(),
355                                    fTransformer,
356                                    fTriggerCircuit,
357                                    fTriggerUtilities);
358
359       AliInfo(Form("Created tracker %p for recoparam of type %s es=%d",
360                    tracker,
361                    AliRecoParam::GetEventSpecieName(AliRecoParam::Convert(rp->GetEventSpecie())),es));
362     }
363     else
364     {
365       
366       tracker = new AliMUONTracker(rp,
367                                    CreateClusterServer(*rp),
368                                    *DigitStore(),
369                                    fTransformer,
370                                    fTriggerCircuit,
371                                    fTriggerUtilities);
372
373       AliInfo(Form("Created (combined) tracker %p for recoparam of type %s es=%d",
374                    tracker,
375                    AliRecoParam::GetEventSpecieName(AliRecoParam::Convert(rp->GetEventSpecie())),es));      
376     }
377     
378     fTrackers.AddAtAndExpand(tracker,es);
379   }
380   
381   
382   return tracker;
383 }
384
385 //_____________________________________________________________________________
386 AliMUONVClusterFinder*
387 AliMUONReconstructor::CreateClusterFinder(const char* clusterFinderType)
388 {
389   /// Create a given cluster finder instance
390   
391   AliCodeTimerAutoGeneral("",0)
392
393   AliMUONVClusterFinder* clusterFinder(0x0);
394   
395   TString opt(clusterFinderType);
396   opt.ToUpper();
397   
398   if ( strstr(opt,"PRECLUSTERV2") )
399   {
400     clusterFinder = new AliMUONPreClusterFinderV2;
401   }    
402   else if ( strstr(opt,"PRECLUSTERV3") )
403   {
404     clusterFinder = new AliMUONPreClusterFinderV3;
405   }  
406   else if ( strstr(opt,"PRECLUSTER") )
407   {
408     clusterFinder = new AliMUONPreClusterFinder;
409   }  
410   else if ( strstr(opt,"PEAKCOG") )
411   {
412     clusterFinder = new AliMUONClusterFinderPeakCOG(kFALSE,new AliMUONPreClusterFinder);
413   }
414   else if ( strstr(opt,"PEAKFIT") )
415   {
416     clusterFinder = new AliMUONClusterFinderPeakFit(kFALSE,new AliMUONPreClusterFinder);
417   }
418   else if ( strstr(opt,"COG") )
419   {
420     clusterFinder = new AliMUONClusterFinderCOG(new AliMUONPreClusterFinder);
421   }  
422   else if ( strstr(opt,"SIMPLEFITV3") )
423   {
424     clusterFinder = new AliMUONClusterFinderSimpleFit(new AliMUONClusterFinderCOG(new AliMUONPreClusterFinderV3));
425   }
426   else if ( strstr(opt,"SIMPLEFIT") )
427   {
428     clusterFinder = new AliMUONClusterFinderSimpleFit(new AliMUONClusterFinderCOG(new AliMUONPreClusterFinder));
429   }
430   else if ( strstr(opt,"MLEM:DRAW") )
431   {
432     clusterFinder = new AliMUONClusterFinderMLEM(kTRUE,new AliMUONPreClusterFinder);
433   }
434   else if ( strstr(opt,"MLEMV3") )
435   {
436     clusterFinder = new AliMUONClusterFinderMLEM(kFALSE,new AliMUONPreClusterFinderV3);
437   } 
438   else if ( strstr(opt,"MLEMV2") )
439   {
440     clusterFinder = new AliMUONClusterFinderMLEM(kFALSE,new AliMUONPreClusterFinderV2);
441   } 
442   else if ( strstr(opt,"MLEM") )
443   {
444     clusterFinder = new AliMUONClusterFinderMLEM(kFALSE,new AliMUONPreClusterFinder);
445   } 
446   else
447   {
448     AliErrorClass(Form("clustering mode \"%s\" does not exist",opt.Data()));
449     return 0x0;
450   }
451   
452   return clusterFinder;
453 }
454
455 //_____________________________________________________________________________
456 AliMUONVClusterServer*
457 AliMUONReconstructor::CreateClusterServer(const AliMUONRecoParam& rp) const
458 {
459   /// Create cluster server
460   
461   AliCodeTimerAuto("",0);
462   
463   AliMUONVClusterServer* clusterServer = static_cast<AliMUONVClusterServer*>(fClusterServers.At(rp.GetEventSpecie()));
464   
465   if (!clusterServer )
466   {
467     AliMUONVClusterFinder* clusterFinder = CreateClusterFinder(rp.GetClusteringMode());
468     
469     if ( !clusterFinder ) return 0x0;
470     
471     clusterServer = new AliMUONSimpleClusterServer(clusterFinder,*fTransformer);
472
473     AliInfo(Form("Created AliMUONSimpleClusterServer (%p) for specie %d with clustering = %s (following requesting clustering mode %s)",
474                  clusterServer,rp.GetEventSpecie(),clusterFinder->ClassName(),rp.GetClusteringMode()));
475     
476     fClusterServers.AddAtAndExpand(clusterServer,rp.GetEventSpecie());
477   }
478   
479   return clusterServer;
480 }
481
482 //_____________________________________________________________________________
483 void
484 AliMUONReconstructor::CreateCalibrationData() const
485 {
486   /// Create the calibrator
487   
488   AliCodeTimerAuto("",0);
489   
490   Int_t runNumber = AliCDBManager::Instance()->GetRun();
491
492   fCalibrationData = new AliMUONCalibrationData(runNumber);
493   if ( !fCalibrationData->IsValid() )
494   {
495     AliError("Could not retrieve calibrations !");
496     delete fCalibrationData;
497     fCalibrationData = 0x0;
498     return;
499   }    
500   
501   // It is now time to check whether we have everything to proceed.
502   // What we need depends on whether both tracker and trigger
503   // are in the readout chain, and what specific "bad channel policy"
504   // we use
505   
506   Bool_t kTracker(kFALSE);
507   Bool_t kTrigger(kFALSE);
508   
509   const AliRunInfo* runInfo = GetRunInfo();
510   if (!runInfo)
511   {
512     AliError("Could not get runinfo ?");
513   }
514   else
515   {
516     TString detectors(runInfo->GetActiveDetectors());
517     if (detectors.Contains("MUONTRK")) kTracker=kTRUE;
518     if (detectors.Contains("MUONTRG")) kTrigger=kTRUE;
519   }
520    
521   AliInfo(Form("Run with MUON TRIGGER : %s and MUON TRACKER : %s",
522                kTrigger ? "YES":"NO" , 
523                kTracker ? "YES":"NO"));
524   
525   if ( kTracker ) 
526   {
527     // Check that we get all the calibrations we'll need
528     if ( !fCalibrationData->Pedestals() ||
529         !fCalibrationData->Gains() )
530     {
531       AliFatal(Form("Could not access all required calibration data (PED %p GAIN %p)",
532                     fCalibrationData->Pedestals(),fCalibrationData->Gains()));      
533     }
534     
535     if ( !fCalibrationData->HV() ) 
536     {
537       // Special treatment of HV. We only break if the values
538       // are not there *AND* we cut on them.
539       UInt_t mask = GetRecoParam()->PadGoodnessMask();
540       TString smask(AliMUONPadStatusMaker::AsCondition(mask));
541       if ( smask.Contains("HV") )
542       {
543         AliFatal("Could not access all required calibration data (HV)");      
544       }
545     } 
546   }
547 }
548
549 //_____________________________________________________________________________
550 void
551 AliMUONReconstructor::CreateCalibrator() const
552 {
553   /// Create the calibrator
554
555   AliCodeTimerAuto("",0);
556
557   if ( ! fCalibrationData )
558     CreateCalibrationData();
559
560   AliInfo("Calibration will occur.");
561
562   TString opt(GetOption());
563   opt.ToUpper();
564   
565   if ( strstr(opt,"NOSTATUSMAP") )
566   {
567     AliWarning("NOSTATUSMAP is obsolete");
568   }
569
570   Bool_t kTracker(kFALSE);
571     
572   const AliRunInfo* runInfo = GetRunInfo();
573   if (!runInfo)
574   {
575     AliError("Could not get runinfo ?");
576   }
577   else
578   {
579     TString detectors(runInfo->GetActiveDetectors());
580     if (detectors.Contains("MUONTRK")) kTracker=kTRUE;
581   }
582     
583   if ( kTracker )
584   {
585     fDigitCalibrator = new AliMUONDigitCalibrator(*fCalibrationData,GetRecoParam());
586   }
587   else
588   {
589     AliWarning("Apparently running without MCH so will not instantiante the DigitCalibrator nor read MCH OCDB objects...");
590     fShouldCalibrate=kFALSE;
591   }
592 }
593
594 //_____________________________________________________________________________
595 void
596 AliMUONReconstructor::ResponseRemovingChambers(AliMUONVTriggerStore* triggerStore) const
597 {
598   /// Update trigger information with informatins obtained after
599   /// re-calculation of trigger response
600   AliCodeTimerAuto("",0);
601
602   if ( ! fCalibrationData )
603     CreateCalibrationData();
604
605   if ( ! fTriggerProcessor )
606     fTriggerProcessor = new AliMUONTriggerElectronics(fCalibrationData);
607
608   fTriggerProcessor->ResponseRemovingChambers(*triggerStore);
609 }
610
611 //_____________________________________________________________________________
612 AliMUONVDigitStore*
613 AliMUONReconstructor::DigitStore() const
614 {
615   /// Return (and create if necessary) the digit container
616   if (!fDigitStore) 
617   {
618     TString sopt(GetOption());
619     sopt.ToUpper();
620     
621     AliInfo(Form("Options=%s",sopt.Data()));
622     
623     if ( sopt.Contains("DIGITSTOREV1") )
624     {
625       fDigitStore = AliMUONVDigitStore::Create("AliMUONDigitStoreV1");
626     }
627     else if ( sopt.Contains("DIGITSTOREV2R") ) 
628     {
629       fDigitStore = AliMUONVDigitStore::Create("AliMUONDigitStoreV2R");
630     }
631     else if ( sopt.Contains("DIGITSTOREV2S") ) 
632     {
633       fDigitStore = AliMUONVDigitStore::Create("AliMUONDigitStoreV2S");
634     }
635     
636     if (!fDigitStore) fDigitStore = AliMUONVDigitStore::Create("AliMUONDigitStoreV2R");
637     
638     AliInfo(Form("Will use %s to store digits during reconstruction",fDigitStore->ClassName()));
639   }
640   return fDigitStore;
641 }
642
643 //_____________________________________________________________________________
644 void
645 AliMUONReconstructor::FillTreeR(AliMUONVTriggerStore* triggerStore,
646                                 TTree& clustersTree) const
647 {
648   /// Write the trigger and cluster information into TreeR
649
650   AliCodeTimerAuto("",0)
651
652   Bool_t ok(kFALSE);
653   Bool_t alone(kTRUE); // is trigger the only info in TreeR ?
654   
655    const AliMUONRecoParam* rp = GetRecoParam();
656   
657   if ( ! rp->CombineClusterTrackReco() )
658   {
659     alone = kFALSE; // we'll get both tracker and trigger information in TreeR
660   }
661   
662   if ( triggerStore ) 
663   {
664     ResponseRemovingChambers(triggerStore);
665     ok = triggerStore->Connect(clustersTree,alone);
666     if (!ok)
667     {
668       AliError("Could not create triggerStore branches in TreeR");
669     }
670   }
671
672   if ( !alone )
673   {
674     if (!fClusterStore)
675     {
676       fClusterStore = new AliMUONClusterStoreV2;
677     }
678     
679     AliMUONVClusterServer* clusterServer = CreateClusterServer(*rp);
680     
681     TIter next(DigitStore()->CreateIterator());
682     clusterServer->UseDigits(next,DigitStore());
683
684     AliMpArea area;
685     
686     AliDebug(1,Form("Doing full clusterization in local reconstruction using %s ",clusterServer->ClassName()));
687     
688     for ( Int_t i = 0; i < AliMpConstants::NofTrackingChambers(); ++i ) 
689     {
690       if (rp->UseChamber(i))
691       {
692         if ( ( i == 6 || i == 7 )  && rp->BypassSt4() ) continue;
693         if ( ( i == 8 || i == 9 )  && rp->BypassSt5() ) continue;
694         
695         clusterServer->Clusterize(i,*fClusterStore,area,rp);
696       }
697     }
698     
699     Bool_t cok = fClusterStore->Connect(clustersTree,alone);
700     
701     if (!cok) AliError("Could not connect clusterStore to clusterTree");
702     
703     AliDebug(1,Form("Number of clusters found = %d",fClusterStore->GetSize()));
704     
705     StdoutToAliDebug(1,fClusterStore->Print());
706   }
707          
708   if (ok) // at least one type of branches created successfully
709   {
710     clustersTree.Fill();
711   }
712   
713   if (fClusterStore) fClusterStore->Clear();
714 }
715
716 //_____________________________________________________________________________
717 const AliMUONRecoParam* AliMUONReconstructor::GetRecoParam()
718
719   /// Get the recoparam from reconstruction
720   return dynamic_cast<const AliMUONRecoParam*>(AliReconstructor::GetRecoParam(AliReconstruction::GetDetIndex("MUON"))); 
721 }
722
723
724 //_____________________________________________________________________________
725 Bool_t 
726 AliMUONReconstructor::HasDigitConversion() const
727 {
728   /// We *do* have digit conversion, but we might advertise it only 
729   /// if we want to save the digits.
730   
731   TString opt(GetOption());
732   opt.ToUpper();
733   if ( opt.Contains("SAVEDIGITS" ) && !opt.Contains("NOLOCALRECONSTRUCTION") )
734   {
735     return kTRUE;
736   }
737   else
738   {
739     return kFALSE;
740   }
741 }
742
743 //_____________________________________________________________________________
744 void 
745 AliMUONReconstructor::Reconstruct(AliRawReader* rawReader, TTree* clustersTree) const
746 {
747   /// This method is called by AliReconstruction if HasLocalReconstruction()==kTRUE AND
748   /// HasDigitConversion()==kFALSE
749   
750   if ( !clustersTree ) 
751   {
752     AliError("clustersTree is 0x0 !");
753     return;
754   }
755   
756   ConvertDigits(rawReader,DigitStore(),TriggerStore());
757
758   FillTreeR(TriggerStore(),*clustersTree);
759 }
760
761 //_____________________________________________________________________________
762 void 
763 AliMUONReconstructor::Reconstruct(TTree* digitsTree, TTree* clustersTree) const
764 {
765   /// This method is called by AliReconstruction if HasLocalReconstruction()==kTRUE
766   /// AND HasDigitConversion()==kTRUE
767   
768   AliCodeTimerAuto("",0)
769   
770   AliDebug(1,"");
771   
772   if (!digitsTree || !clustersTree) 
773   {
774     AliError(Form("Tree is null : digitsTree=%p clustersTree=%p",
775                   digitsTree,clustersTree));
776     return;
777   }
778
779   if (!fDigitStore)
780   {
781     fDigitStore = AliMUONVDigitStore::Create(*digitsTree);
782     if (!fDigitStore)
783     {
784       AliError(Form("Could not get DigitStore from %s",digitsTree->GetName()));
785     }
786     else
787     {
788       AliInfo(Form("Created %s from %s",fDigitStore->ClassName(),digitsTree->GetName()));
789     }
790   }
791   if (!fTriggerStore)
792   {
793     fTriggerStore = AliMUONVTriggerStore::Create(*digitsTree);
794     if (!fTriggerStore)
795     {
796       AliError(Form("Could not get TriggerStore from %s",digitsTree->GetName()));
797     }
798     else
799     {
800       AliInfo(Form("Created %s from %s",fTriggerStore->ClassName(),digitsTree->GetName()));
801     }
802   }
803   
804   if (!fTriggerStore && !fDigitStore)
805   {
806     AliError("No store at all. Nothing to do.");
807     return;
808   }
809   
810   // insure we start with empty stores
811   if ( fDigitStore ) 
812   {
813     fDigitStore->Clear(); 
814     Bool_t alone = ( fTriggerStore ? kFALSE : kTRUE );
815     Bool_t ok = fDigitStore->Connect(*digitsTree,alone);
816     if (!ok)
817     {
818       AliError("Could not connect digitStore to digitsTree");
819       return;
820     }
821   }
822   if ( fTriggerStore ) 
823   {
824     fTriggerStore->Clear();
825     Bool_t alone = ( fDigitStore ? kFALSE : kTRUE );
826     Bool_t ok = fTriggerStore->Connect(*digitsTree,alone);
827     if (!ok)
828     {
829       AliError("Could not connect triggerStore to digitsTree");
830       return;
831     }
832   }
833   
834   digitsTree->GetEvent(0);
835   
836   if ( fDigitStore ) 
837   {
838     // Insure we got calibrated digits (if we reconstruct from pure simulated,
839     // i.e. w/o going through raw data, this will be the case)
840     TIter next(fDigitStore->CreateIterator());
841     AliMUONVDigit* digit = static_cast<AliMUONVDigit*>(next());
842     if (digit && !digit->IsCalibrated())
843     {
844       Calibrate(*fDigitStore);
845     }
846   }
847     
848   FillTreeR(fTriggerStore,*clustersTree);
849 }
850
851 //_____________________________________________________________________________
852 AliMUONVTriggerStore*
853 AliMUONReconstructor::TriggerStore() const
854 {
855   /// Return (and create if necessary and allowed) the trigger container
856   TString sopt(GetOption());
857   sopt.ToUpper();
858   
859   if (sopt.Contains("TRIGGERDISABLE"))
860   {
861     delete fTriggerStore;
862     fTriggerStore = 0x0;
863   }
864   else
865   {
866     if (!fTriggerStore)
867     {
868       fTriggerStore = new AliMUONTriggerStoreV1;
869     }
870   }
871   return fTriggerStore;
872 }