/// reconstruct tracks from recpoints
///
/// Actual tracking is performed by some AliMUONVTrackReconstructor children
+/// Tracking modes (ORIGINAL, KALMAN) and associated options and parameters can be changed
+/// through the AliMUONRecoParam object set in the reconstruction macro or read from the CDB
+/// (see methods in AliMUONRecoParam.h file for details)
///
/// \author Christian Finck and Laurent Aphecetche, SUBATECH Nantes
//-----------------------------------------------------------------------------
#include "AliMUONTracker.h"
+#include "AliCodeTimer.h"
+#include "AliESDEvent.h"
+#include "AliESDMuonTrack.h"
+#include "AliESDVertex.h"
+#include "AliLog.h"
+#include "AliMUONClusterStoreV2.h"
+#include "AliMUONESDInterface.h"
+#include "AliMUONLegacyClusterServer.h"
+#include "AliMUONRecoParam.h"
+#include "AliMUONReconstructor.h"
#include "AliMUONTrack.h"
#include "AliMUONTrackExtrap.h"
#include "AliMUONTrackHitPattern.h"
#include "AliMUONTrackReconstructor.h"
#include "AliMUONTrackReconstructorK.h"
#include "AliMUONTrackStoreV1.h"
-#include "AliMUONTriggerChamberEff.h"
#include "AliMUONTriggerTrackStoreV1.h"
-#include "AliMUONVClusterStore.h"
+#include "AliMUONTriggerTrack.h"
+#include "AliMUONLocalTrigger.h"
+#include "AliMUONVClusterServer.h"
+#include "AliMUONVDigitStore.h"
#include "AliMUONVTriggerStore.h"
-
-#include "AliESDEvent.h"
-#include "AliESDMuonTrack.h"
-#include "AliESDVertex.h"
-#include "AliLoader.h"
-#include "AliLog.h"
-
+#include "AliMUONTriggerUtilities.h"
#include <Riostream.h>
+#include <TRandom.h>
#include <TTree.h>
+#include "AliLog.h"
/// \cond CLASSIMP
ClassImp(AliMUONTracker)
//_____________________________________________________________________________
-AliMUONTracker::AliMUONTracker(AliLoader* loader,
- const AliMUONDigitMaker* digitMaker,
+AliMUONTracker::AliMUONTracker(const AliMUONRecoParam* recoParam,
+ AliMUONVClusterServer* clusterServer,
+ AliMUONVDigitStore& digitStore,
const AliMUONGeometryTransformer* transformer,
const AliMUONTriggerCircuit* triggerCircuit,
- AliMUONTriggerChamberEff* chamberEff)
+ const AliMUONTriggerUtilities* triggerUtilities)
: AliTracker(),
- fLoader(loader),
- fDigitMaker(digitMaker), // not owner
- fTransformer(transformer), // not owner
- fTriggerCircuit(triggerCircuit), // not owner
- fTrigChamberEff(chamberEff), // not owner
- fTrackHitPatternMaker(0x0),
- fTrackReco(0x0),
- fClusterStore(0x0),
- fTriggerStore(0x0)
+fkTransformer(transformer), // not owner
+fkTriggerCircuit(triggerCircuit), // not owner
+fTrackHitPatternMaker(0x0),
+fTrackReco(0x0),
+fClusterStore(0x0),
+fTriggerStore(0x0),
+fClusterServer(clusterServer),
+fIsOwnerOfClusterServer(kFALSE),
+fkDigitStore(digitStore), // not owner
+fInputClusterStore(0x0),
+fTriggerTrackStore(0x0),
+fkRecoParam(recoParam),
+fInternalTrackStore(0x0)
{
/// constructor
- if (fTransformer && fDigitMaker)
+
+ if (fkTransformer)
+ fTrackHitPatternMaker = new AliMUONTrackHitPattern(recoParam,*fkTransformer,fkDigitStore,triggerUtilities);
+
+ if (!fClusterServer)
{
- fTrackHitPatternMaker = new AliMUONTrackHitPattern(*fTransformer,*fDigitMaker);
+ AliDebug(1,"No cluster server given. Will use AliMUONLegacyClusterServer");
+ fIsOwnerOfClusterServer = kTRUE;
+ }
+ else
+ {
+ TIter next(fkDigitStore.CreateIterator());
+ fClusterServer->UseDigits(next,&digitStore);
+
+ SetupClusterServer(*fClusterServer);
}
}
AliMUONTracker::~AliMUONTracker()
{
/// dtor
+
delete fTrackReco;
delete fTrackHitPatternMaker;
delete fClusterStore;
delete fTriggerStore;
+ if ( fIsOwnerOfClusterServer ) delete fClusterServer;
+ delete fInputClusterStore;
+ delete fTriggerTrackStore;
+ delete fInternalTrackStore;
}
//_____________________________________________________________________________
-Int_t
-AliMUONTracker::LoadClusters(TTree* clustersTree)
+AliMUONVClusterStore*
+AliMUONTracker::ClusterStore() const
{
- /// Load clusterStore and triggerStore from clustersTree
- delete fClusterStore;
- delete fTriggerStore;
+ /// Return (and create if necessary) the cluster container
+ if (!fClusterStore)
+ {
+ fClusterStore = new AliMUONClusterStoreV2;
+ }
+ return fClusterStore;
+}
- fClusterStore = AliMUONVClusterStore::Create(*clustersTree);
- fTriggerStore = AliMUONVTriggerStore::Create(*clustersTree);
-
- if (!fClusterStore)
+//_____________________________________________________________________________
+AliMUONVTriggerTrackStore*
+AliMUONTracker::TriggerTrackStore() const
+{
+ /// Return (and create if necessary) the trigger track container
+ if (!fTriggerTrackStore)
{
- AliError("Could not get clusterStore");
+ fTriggerTrackStore = new AliMUONTriggerTrackStoreV1;
+ }
+ return fTriggerTrackStore;
+}
+
+//_____________________________________________________________________________
+Int_t AliMUONTracker::LoadClusters(TTree* clustersTree)
+{
+ /// Load triggerStore from clustersTree
+
+ if ( ! clustersTree ) {
+ AliFatal("No clustersTree");
return 1;
}
+
+ if ( !fTriggerStore )
+ {
+ fTriggerStore = AliMUONVTriggerStore::Create(*clustersTree);
+ }
+
if (!fTriggerStore)
{
AliError("Could not get triggerStore");
return 2;
}
- fClusterStore->Connect(*clustersTree,kFALSE);
+ if (!fInputClusterStore)
+ {
+ fInputClusterStore = AliMUONVClusterStore::Create(*clustersTree);
+ if (!fInputClusterStore)
+ {
+ AliError("Could not get clusterStore");
+ return 3;
+ }
+ AliDebug(1,Form("Created %s from cluster tree",fInputClusterStore->ClassName()));
+ }
+
+ if ( !fClusterServer && fIsOwnerOfClusterServer )
+ {
+ if ( !fClusterServer )
+ {
+ fClusterServer = new AliMUONLegacyClusterServer(*fkTransformer,fInputClusterStore,
+ GetRecoParam()->BypassSt4(),
+ GetRecoParam()->BypassSt5());
+ SetupClusterServer(*fClusterServer);
+ }
+
+ }
+
+ fInputClusterStore->Clear();
+ fInputClusterStore->Connect(*clustersTree,kFALSE);
+ fTriggerStore->Clear();
fTriggerStore->Connect(*clustersTree,kFALSE);
clustersTree->GetEvent(0);
}
//_____________________________________________________________________________
-Int_t
-AliMUONTracker::Clusters2Tracks(AliESDEvent* esd)
+Int_t AliMUONTracker::Clusters2Tracks(AliESDEvent* esd)
{
- /// Performs the tracking and store the resulting tracks in both
- /// the TreeT and the ESD
-
- Int_t rv(0);
+ /// Performs the tracking and store the resulting tracks in the ESD
+ ///
+ /// note that we're dealing with two cluster stores here : fInputClusterStore
+ /// and ClusterStore().
+ /// The first one is read from the TreeR and may be used by the cluster server
+ /// (that's the case for the legacy cluster server) to fill the other one.
+ /// The second one is more dynamic and might be created on the fly by the cluster
+ /// server (used by the combined tracking, in which case the first one is not used
+ /// at all).
- TTree* tracksTree = fLoader->TreeT();
+ AliCodeTimerAuto("",0)
- if (!tracksTree)
+ if (!fTrackReco)
{
- AliError("Cannot get TreeT");
- rv=1;
+ fTrackReco = CreateTrackReconstructor(GetRecoParam(),fClusterServer);
+ fInternalTrackStore = new AliMUONTrackStoreV1;
}
- if (!fClusterStore)
+
+ // if the required tracking mode does not exist
+ if (!fTrackReco) return 1;
+
+ if ( ! ClusterStore() )
{
AliError("ClusterStore is NULL");
- rv=2;
+ return 2;
}
- if (!fTriggerStore)
- {
+
+ if (!fTriggerStore) {
AliError("TriggerStore is NULL");
- rv=3;
+ return 3;
}
- if (!rv)
- {
- rv = Clusters2Tracks(*tracksTree,esd);
- }
- return rv;
-}
-//_____________________________________________________________________________
-Int_t AliMUONTracker::Clusters2Tracks(TTree& tracksTree, AliESDEvent* esd)
-{
- /// Performs the tracking
-
- AliDebug(1,"");
-
- AliMUONVTrackStore* trackStore(0x0);
- AliMUONVTriggerTrackStore* triggerTrackStore(0x0);
-
- // Make tracker tracks
- if ( fClusterStore )
+ // Make trigger tracks
+ if ( fkTriggerCircuit )
{
- trackStore = new AliMUONTrackStoreV1;
- Bool_t alone = ( ( fTriggerStore && fTriggerCircuit ) ? kFALSE : kTRUE );
- trackStore->Connect(tracksTree,alone);
- fTrackReco->EventReconstruct(*fClusterStore,*trackStore);
+ TriggerTrackStore()->Clear();
+ fTrackReco->EventReconstructTrigger(*fkTriggerCircuit,*fTriggerStore,*(TriggerTrackStore()));
}
- if ( fTriggerStore && fTriggerCircuit )
+ if ( TriggerTrackStore()->GetSize() > GetRecoParam()->GetMaxTriggerTracks() )
{
- // Make trigger tracks
- triggerTrackStore = new AliMUONTriggerTrackStoreV1;
- Bool_t alone = ( fClusterStore ? kFALSE : kTRUE );
- triggerTrackStore->Connect(tracksTree,alone);
- fTrackReco->EventReconstructTrigger(*fTriggerCircuit,*fTriggerStore,*triggerTrackStore);
- }
+ // cut to reject shower events
+
+ AliCodeTimerAuto("MUON Shower events",1);
- if ( trackStore && triggerTrackStore && fTriggerStore && fTrackHitPatternMaker )
- {
- fTrackReco->ValidateTracksWithTrigger(*trackStore,*triggerTrackStore,*fTriggerStore,*fTrackHitPatternMaker);
+ AliWarning(Form("Probably got a shower event (%d trigger tracks). Will not reconstruct tracks.",
+ TriggerTrackStore()->GetSize()));
+
+ return 0;
}
+
+ fTrackReco->EventReconstruct(*(ClusterStore()),*fInternalTrackStore);
- // Fills output TreeT
- tracksTree.Fill();
-
- if( trackStore && triggerTrackStore && fTriggerStore && fTrigChamberEff){
- fTrigChamberEff->EventChamberEff(*fTriggerStore,*triggerTrackStore,*trackStore);
+ // Match tracker/trigger tracks
+ if ( fTrackHitPatternMaker )
+ {
+ fTrackReco->ValidateTracksWithTrigger(*fInternalTrackStore,*(TriggerTrackStore()),*fTriggerStore,*fTrackHitPatternMaker);
}
-
- FillESD(*trackStore,esd);
- // cleanup
- delete trackStore;
- delete triggerTrackStore;
+ // Fill ESD
+ FillESD(*fInternalTrackStore,esd);
+
+ fInternalTrackStore->Clear();
+ ClusterStore()->Clear();
return 0;
}
//_____________________________________________________________________________
-void
-AliMUONTracker::FillESD(AliMUONVTrackStore& trackStore, AliESDEvent* esd) const
+void AliMUONTracker::FillESD(const AliMUONVTrackStore& trackStore, AliESDEvent* esd) const
{
/// Fill the ESD from the trackStore
-
AliDebug(1,"");
+ AliCodeTimerAuto("",0)
- // Get vertex
- Double_t vertex[3] = {0};
+ // get ITS vertex
+ Double_t vertex[3] = {0., 0., 0.};
const AliESDVertex* esdVert = esd->GetVertex();
- if (esdVert->GetNContributors())
- {
+ if (esdVert->GetNContributors() > 0 || !strcmp(esdVert->GetTitle(),"vertexer: smearMC")) {
esdVert->GetXYZ(vertex);
AliDebug(1,Form("found vertex (%e,%e,%e)",vertex[0],vertex[1],vertex[2]));
}
- // setting ESD MUON class
- AliESDMuonTrack esdTrack;
-
+ // fill ESD event including all info in ESD cluster if required and only for the given fraction of events
AliMUONTrack* track;
+ AliMUONLocalTrigger* locTrg;
TIter next(trackStore.CreateIterator());
-
- while ( ( track = static_cast<AliMUONTrack*>(next()) ) )
- {
- AliMUONTrackParam* trackParam = static_cast<AliMUONTrackParam*>((track->GetTrackParamAtHit())->First());
- AliMUONTrackParam trackParamAtVtx(*trackParam);
+ if (GetRecoParam()->SaveFullClusterInESD() &&
+ gRandom->Uniform(100.) <= GetRecoParam()->GetPercentOfFullClusterInESD()) {
+
+ while ( ( track = static_cast<AliMUONTrack*>(next()) ) ) {
+
+ if (track->GetMatchTrigger() > 0) {
+ locTrg = static_cast<AliMUONLocalTrigger*>(fTriggerStore->FindLocal(track->LoCircuit()));
+ AliMUONESDInterface::MUONToESD(*track, *esd, vertex, &fkDigitStore, locTrg);
+ } else AliMUONESDInterface::MUONToESD(*track, *esd, vertex, &fkDigitStore);
+
+ }
+
+ } else {
- /// Extrapolate to vertex (which is set to (0,0,0) if not available, see above)
- AliMUONTrackExtrap::ExtrapToVertex(&trackParamAtVtx, vertex[0],vertex[1],vertex[2]);
+ while ( ( track = static_cast<AliMUONTrack*>(next()) ) ) {
+
+ if (track->GetMatchTrigger() > 0) {
+ locTrg = static_cast<AliMUONLocalTrigger*>(fTriggerStore->FindLocal(track->LoCircuit()));
+ AliMUONESDInterface::MUONToESD(*track, *esd, vertex, 0x0, locTrg);
+ } else AliMUONESDInterface::MUONToESD(*track, *esd, vertex);
+
+ }
- // setting data member of ESD MUON
+ }
+
+ // fill the local trigger decisions not matched with tracks (associate them to "ghost" tracks)
+ UInt_t ghostId = 0xFFFFFFFF - 1;
+ Bool_t matched = kFALSE;
+ AliMUONTriggerTrack *triggerTrack;
+ TIter itTriggerTrack(fTriggerTrackStore->CreateIterator());
+ while ( ( triggerTrack = static_cast<AliMUONTriggerTrack*>(itTriggerTrack()) ) ) {
+
+ locTrg = static_cast<AliMUONLocalTrigger*>(fTriggerStore->FindLocal(triggerTrack->GetLoTrgNum()));
- // at first station
- esdTrack.SetInverseBendingMomentumUncorrected(trackParam->GetInverseBendingMomentum());
- esdTrack.SetThetaXUncorrected(TMath::ATan(trackParam->GetNonBendingSlope()));
- esdTrack.SetThetaYUncorrected(TMath::ATan(trackParam->GetBendingSlope()));
- esdTrack.SetZUncorrected(trackParam->GetZ());
- esdTrack.SetBendingCoorUncorrected(trackParam->GetBendingCoor());
- esdTrack.SetNonBendingCoorUncorrected(trackParam->GetNonBendingCoor());
- // at vertex
- esdTrack.SetInverseBendingMomentum(trackParamAtVtx.GetInverseBendingMomentum());
- esdTrack.SetThetaX(TMath::ATan(trackParamAtVtx.GetNonBendingSlope()));
- esdTrack.SetThetaY(TMath::ATan(trackParamAtVtx.GetBendingSlope()));
- esdTrack.SetZ(trackParamAtVtx.GetZ());
- esdTrack.SetBendingCoor(trackParamAtVtx.GetBendingCoor());
- esdTrack.SetNonBendingCoor(trackParamAtVtx.GetNonBendingCoor());
- // global info
- esdTrack.SetChi2(track->GetFitFMin());
- esdTrack.SetNHit(track->GetNTrackHits());
- esdTrack.SetLocalTrigger(track->GetLocalTrigger());
- esdTrack.SetChi2MatchTrigger(track->GetChi2MatchTrigger());
- esdTrack.SetHitsPatternInTrigCh(track->GetHitsPatternInTrigCh());
+ // check if this local trigger has already been matched
+ TIter itTrack(trackStore.CreateIterator());
+ while ( ( track = static_cast<AliMUONTrack*>(itTrack()) ) ) {
+ matched = (track->LoCircuit() == locTrg->LoCircuit());
+ if (matched) break;
+ }
+ if (matched) continue;
+
+ AliMUONESDInterface::MUONToESD(*locTrg, *esd, ghostId, triggerTrack);
- // storing ESD MUON Track into ESD Event
- esd->AddMuonTrack(&esdTrack);
- } // end of loop on tracks
+ ghostId -= 1;
+ }
+
}
//_____________________________________________________________________________
-void AliMUONTracker::SetOption(Option_t* option)
+AliMUONVTrackReconstructor* AliMUONTracker::CreateTrackReconstructor(const AliMUONRecoParam* recoParam, AliMUONVClusterServer* clusterServer)
{
- /// set reconstructor class
+ /// Create track reconstructor, depending on tracking mode set in RecoParam
- if (strstr(option,"Original"))
+ AliMUONVTrackReconstructor* trackReco(0x0);
+
+ TString opt(recoParam->GetTrackingMode());
+ opt.ToUpper();
+
+ if (strstr(opt,"ORIGINAL"))
+ {
+ trackReco = new AliMUONTrackReconstructor(recoParam,clusterServer);
+ }
+ else if (strstr(opt,"KALMAN"))
{
- fTrackReco = new AliMUONTrackReconstructor;
+ trackReco = new AliMUONTrackReconstructorK(recoParam,clusterServer);
}
- else
+ else
{
- fTrackReco = new AliMUONTrackReconstructorK();
+ AliErrorClass(Form("tracking mode \"%s\" does not exist",opt.Data()));
+ return 0x0;
}
+
+ AliDebugClass(1,Form("Will use %s for tracking",trackReco->ClassName()));
+
+ return trackReco;
}
//_____________________________________________________________________________
-void
-AliMUONTracker::UnloadClusters()
+void AliMUONTracker::UnloadClusters()
{
- /// Delete internal clusterStore
- delete fClusterStore;
- fClusterStore = 0x0;
+ /// Clear internal clusterStore
+
+ fInputClusterStore->Clear();
+}
+
+
+//_____________________________________________________________________________
+void
+AliMUONTracker::SetupClusterServer(AliMUONVClusterServer& clusterServer)
+{
+ /// Setup the cluster server
+
+ if ( GetRecoParam()->BypassSt4() ||
+ GetRecoParam()->BypassSt5() )
+ {
+ Bool_t ok = clusterServer.UseTriggerTrackStore(TriggerTrackStore());
+
+ TString msg1;
+ TString msg2;
+
+ if ( GetRecoParam()->BypassSt45() )
+ {
+ msg1 = "STATIONS 4 AND 5";
+ msg2 = "THOSE TWO STATIONS";
+ }
+ else if ( GetRecoParam()->BypassSt4() )
+ {
+ msg1 = "STATION 4";
+ msg2 = "THAT STATION";
+ }
+ else if ( GetRecoParam()->BypassSt5() )
+ {
+ msg1 = "STATION 5";
+ msg2 = "THAT STATION";
+ }
+
+ if ( ok )
+ {
+ AliWarning(Form("WILL USE TRIGGER TRACKS TO GENERATE CLUSTERS IN %s, "
+ "THUS BYPASSING REAL CLUSTERS IN %s!!!",msg1.Data(),msg2.Data()));
+ }
+ else
+ {
+ AliWarning("BYPASSING OF ST4 AND/OR 5 REQUESTED, BUT CLUSTERSERVER DOES NOT SEEM TO SUPPORT IT !!!");
+ }
+ }
}
+