/* $Id$ */
-/// \class AliMUONVTrackReconstructor
////////////////////////////////////
///
+/// \class AliMUONVTrackReconstructor
/// Virtual MUON track reconstructor in ALICE (class renamed from AliMUONEventReconstructor)
///
/// This class contains as data:
/// * EventReconstruct to build the muon tracks
/// * EventReconstructTrigger to build the trigger tracks
///
+/// \author Philippe Pillot
+///
////////////////////////////////////
-#include <stdlib.h>
-#include <Riostream.h>
-#include <TClonesArray.h>
-#include <TMath.h>
-#include <TTree.h>
-
#include "AliMUONVTrackReconstructor.h"
-#include "AliMUONData.h"
+#include "AliMUONRecData.h"
#include "AliMUONConstants.h"
#include "AliMUONHitForRec.h"
#include "AliMUONObjectPair.h"
#include "AliMUONTrack.h"
#include "AliMUONTrackParam.h"
#include "AliMUONTrackExtrap.h"
-#include "AliMagF.h"
+#include "AliMUONTrackHitPattern.h"
+
#include "AliLog.h"
#include "AliTracker.h"
+#include <Riostream.h>
+#include <TClonesArray.h>
+#include <TMath.h>
+
+/// \cond CLASSIMP
ClassImp(AliMUONVTrackReconstructor) // Class implementation in ROOT context
+/// \endcond
//************* Defaults parameters for reconstruction
const Double_t AliMUONVTrackReconstructor::fgkDefaultMinBendingMomentum = 3.0;
const Double_t AliMUONVTrackReconstructor::fgkDefaultMaxNormChi2MatchTrigger = 16.0;
//__________________________________________________________________________
-AliMUONVTrackReconstructor::AliMUONVTrackReconstructor(AliMUONData* data)
+AliMUONVTrackReconstructor::AliMUONVTrackReconstructor(AliMUONRecData* data)
: TObject(),
fMinBendingMomentum(fgkDefaultMinBendingMomentum),
fMaxBendingMomentum(fgkDefaultMaxBendingMomentum),
fBendingVertexDispersion(fgkDefaultBendingVertexDispersion),
fNonBendingVertexDispersion(fgkDefaultNonBendingVertexDispersion),
fMaxNormChi2MatchTrigger(fgkDefaultMaxNormChi2MatchTrigger),
- fSegmentMaxDistBending(0x0),
- fSegmentMaxDistNonBending(0x0),
fHitsForRecPtr(0x0),
fNHitsForRec(0),
fNHitsForRecPerChamber(0x0),
fTriggerCircuit(0x0)
{
/// Constructor for class AliMUONVTrackReconstructor
- fSegmentMaxDistBending = new Double_t[AliMUONConstants::NTrackingSt()];
- fSegmentMaxDistNonBending = new Double_t[AliMUONConstants::NTrackingSt()];
fNHitsForRecPerChamber = new Int_t[AliMUONConstants::NTrackingCh()];
fIndexOfFirstHitForRecPerChamber = new Int_t[AliMUONConstants::NTrackingCh()];
- SetReconstructionParametersToDefaults();
-
// Memory allocation for the TClonesArray of hits for reconstruction
// Is 10000 the right size ????
fHitsForRecPtr = new TClonesArray("AliMUONHitForRec", 10000);
const AliMagF* kField = AliTracker::GetFieldMap();
if (!kField) AliFatal("No field available");
AliMUONTrackExtrap::SetField(kField);
+
+ fTrackHitPattern = new AliMUONTrackHitPattern(fMUONData);
}
//__________________________________________________________________________
AliMUONVTrackReconstructor::~AliMUONVTrackReconstructor(void)
{
/// Destructor for class AliMUONVTrackReconstructor
- delete [] fSegmentMaxDistBending;
- delete [] fSegmentMaxDistNonBending;
delete [] fNHitsForRecPerChamber;
delete [] fIndexOfFirstHitForRecPerChamber;
delete fTriggerTrack;
delete fHitsForRecPtr;
-}
-
- //__________________________________________________________________________
-void AliMUONVTrackReconstructor::SetReconstructionParametersToDefaults(void)
-{
- /// Set reconstruction parameters for making segments to default values
- // Would be much more convenient with a structure (or class) ????
-
- // ******** Parameters for making segments
- // should be parametrized ????
- // according to interval between chambers in a station ????
- // Maximum distance in non bending plane
- // 5 * 0.22 just to remember the way it was made in TRACKF_STAT
- // SIGCUT*DYMAX(IZ)
- for (Int_t st = 0; st < AliMUONConstants::NTrackingSt(); st++)
- fSegmentMaxDistNonBending[st] = 5. * 0.22;
- // Maximum distance in bending plane:
- // values from TRACKF_STAT, corresponding to (J psi 20cm),
- // scaled to the real distance between chambers in a station
- fSegmentMaxDistBending[0] = TMath::Abs( 1.5 *
- (AliMUONConstants::DefaultChamberZ(1) - AliMUONConstants::DefaultChamberZ(0)) / 20.0);
- fSegmentMaxDistBending[1] = TMath::Abs( 1.5 *
- (AliMUONConstants::DefaultChamberZ(3) - AliMUONConstants::DefaultChamberZ(2)) / 20.0);
- fSegmentMaxDistBending[2] = TMath::Abs( 3.0 *
- (AliMUONConstants::DefaultChamberZ(5) - AliMUONConstants::DefaultChamberZ(4)) / 20.0);
- fSegmentMaxDistBending[3] = TMath::Abs( 6.0 *
- (AliMUONConstants::DefaultChamberZ(7) - AliMUONConstants::DefaultChamberZ(6)) / 20.0);
- fSegmentMaxDistBending[4] = TMath::Abs( 6.0 *
- (AliMUONConstants::DefaultChamberZ(9) - AliMUONConstants::DefaultChamberZ(8)) / 20.0);
-
- return;
+ delete fTrackHitPattern;
}
//__________________________________________________________________________
void AliMUONVTrackReconstructor::EventReconstruct(void)
{
- // To reconstruct one event
+ /// To reconstruct one event
AliDebug(1,"Enter EventReconstruct");
+
ResetTracks(); //AZ
ResetHitsForRec(); //AZ
AddHitsForRecFromRawClusters();
MakeTracks();
if (fMUONData->IsTriggerTrackBranchesInTree())
ValidateTracksWithTrigger();
-
+
+ fTrackHitPattern->GetHitPattern(fRecTracksPtr);
+
// Add tracks to MUON data container
for(Int_t i=0; i<fNRecTracks; i++) {
AliMUONTrack * track = (AliMUONTrack*) fRecTracksPtr->At(i);
AliMUONHitForRec *hit1Ptr, *hit2Ptr;
AliMUONObjectPair *segment;
- Double_t bendingSlope, distBend, distNonBend, extBendCoor, extNonBendCoor, extrapFact;
- Double_t impactParam = 0., bendingMomentum = 0.; // to avoid compilation warning
+ Double_t bendingSlope = 0, impactParam = 0., bendingMomentum = 0.; // to avoid compilation warning
// first and second chambers (0...) in the station
Int_t ch1 = 2 * station;
Int_t ch2 = ch1 + 1;
hit1++) {
// pointer to the HitForRec
hit1Ptr = (AliMUONHitForRec*) ((*fHitsForRecPtr)[hit1]);
- // extrapolation, on the straight line joining the HitForRec to the vertex (0,0,0),
- // to the Z of the HitForRec in the second chamber of the station
// Loop over HitsForRec's in the second chamber of the station
for (Int_t hit2 = fIndexOfFirstHitForRecPerChamber[ch2];
hit2 < fIndexOfFirstHitForRecPerChamber[ch2] + fNHitsForRecPerChamber[ch2];
hit2++) {
// pointer to the HitForRec
hit2Ptr = (AliMUONHitForRec*) ((*fHitsForRecPtr)[hit2]);
- // absolute values of distances, in bending and non bending planes,
- // between the HitForRec in the second chamber
- // and the previous extrapolation
- extrapFact = hit2Ptr->GetZ()/ hit1Ptr->GetZ();
- extBendCoor = extrapFact * hit1Ptr->GetBendingCoor();
- extNonBendCoor = extrapFact * hit1Ptr->GetNonBendingCoor();
- distBend = TMath::Abs(hit2Ptr->GetBendingCoor() - extBendCoor);
- distNonBend = TMath::Abs(hit2Ptr->GetNonBendingCoor() - extNonBendCoor);
- // bending slope
if ( hit1Ptr->GetZ() - hit2Ptr->GetZ() != 0. ) {
+ // bending slope
bendingSlope = (hit1Ptr->GetBendingCoor() - hit2Ptr->GetBendingCoor()) / (hit1Ptr->GetZ() - hit2Ptr->GetZ());
// impact parameter
impactParam = hit1Ptr->GetBendingCoor() - hit1Ptr->GetZ() * bendingSlope;
AliWarning("hit1Ptr->GetZ() = hit2Ptr->GetZ(): no segment created");
continue;
}
- // check for distances not too large,
- // and impact parameter not too big if stations downstream of the dipole.
- // Conditions "distBend" and "impactParam" correlated for these stations ????
- if ((distBend < fSegmentMaxDistBending[station]) && (distNonBend < fSegmentMaxDistNonBending[station]) &&
- (bendingMomentum < fMaxBendingMomentum) && (bendingMomentum > fMinBendingMomentum)) {
+ // check for bending momentum within tolerances
+ if ((bendingMomentum < fMaxBendingMomentum) && (bendingMomentum > fMinBendingMomentum)) {
// make new segment
segment = new ((*segments)[segments->GetLast()+1]) AliMUONObjectPair(hit1Ptr, hit2Ptr, kFALSE, kFALSE);
if (AliLog::GetGlobalDebugLevel() > 1) {
- cout << "segmentIndex(0...): " << segments->GetLast()
- << " distBend: " << distBend
- << " distNonBend: " << distNonBend
- << endl;
+ cout << "segmentIndex(0...): " << segments->GetLast() << endl;
segment->Dump();
cout << "HitForRec in first chamber" << endl;
hit1Ptr->Dump();
AliMUONTrack *track;
AliMUONTrackParam trackParam;
AliMUONTriggerTrack *triggerTrack;
+ AliMUONLocalTrigger *locTrg;
fMUONData->SetTreeAddress("RL");
fMUONData->GetRecTriggerTracks();
TClonesArray *recTriggerTracks = fMUONData->RecTriggerTracks();
-
- Bool_t matchTrigger;
+
+ fMUONData->SetTreeAddress("TC");
+ fMUONData->GetTrigger();
+ TClonesArray *localTrigger = fMUONData->LocalTrigger();
+
+ Int_t matchTrigger;
Int_t loTrgNum;
Double_t distTriggerTrack[3];
Double_t xTrack, yTrack, ySlopeTrack, chi2MatchTrigger, minChi2MatchTrigger, chi2;
track = (AliMUONTrack*) fRecTracksPtr->First();
while (track) {
- matchTrigger = kFALSE;
+ matchTrigger = -1;
chi2MatchTrigger = 0.;
loTrgNum = -1;
+ Int_t doubleMatch=-1; // Check if track matches 2 trigger tracks
+ Double_t doubleChi2 = -1.;
trackParam = *((AliMUONTrackParam*) (track->GetTrackParamAtHit()->Last()));
AliMUONTrackExtrap::ExtrapToZ(&trackParam, AliMUONConstants::DefaultChamberZ(10)); // extrap to 1st trigger chamber
chi2 = 0.;
for (Int_t iVar = 0; iVar < 3; iVar++) chi2 += distTriggerTrack[iVar]*distTriggerTrack[iVar];
chi2 /= 3.; // Normalized Chi2: 3 degrees of freedom (X,Y,slopeY)
- if (chi2 < minChi2MatchTrigger && chi2 < fMaxNormChi2MatchTrigger) {
- minChi2MatchTrigger = chi2;
- matchTrigger = kTRUE;
- chi2MatchTrigger = chi2;
- loTrgNum=triggerTrack->GetLoTrgNum();
+ if (chi2 < fMaxNormChi2MatchTrigger) {
+ Bool_t isDoubleTrack = (TMath::Abs(chi2 - minChi2MatchTrigger)<1.);
+ if (chi2 < minChi2MatchTrigger && chi2 < fMaxNormChi2MatchTrigger) {
+ if(isDoubleTrack){
+ doubleMatch = loTrgNum;
+ doubleChi2 = chi2MatchTrigger;
+ }
+ minChi2MatchTrigger = chi2;
+ chi2MatchTrigger = chi2;
+ loTrgNum=triggerTrack->GetLoTrgNum();
+ locTrg = (AliMUONLocalTrigger*)localTrigger->UncheckedAt(loTrgNum);
+ matchTrigger=0;
+ if(locTrg->LoLpt()>0)matchTrigger=1;
+ if(locTrg->LoHpt()>0)matchTrigger=2;
+ }
+ else if(isDoubleTrack) {
+ doubleMatch = triggerTrack->GetLoTrgNum();
+ doubleChi2 = chi2;
+ }
}
triggerTrack = (AliMUONTriggerTrack*) recTriggerTracks->After(triggerTrack);
}
+ if(doubleMatch>=0){ // If two trigger tracks match, select the one passing more trigger cuts
+ AliDebug(1, Form("Two candidates found: %i and %i",loTrgNum,doubleMatch));
+ AliMUONLocalTrigger *locTrg1 = (AliMUONLocalTrigger*)localTrigger->UncheckedAt(doubleMatch);
+ if((locTrg1->LoLpt()>0 && matchTrigger<1) || (locTrg1->LoHpt() && matchTrigger<2)){
+ if(locTrg1->LoHpt()>0)matchTrigger=2;
+ else matchTrigger=1;
+ loTrgNum = doubleMatch;
+ chi2MatchTrigger=doubleChi2;
+ }
+ }
track->SetMatchTrigger(matchTrigger);
track->SetLoTrgNum(loTrgNum);
//__________________________________________________________________________
Bool_t AliMUONVTrackReconstructor::MakeTriggerTracks(void)
{
- // To make the trigger tracks from Local Trigger
+ /// To make the trigger tracks from Local Trigger
AliDebug(1, "Enter MakeTriggerTracks");
TTree* treeR;
Float_t x11 = 0.;
for (Int_t i=0; i<nlocals; i++) { // loop on Local Trigger
- locTrg = (AliMUONLocalTrigger*)localTrigger->UncheckedAt(i);
-
- AliDebug(1, "AliMUONTrackReconstructor::MakeTriggerTrack using NEW trigger \n");
- AliMUONTriggerCircuit* circuit =
- (AliMUONTriggerCircuit*)fTriggerCircuit->At(locTrg->LoCircuit()-1); // -1 !!!
-
- y11 = circuit->GetY11Pos(locTrg->LoStripX());
- stripX21 = locTrg->LoStripX()+locTrg->LoDev()+1;
- y21 = circuit->GetY21Pos(stripX21);
- x11 = circuit->GetX11Pos(locTrg->LoStripY());
-
- AliDebug(1, Form(" MakeTriggerTrack %d %d %d %d %d %f %f %f \n",i,locTrg->LoCircuit(),
- locTrg->LoStripX(),locTrg->LoStripX()+locTrg->LoDev()+1,locTrg->LoStripY(),y11, y21, x11));
-
- Float_t thetax = TMath::ATan2( x11 , z11 );
- Float_t thetay = TMath::ATan2( (y21-y11) , (z21-z11) );
-
- fTriggerTrack->SetX11(x11);
- fTriggerTrack->SetY11(y11);
- fTriggerTrack->SetThetax(thetax);
- fTriggerTrack->SetThetay(thetay);
- fTriggerTrack->SetGTPattern(gloTrigPat);
- fTriggerTrack->SetLoTrgNum(i);
-
- fMUONData->AddRecTriggerTrack(*fTriggerTrack);
+ locTrg = (AliMUONLocalTrigger*)localTrigger->UncheckedAt(i);
+
+ Bool_t xTrig=kFALSE;
+ Bool_t yTrig=kFALSE;
+
+ if ( locTrg->LoSdev()==1 && locTrg->LoDev()==0 &&
+ locTrg->LoStripX()==0) xTrig=kFALSE; // no trigger in X
+ else xTrig=kTRUE; // trigger in X
+ if (locTrg->LoTrigY()==1 &&
+ locTrg->LoStripY()==15 ) yTrig = kFALSE; // no trigger in Y
+ else yTrig = kTRUE; // trigger in Y
+
+ if (xTrig && yTrig) { // make Trigger Track if trigger in X and Y
+
+ AliDebug(1, "AliMUONTrackReconstructor::MakeTriggerTrack using NEW trigger \n");
+ AliMUONTriggerCircuit* circuit =
+ (AliMUONTriggerCircuit*)fTriggerCircuit->At(locTrg->LoCircuit()-1); // -1 !!!
+
+ y11 = circuit->GetY11Pos(locTrg->LoStripX());
+// need first to convert deviation to [0-30]
+// (see AliMUONLocalTriggerBoard::LocalTrigger)
+ Int_t deviation = locTrg->LoDev();
+ Int_t sign = 0;
+ if ( !locTrg->LoSdev() && deviation ) sign=-1;
+ if ( !locTrg->LoSdev() && !deviation ) sign= 0;
+ if ( locTrg->LoSdev() == 1 ) sign=+1;
+ deviation *= sign;
+ deviation += 15;
+ stripX21 = locTrg->LoStripX()+deviation+1;
+ y21 = circuit->GetY21Pos(stripX21);
+ x11 = circuit->GetX11Pos(locTrg->LoStripY());
+
+ AliDebug(1, Form(" MakeTriggerTrack %d %d %d %d %d %f %f %f \n",i,locTrg->LoCircuit(),
+ locTrg->LoStripX(),locTrg->LoStripX()+locTrg->LoDev()+1,locTrg->LoStripY(),y11, y21, x11));
+
+ Float_t thetax = TMath::ATan2( x11 , z11 );
+ Float_t thetay = TMath::ATan2( (y21-y11) , (z21-z11) );
+
+ fTriggerTrack->SetX11(x11);
+ fTriggerTrack->SetY11(y11);
+ fTriggerTrack->SetThetax(thetax);
+ fTriggerTrack->SetThetay(thetay);
+ fTriggerTrack->SetGTPattern(gloTrigPat);
+ fTriggerTrack->SetLoTrgNum(i);
+
+ fMUONData->AddRecTriggerTrack(*fTriggerTrack);
+ } // board is fired
} // end of loop on Local Trigger
return kTRUE;