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 /// PRECLUSTER : use only AliMUONPreClusterFinder. Only for debug as
36 /// the produced clusters do not have a position, hence the tracking will not
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...
43 /// NOCLUSTERING : bypass completely the clustering stage
45 /// NOSTATUSMAP : disable the computation and usage of the pad status map. Only
48 /// NOLOCALRECONSTRUCTION : for debug, to disable local reconstruction (and hence
49 /// "recover" old behavior)
51 /// TRIGGERDISABLE : disable the treatment of MUON trigger
53 /// \author Laurent Aphecetche, Subatech
55 #include "AliMUONReconstructor.h"
57 #include "AliCDBManager.h"
58 #include "AliLoader.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>
90 ClassImp(AliMUONReconstructor)
93 //_____________________________________________________________________________
94 AliMUONReconstructor::AliMUONReconstructor() :
98 fTransformer(new AliMUONGeometryTransformer(kTRUE)),
100 fTriggerCircuit(0x0),
101 fCalibrationData(0x0),
102 fDigitCalibrator(0x0),
103 fClusterReconstructor(0x0),
107 fTrigChamberEff(0x0),
108 fTimers(new AliMUONStopwatchGroup)
111 fTransformer->ReadGeometryData("volpath.dat", "geometry.root");
114 //_____________________________________________________________________________
115 AliMUONReconstructor::~AliMUONReconstructor()
121 delete fCrateManager;
122 delete fTriggerCircuit;
123 delete fCalibrationData;
124 delete fDigitCalibrator;
125 delete fClusterReconstructor;
126 delete fClusterStore;
127 delete fTriggerStore;
129 delete fTrigChamberEff;
135 //_____________________________________________________________________________
137 AliMUONReconstructor::Calibrate(AliMUONVDigitStore& digitStore) const
139 /// Calibrate the digitStore
140 if (!fDigitCalibrator)
144 AliMUONStopwatchGroupElement timer(fTimers,"MUON",Form("%s::Calibrate(AliMUONVDigitStore*)",fDigitCalibrator->ClassName()));
145 fDigitCalibrator->Calibrate(digitStore);
148 //_____________________________________________________________________________
150 AliMUONReconstructor::Clusterize(const AliMUONVDigitStore& digitStore,
151 AliMUONVClusterStore& clusterStore) const
153 /// Creates clusters from digits.
155 TString sopt(GetOption());
157 if ( sopt.Contains("NOCLUSTERING") ) return;
159 if (!fClusterReconstructor)
161 CreateClusterReconstructor();
164 AliMUONStopwatchGroupElement timer(fTimers,"MUON",Form("%s::Digits2Clusters(const AliMUONVDigitStore&,AliMUONVClusterStore&)",
165 fClusterReconstructor->ClassName()));
166 fClusterReconstructor->Digits2Clusters(digitStore,clusterStore);
169 //_____________________________________________________________________________
170 AliMUONVClusterStore*
171 AliMUONReconstructor::ClusterStore() const
173 /// Return (and create if necessary) the cluster container
176 fClusterStore = new AliMUONClusterStoreV1;
178 return fClusterStore;
181 //_____________________________________________________________________________
183 AliMUONReconstructor::ConvertDigits(AliRawReader* rawReader,
184 AliMUONVDigitStore* digitStore,
185 AliMUONVTriggerStore* triggerStore) const
187 /// Convert raw data into digit and trigger stores
189 AliMUONStopwatchGroupElement timer(fTimers,"MUON",Form("%s::Raw2Digits(AliRawReader*,AliMUONVDigitStore*,AliMUONVTriggerStore*)",
190 fDigitMaker->ClassName()));
191 fDigitMaker->Raw2Digits(rawReader,digitStore,triggerStore);
192 Calibrate(*digitStore);
195 //_____________________________________________________________________________
197 AliMUONReconstructor::ConvertDigits(AliRawReader* rawReader, TTree* digitsTree) const
199 /// convert raw data into a digit tree
201 Bool_t alone = ( TriggerStore() == 0 );
203 Bool_t ok = DigitStore()->Connect(*digitsTree,alone);
204 if ( TriggerStore() )
206 ok = ok && TriggerStore()->Connect(*digitsTree,kFALSE);
211 AliError("Could not make branches on TreeD");
215 ConvertDigits(rawReader,DigitStore(),TriggerStore());
217 DigitStore()->Clear();
221 //_____________________________________________________________________________
222 AliMUONTriggerCrateStore*
223 AliMUONReconstructor::CrateManager() const
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;
232 //_____________________________________________________________________________
234 AliMUONReconstructor::CreateDigitMaker() const
236 /// Create (and create if necessary) the digit maker
237 if (fDigitMaker) return;
239 AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::CreateDigitMaker()");
241 fDigitMaker = new AliMUONDigitMaker;
244 //_____________________________________________________________________________
246 AliMUONReconstructor::CreateTriggerCircuit() const
248 /// Return (and create if necessary) the trigger circuit object
249 if (fTriggerCircuit) return;
251 AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::CreateTriggerCircuit()");
253 fTriggerCircuit = new AliMUONTriggerCircuit(fTransformer);
257 //_____________________________________________________________________________
259 AliMUONReconstructor::CreateTriggerChamberEff() const
261 /// Create (and create if necessary) the trigger chamber efficiency class
262 if (fTrigChamberEff) return;
264 AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::CreateTriggerChamberEff()");
266 fTrigChamberEff = new AliMUONTriggerChamberEff(fTransformer,fDigitMaker,kTRUE);
267 //fTrigChamberEff->SetDebugLevel(1);
270 //_____________________________________________________________________________
272 AliMUONReconstructor::CreateTracker(AliRunLoader* runLoader) const
274 /// Create the MUONTracker object
275 /// The MUONTracker is passed the GetOption(), i.e. our own options
277 CreateTriggerCircuit();
279 CreateTriggerChamberEff();
281 AliLoader* loader = runLoader->GetDetectorLoader("MUON");
284 AliError("Cannot get MUONLoader, so cannot create MUONTracker");
287 AliMUONTracker* tracker = new AliMUONTracker(loader,fDigitMaker,fTransformer,fTriggerCircuit,fTrigChamberEff);
288 tracker->SetOption(GetOption());
293 //_____________________________________________________________________________
295 AliMUONReconstructor::CreateClusterReconstructor() const
297 /// Create cluster reconstructor, depending on GetOption()
299 AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::CreateClusterReconstructor()");
303 AliMUONVClusterFinder* clusterFinder(0x0);
305 TString opt(GetOption());
308 if ( strstr(opt,"PRECLUSTER") )
310 clusterFinder = new AliMUONPreClusterFinder;
312 else if ( strstr(opt,"COG") )
314 clusterFinder = new AliMUONClusterFinderCOG;
316 else if ( strstr(opt,"SIMPLEFIT") )
318 clusterFinder = new AliMUONClusterFinderSimpleFit;
320 else if ( strstr(opt,"MLEM:DRAW") )
322 clusterFinder = new AliMUONClusterFinderMLEM(kTRUE);
324 else if ( strstr(opt,"MLEM") )
326 clusterFinder = new AliMUONClusterFinderMLEM(kFALSE);
328 else if ( strstr(opt,"AZ") )
330 clusterFinder = new AliMUONClusterFinderAZ;
334 clusterFinder = new AliMUONClusterFinderAZ;
339 AliInfo(Form("Will use %s for clusterizing",clusterFinder->ClassName()));
342 fClusterReconstructor = new AliMUONClusterReconstructor(clusterFinder,fTransformer);
345 //_____________________________________________________________________________
347 AliMUONReconstructor::CreateCalibrator() const
349 /// Create the calibrator
351 AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::CreateCalibrator()");
353 Int_t runNumber = AliCDBManager::Instance()->GetRun();
355 AliInfo("Calibration will occur.");
357 fCalibrationData = new AliMUONCalibrationData(runNumber);
358 if ( !fCalibrationData->IsValid() )
360 AliError("Could not retrieve calibrations !");
361 delete fCalibrationData;
362 fCalibrationData = 0x0;
366 // Check that we get all the calibrations we'll need
367 if ( !fCalibrationData->Pedestals() ||
368 !fCalibrationData->Gains() ||
369 !fCalibrationData->HV() )
371 AliFatal("Could not access all required calibration data");
374 TString opt(GetOption());
376 Bool_t statusMap(kTRUE);
378 if ( strstr(opt,"NOSTATUSMAP") )
380 AliWarning("Disconnecting status map : SHOULD BE USED FOR DEBUG ONLY. NOT FOR PRODUCTION !!!");
383 fDigitCalibrator = new AliMUONDigitCalibrator(*fCalibrationData,statusMap);
386 //_____________________________________________________________________________
388 AliMUONReconstructor::DigitStore() const
390 /// Return (and create if necessary) the digit container
393 fDigitStore = new AliMUONDigitStoreV1;
398 //_____________________________________________________________________________
400 AliMUONReconstructor::FillTreeR(AliMUONVTriggerStore* triggerStore,
401 AliMUONVClusterStore* clusterStore,
402 TTree& clustersTree) const
404 /// Write the trigger and cluster information into TreeR
406 AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::FillTreeR()");
413 Bool_t alone = ( clusterStore ? kFALSE : kTRUE );
414 ok = triggerStore->Connect(clustersTree,alone);
417 AliError("Could not create triggerStore branches in TreeR");
423 Bool_t alone = ( triggerStore ? kFALSE : kTRUE );
424 ok = clusterStore->Connect(clustersTree,alone);
427 AliError("Could not create triggerStore branches in TreeR");
431 if (ok) // at least one type of branches created successfully
437 //_____________________________________________________________________________
439 AliMUONReconstructor::HasDigitConversion() const
441 /// We *do* have digit conversion, but we might advertise it only
442 /// if we want to save the digits.
444 TString opt(GetOption());
446 if ( opt.Contains("SAVEDIGITS" ) && !opt.Contains("NOLOCALRECONSTRUCTION") )
456 //_____________________________________________________________________________
458 AliMUONReconstructor::HasLocalReconstruction() const
460 /// Whether or not we have local reconstruction
461 TString opt(GetOption());
463 if ( opt.Contains("NOLOCALRECONSTRUCTION" ) )
473 //_____________________________________________________________________________
475 AliMUONReconstructor::Reconstruct(AliRawReader* rawReader, TTree* clustersTree) const
477 /// This method is called by AliReconstruction if HasLocalReconstruction()==kTRUE AND
478 /// HasDigitConversion()==kFALSE
482 AliError("clustersTree is 0x0 !");
488 ConvertDigits(rawReader,DigitStore(),TriggerStore());
489 Clusterize(*(DigitStore()),*(ClusterStore()));
492 FillTreeR(TriggerStore(),ClusterStore(),*clustersTree);
495 //_____________________________________________________________________________
497 AliMUONReconstructor::Reconstruct(AliRunLoader* runLoader) const
499 /// Reconstruct simulated data
501 AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::Reconstruct(AliRunLoader*)");
503 AliLoader* loader = runLoader->GetDetectorLoader("MUON");
506 AliError("Could not get MUON loader");
510 Int_t nEvents = runLoader->GetNumberOfEvents();
512 for ( Int_t i = 0; i < nEvents; ++i )
514 runLoader->GetEvent(i);
516 loader->LoadRecPoints("update");
517 loader->CleanRecPoints();
518 loader->MakeRecPointsContainer();
519 TTree* clustersTree = loader->TreeR();
521 loader->LoadDigits("read");
522 TTree* digitsTree = loader->TreeD();
524 Reconstruct(digitsTree,clustersTree);
526 loader->UnloadDigits();
527 loader->WriteRecPoints("OVERWRITE");
528 loader->UnloadRecPoints();
532 //_____________________________________________________________________________
534 AliMUONReconstructor::Reconstruct(AliRunLoader* runLoader, AliRawReader* rawReader) const
536 /// This method is called by AliReconstruction if HasLocalReconstruction()==kFALSE
538 AliMUONStopwatchGroupElement timer(fTimers,"MUON","AliMUONReconstructor::Reconstruct(AliRunLoader*, AliRawReader*)");
540 AliLoader* loader = runLoader->GetDetectorLoader("MUON");
543 AliError("Could not get MUON loader");
549 while (rawReader->NextEvent())
551 runLoader->GetEvent(i++);
553 loader->LoadRecPoints("update");
554 loader->CleanRecPoints();
555 loader->MakeRecPointsContainer();
556 TTree* clustersTree = loader->TreeR();
558 loader->LoadDigits("update");
559 loader->CleanDigits();
560 loader->MakeDigitsContainer();
561 TTree* digitsTree = loader->TreeD();
562 ConvertDigits(rawReader, digitsTree);
563 loader->WriteDigits("OVERWRITE");
565 Reconstruct(digitsTree,clustersTree);
567 loader->UnloadDigits();
568 loader->WriteRecPoints("OVERWRITE");
569 loader->UnloadRecPoints();
573 //_____________________________________________________________________________
575 AliMUONReconstructor::Reconstruct(TTree* digitsTree, TTree* clustersTree) const
577 /// This method is called by AliReconstruction if HasLocalReconstruction()==kTRUE
578 /// AND HasDigitConversion()==kTRUE
582 if (!digitsTree || !clustersTree)
584 AliError(Form("Tree is null : digitsTree=%p clustersTree=%p",
585 digitsTree,clustersTree));
591 fDigitStore = AliMUONVDigitStore::Create(*digitsTree);
594 AliError(Form("Could not get DigitStore from %s",digitsTree->GetName()));
598 AliInfo(Form("Created %s from %s",fDigitStore->ClassName(),digitsTree->GetName()));
603 fTriggerStore = AliMUONVTriggerStore::Create(*digitsTree);
606 AliError(Form("Could not get TriggerStore from %s",digitsTree->GetName()));
610 AliInfo(Form("Created %s from %s",fTriggerStore->ClassName(),digitsTree->GetName()));
614 if (!fTriggerStore && !fDigitStore)
616 AliError("No store at all. Nothing to do.");
620 // insure we start with empty stores
623 fDigitStore->Clear();
624 Bool_t alone = ( fTriggerStore ? kFALSE : kTRUE );
625 Bool_t ok = fDigitStore->Connect(*digitsTree,alone);
628 AliError("Could not connect digitStore to digitsTree");
634 fTriggerStore->Clear();
635 Bool_t alone = ( fDigitStore ? kFALSE : kTRUE );
636 Bool_t ok = fTriggerStore->Connect(*digitsTree,alone);
639 AliError("Could not connect triggerStore to digitsTree");
644 digitsTree->GetEvent(0);
648 // Insure we got calibrated digits (if we reconstruct from pure simulated,
649 // i.e. w/o going through raw data, this will be the case)
650 TIter next(fDigitStore->CreateIterator());
651 AliMUONVDigit* digit = static_cast<AliMUONVDigit*>(next());
652 if (!digit->IsCalibrated())
654 Calibrate(*fDigitStore);
656 Clusterize(*fDigitStore,*(ClusterStore()));
659 FillTreeR(fTriggerStore,ClusterStore(),*clustersTree);
662 //_____________________________________________________________________________
663 AliMUONVTriggerStore*
664 AliMUONReconstructor::TriggerStore() const
666 /// Return (and create if necessary and allowed) the trigger container
667 TString sopt(GetOption());
670 if (sopt.Contains("TRIGGERDISABLE"))
672 delete fTriggerStore;
679 fTriggerStore = new AliMUONTriggerStoreV1;
682 return fTriggerStore;