1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
17 /// \class AliMUONReconstructor
19 /// Implementation of AliReconstructor for MUON subsystem.
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.
26 /// Valid options are :
28 /// SAVEDIGITS : if you want to save in the TreeD the *calibrated* digits
29 /// that are used for the clustering
31 /// SIMPLEFIT : use the AliMUONClusterFinderSimpleFit clusterizer
33 /// AZ : use the AliMUONClusterFinderAZ clusterizer (default)
35 /// MLEM : another implementation of AZ, where preclustering is external
36 /// MLEMV3 : MLEM with preclustering=PRECLUSTERV2
37 /// MLEMV3 : MLEM with preclustering=PRECLUSTERV3
39 /// PRECLUSTER : use only AliMUONPreClusterFinder. Only for debug as
40 /// the produced clusters do not have a position, hence the tracking will not
42 /// PRECLUSTERV2 : another version of the preclustering
43 /// PRECLUSTERV3 : yet another version of the preclustering
45 /// COG : use AliMUONClusterFinderCOG clusterizer. Not really a production
46 /// option either, as center-of-gravity is generally not a good estimate
47 /// of the cluster position...
49 /// NOCLUSTERING : bypass completely the clustering stage
51 /// NOSTATUSMAP : disable the computation and usage of the pad status map. Only
54 /// NOLOCALRECONSTRUCTION : for debug, to disable local reconstruction (and hence
55 /// "recover" old behavior)
57 /// TRIGGERDISABLE : disable the treatment of MUON trigger
59 /// DIGITSTOREV1 : use the V1 implementation of the digitstore
60 /// DIGITSTOREV2R : use the V2R implementation of the digitstore
62 /// \author Laurent Aphecetche, Subatech
64 #include "AliMUONReconstructor.h"
66 #include "AliCDBManager.h"
67 #include "AliLoader.h"
69 #include "AliRunLoader.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"
94 #include "AliRawReader.h"
95 #include "AliCodeTimer.h"
96 #include <Riostream.h>
97 #include <TClonesArray.h>
100 //#include "AliCodeTimer.h"
102 ClassImp(AliMUONReconstructor)
105 //_____________________________________________________________________________
106 AliMUONReconstructor::AliMUONReconstructor() :
110 fTransformer(new AliMUONGeometryTransformer()),
112 fTriggerCircuit(0x0),
113 fCalibrationData(0x0),
114 fDigitCalibrator(0x0),
115 fClusterReconstructor(0x0),
123 // Load geometry data
124 fTransformer->LoadGeometryData();
127 if ( ! AliMpCDB::LoadMpSegmentation() )
129 AliFatal("Could not access mapping from OCDB !");
133 if ( ! AliMpCDB::LoadDDLStore() )
135 AliFatal("Could not access DDL Store from OCDB !");
141 //_____________________________________________________________________________
142 AliMUONReconstructor::~AliMUONReconstructor()
148 delete fCrateManager;
149 delete fTriggerCircuit;
150 delete fCalibrationData;
151 delete fDigitCalibrator;
152 delete fClusterReconstructor;
153 delete fClusterStore;
154 delete fTriggerStore;
156 delete fTrigChamberEff;
159 //_____________________________________________________________________________
161 AliMUONReconstructor::Calibrate(AliMUONVDigitStore& digitStore) const
163 /// Calibrate the digitStore
164 if (!fDigitCalibrator)
168 AliCodeTimerAuto(Form("%s::Calibrate(AliMUONVDigitStore*)",fDigitCalibrator->ClassName()))
169 fDigitCalibrator->Calibrate(digitStore);
172 //_____________________________________________________________________________
174 AliMUONReconstructor::Clusterize(const AliMUONVDigitStore& digitStore,
175 AliMUONVClusterStore& clusterStore) const
177 /// Creates clusters from digits.
179 TString sopt(GetOption());
181 if ( sopt.Contains("NOCLUSTERING") ) return;
183 if (!fClusterReconstructor)
185 CreateClusterReconstructor();
188 AliCodeTimerAuto(Form("%s::Digits2Clusters(const AliMUONVDigitStore&,AliMUONVClusterStore&)",
189 fClusterReconstructor->ClassName()))
190 fClusterReconstructor->Digits2Clusters(digitStore,clusterStore);
193 //_____________________________________________________________________________
194 AliMUONVClusterStore*
195 AliMUONReconstructor::ClusterStore() const
197 /// Return (and create if necessary) the cluster container
200 fClusterStore = new AliMUONClusterStoreV1;
202 return fClusterStore;
205 //_____________________________________________________________________________
207 AliMUONReconstructor::ConvertDigits(AliRawReader* rawReader,
208 AliMUONVDigitStore* digitStore,
209 AliMUONVTriggerStore* triggerStore) const
211 /// Convert raw data into digit and trigger stores
214 AliCodeTimerStart(Form("%s::Raw2Digits(AliRawReader*,AliMUONVDigitStore*,AliMUONVTriggerStore*)",
215 fDigitMaker->ClassName()))
216 fDigitMaker->Raw2Digits(rawReader,digitStore,triggerStore);
217 AliCodeTimerStop(Form("%s::Raw2Digits(AliRawReader*,AliMUONVDigitStore*,AliMUONVTriggerStore*)",
218 fDigitMaker->ClassName()))
219 Calibrate(*digitStore);
222 //_____________________________________________________________________________
224 AliMUONReconstructor::ConvertDigits(AliRawReader* rawReader, TTree* digitsTree) const
226 /// convert raw data into a digit tree
228 Bool_t alone = ( TriggerStore() == 0 );
230 Bool_t ok = DigitStore()->Connect(*digitsTree,alone);
231 if ( TriggerStore() )
233 ok = ok && TriggerStore()->Connect(*digitsTree,kFALSE);
238 AliError("Could not make branches on TreeD");
242 ConvertDigits(rawReader,DigitStore(),TriggerStore());
244 DigitStore()->Clear();
248 //_____________________________________________________________________________
249 AliMUONTriggerCrateStore*
250 AliMUONReconstructor::CrateManager() const
252 /// Return (and create if necessary) the trigger crate store
253 if (fCrateManager) return fCrateManager;
254 fCrateManager = new AliMUONTriggerCrateStore;
255 fCrateManager->ReadFromFile();
256 return fCrateManager;
259 //_____________________________________________________________________________
261 AliMUONReconstructor::CreateDigitMaker() const
263 /// Create (and create if necessary) the digit maker
264 if (fDigitMaker) return;
268 fDigitMaker = new AliMUONDigitMaker;
271 //_____________________________________________________________________________
273 AliMUONReconstructor::CreateTriggerCircuit() const
275 /// Return (and create if necessary) the trigger circuit object
276 if (fTriggerCircuit) return;
280 fTriggerCircuit = new AliMUONTriggerCircuit(fTransformer);
284 //_____________________________________________________________________________
286 AliMUONReconstructor::CreateTriggerChamberEff() const
288 /// Create (and create if necessary) the trigger chamber efficiency class
289 if (fTrigChamberEff) return;
293 fTrigChamberEff = new AliMUONTriggerChamberEff(fTransformer,fDigitMaker,kTRUE);
294 //fTrigChamberEff->SetDebugLevel(1);
297 //_____________________________________________________________________________
299 AliMUONReconstructor::CreateTracker(AliRunLoader* runLoader) const
301 /// Create the MUONTracker object
302 /// The MUONTracker is passed the GetOption(), i.e. our own options
304 CreateTriggerCircuit();
306 CreateTriggerChamberEff();
308 AliLoader* loader = runLoader->GetDetectorLoader("MUON");
311 AliError("Cannot get MUONLoader, so cannot create MUONTracker");
314 AliMUONTracker* tracker = new AliMUONTracker(loader,fDigitMaker,fTransformer,fTriggerCircuit,fTrigChamberEff);
315 tracker->SetOption(GetOption());
320 //_____________________________________________________________________________
322 AliMUONReconstructor::CreateClusterReconstructor() const
324 /// Create cluster reconstructor, depending on GetOption()
330 AliMUONVClusterFinder* clusterFinder(0x0);
332 TString opt(GetOption());
335 if ( strstr(opt,"PRECLUSTERV2") )
337 clusterFinder = new AliMUONPreClusterFinderV2;
339 else if ( strstr(opt,"PRECLUSTERV3") )
341 clusterFinder = new AliMUONPreClusterFinderV3;
343 else if ( strstr(opt,"PRECLUSTER") )
345 clusterFinder = new AliMUONPreClusterFinder;
347 else if ( strstr(opt,"COG") )
349 clusterFinder = new AliMUONClusterFinderCOG(new AliMUONPreClusterFinder);
351 else if ( strstr(opt,"SIMPLEFITV3") )
353 clusterFinder = new AliMUONClusterFinderSimpleFit(new AliMUONClusterFinderCOG(new AliMUONPreClusterFinderV3));
355 else if ( strstr(opt,"SIMPLEFIT") )
357 clusterFinder = new AliMUONClusterFinderSimpleFit(new AliMUONClusterFinderCOG(new AliMUONPreClusterFinder));
359 else if ( strstr(opt,"MLEM:DRAW") )
361 clusterFinder = new AliMUONClusterFinderMLEM(kTRUE,new AliMUONPreClusterFinder);
363 else if ( strstr(opt,"MLEMV3") )
365 clusterFinder = new AliMUONClusterFinderMLEM(kFALSE,new AliMUONPreClusterFinderV3);
367 else if ( strstr(opt,"MLEMV2") )
369 clusterFinder = new AliMUONClusterFinderMLEM(kFALSE,new AliMUONPreClusterFinderV2);
371 else if ( strstr(opt,"MLEM") )
373 clusterFinder = new AliMUONClusterFinderMLEM(kFALSE,new AliMUONPreClusterFinder);
375 else if ( strstr(opt,"AZ") )
377 clusterFinder = new AliMUONClusterFinderAZ;
381 // default is currently AZ
382 clusterFinder = new AliMUONClusterFinderAZ;
387 AliInfo(Form("Will use %s for clusterizing",clusterFinder->ClassName()));
390 fClusterReconstructor = new AliMUONClusterReconstructor(clusterFinder,fTransformer);
393 //_____________________________________________________________________________
395 AliMUONReconstructor::CreateCalibrator() const
397 /// Create the calibrator
401 Int_t runNumber = AliCDBManager::Instance()->GetRun();
403 AliInfo("Calibration will occur.");
405 fCalibrationData = new AliMUONCalibrationData(runNumber);
406 if ( !fCalibrationData->IsValid() )
408 AliError("Could not retrieve calibrations !");
409 delete fCalibrationData;
410 fCalibrationData = 0x0;
414 // Check that we get all the calibrations we'll need
415 if ( !fCalibrationData->Pedestals() ||
416 !fCalibrationData->Gains() ||
417 !fCalibrationData->HV() )
419 AliFatal("Could not access all required calibration data");
422 TString opt(GetOption());
424 Bool_t statusMap(kTRUE);
426 if ( strstr(opt,"NOSTATUSMAP") )
428 AliWarning("Disconnecting status map : SHOULD BE USED FOR DEBUG ONLY. NOT FOR PRODUCTION !!!");
431 fDigitCalibrator = new AliMUONDigitCalibrator(*fCalibrationData,statusMap);
434 //_____________________________________________________________________________
436 AliMUONReconstructor::DigitStore() const
438 /// Return (and create if necessary) the digit container
441 TString sopt(GetOption());
444 AliInfo(Form("Options=%s",sopt.Data()));
446 if ( sopt.Contains("DIGITSTOREV1") )
448 fDigitStore = AliMUONVDigitStore::Create("AliMUONDigitStoreV1");
450 else if ( sopt.Contains("DIGITSTOREV2R") )
452 fDigitStore = AliMUONVDigitStore::Create("AliMUONDigitStoreV2R");
454 else if ( sopt.Contains("DIGITSTOREV2S") )
456 fDigitStore = AliMUONVDigitStore::Create("AliMUONDigitStoreV2S");
459 if (!fDigitStore) fDigitStore = AliMUONVDigitStore::Create("AliMUONDigitStoreV2R");
461 AliInfo(Form("Will use %s to store digits during reconstruction",fDigitStore->ClassName()));
466 //_____________________________________________________________________________
468 AliMUONReconstructor::FillTreeR(AliMUONVTriggerStore* triggerStore,
469 AliMUONVClusterStore* clusterStore,
470 TTree& clustersTree) const
472 /// Write the trigger and cluster information into TreeR
481 Bool_t alone = ( clusterStore ? kFALSE : kTRUE );
482 ok = triggerStore->Connect(clustersTree,alone);
485 AliError("Could not create triggerStore branches in TreeR");
491 Bool_t alone = ( triggerStore ? kFALSE : kTRUE );
492 ok = clusterStore->Connect(clustersTree,alone);
495 AliError("Could not create triggerStore branches in TreeR");
499 if (ok) // at least one type of branches created successfully
505 //_____________________________________________________________________________
507 AliMUONReconstructor::HasDigitConversion() const
509 /// We *do* have digit conversion, but we might advertise it only
510 /// if we want to save the digits.
512 TString opt(GetOption());
514 if ( opt.Contains("SAVEDIGITS" ) && !opt.Contains("NOLOCALRECONSTRUCTION") )
524 //_____________________________________________________________________________
526 AliMUONReconstructor::HasLocalReconstruction() const
528 /// Whether or not we have local reconstruction
529 TString opt(GetOption());
531 if ( opt.Contains("NOLOCALRECONSTRUCTION" ) )
541 //_____________________________________________________________________________
543 AliMUONReconstructor::Reconstruct(AliRawReader* rawReader, TTree* clustersTree) const
545 /// This method is called by AliReconstruction if HasLocalReconstruction()==kTRUE AND
546 /// HasDigitConversion()==kFALSE
550 AliError("clustersTree is 0x0 !");
554 ConvertDigits(rawReader,DigitStore(),TriggerStore());
555 Clusterize(*(DigitStore()),*(ClusterStore()));
557 FillTreeR(TriggerStore(),ClusterStore(),*clustersTree);
560 //_____________________________________________________________________________
562 AliMUONReconstructor::Reconstruct(AliRunLoader* runLoader) const
564 /// Reconstruct simulated data
566 AliCodeTimerAuto("Reconstruct(AliRunLoader*)")
568 AliLoader* loader = runLoader->GetDetectorLoader("MUON");
571 AliError("Could not get MUON loader");
575 Int_t nEvents = runLoader->GetNumberOfEvents();
577 for ( Int_t i = 0; i < nEvents; ++i )
579 runLoader->GetEvent(i);
581 loader->LoadRecPoints("update");
582 loader->CleanRecPoints();
583 loader->MakeRecPointsContainer();
584 TTree* clustersTree = loader->TreeR();
586 loader->LoadDigits("read");
587 TTree* digitsTree = loader->TreeD();
589 Reconstruct(digitsTree,clustersTree);
591 loader->UnloadDigits();
592 loader->WriteRecPoints("OVERWRITE");
593 loader->UnloadRecPoints();
597 //_____________________________________________________________________________
599 AliMUONReconstructor::Reconstruct(AliRunLoader* runLoader, AliRawReader* rawReader) const
601 /// This method is called by AliReconstruction if HasLocalReconstruction()==kFALSE
603 AliCodeTimerAuto("AliMUONReconstructor::Reconstruct(AliRunLoader*, AliRawReader*)")
605 AliLoader* loader = runLoader->GetDetectorLoader("MUON");
608 AliError("Could not get MUON loader");
614 while (rawReader->NextEvent())
616 runLoader->GetEvent(i++);
618 loader->LoadRecPoints("update");
619 loader->CleanRecPoints();
620 loader->MakeRecPointsContainer();
621 TTree* clustersTree = loader->TreeR();
623 loader->LoadDigits("update");
624 loader->CleanDigits();
625 loader->MakeDigitsContainer();
626 TTree* digitsTree = loader->TreeD();
627 ConvertDigits(rawReader, digitsTree);
628 loader->WriteDigits("OVERWRITE");
630 Reconstruct(digitsTree,clustersTree);
632 loader->UnloadDigits();
633 loader->WriteRecPoints("OVERWRITE");
634 loader->UnloadRecPoints();
638 //_____________________________________________________________________________
640 AliMUONReconstructor::Reconstruct(TTree* digitsTree, TTree* clustersTree) const
642 /// This method is called by AliReconstruction if HasLocalReconstruction()==kTRUE
643 /// AND HasDigitConversion()==kTRUE
645 // AliCodeTimerAuto("(TTree*,TTree*)")
649 if (!digitsTree || !clustersTree)
651 AliError(Form("Tree is null : digitsTree=%p clustersTree=%p",
652 digitsTree,clustersTree));
658 fDigitStore = AliMUONVDigitStore::Create(*digitsTree);
661 AliError(Form("Could not get DigitStore from %s",digitsTree->GetName()));
665 AliInfo(Form("Created %s from %s",fDigitStore->ClassName(),digitsTree->GetName()));
670 fTriggerStore = AliMUONVTriggerStore::Create(*digitsTree);
673 AliError(Form("Could not get TriggerStore from %s",digitsTree->GetName()));
677 AliInfo(Form("Created %s from %s",fTriggerStore->ClassName(),digitsTree->GetName()));
681 if (!fTriggerStore && !fDigitStore)
683 AliError("No store at all. Nothing to do.");
687 // insure we start with empty stores
690 fDigitStore->Clear();
691 Bool_t alone = ( fTriggerStore ? kFALSE : kTRUE );
692 Bool_t ok = fDigitStore->Connect(*digitsTree,alone);
695 AliError("Could not connect digitStore to digitsTree");
701 fTriggerStore->Clear();
702 Bool_t alone = ( fDigitStore ? kFALSE : kTRUE );
703 Bool_t ok = fTriggerStore->Connect(*digitsTree,alone);
706 AliError("Could not connect triggerStore to digitsTree");
711 digitsTree->GetEvent(0);
715 // Insure we got calibrated digits (if we reconstruct from pure simulated,
716 // i.e. w/o going through raw data, this will be the case)
717 TIter next(fDigitStore->CreateIterator());
718 AliMUONVDigit* digit = static_cast<AliMUONVDigit*>(next());
719 if (!digit->IsCalibrated())
721 Calibrate(*fDigitStore);
723 Clusterize(*fDigitStore,*(ClusterStore()));
726 FillTreeR(fTriggerStore,ClusterStore(),*clustersTree);
729 //_____________________________________________________________________________
730 AliMUONVTriggerStore*
731 AliMUONReconstructor::TriggerStore() const
733 /// Return (and create if necessary and allowed) the trigger container
734 TString sopt(GetOption());
737 if (sopt.Contains("TRIGGERDISABLE"))
739 delete fTriggerStore;
746 fTriggerStore = new AliMUONTriggerStoreV1;
749 return fTriggerStore;