X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=MUON%2FAliMUONTrackHitPattern.cxx;h=b6614030785f9c875c58c13b4fcf5d8ffc6caeaa;hb=66586048dfefbba1fb64f8106d8ae2af7dd5a57b;hp=ce67f5d9679138b745142b049ef77743924e7297;hpb=803eec577ba702c6a1733cef71ebe54c956cc84c;p=u%2Fmrichter%2FAliRoot.git diff --git a/MUON/AliMUONTrackHitPattern.cxx b/MUON/AliMUONTrackHitPattern.cxx index ce67f5d9679..b6614030785 100644 --- a/MUON/AliMUONTrackHitPattern.cxx +++ b/MUON/AliMUONTrackHitPattern.cxx @@ -13,57 +13,59 @@ * provided "as is" without express or implied warranty. * **************************************************************************/ -//////////////////////////////////// -/// +/* $Id$ */ + + +//----------------------------------------------------------------------------- /// \class AliMUONTrackHitPattern /// /// This class propagates tracks to trigger chambers -/// searching for fired strips. +/// searching for matching trigger tracks and fired strips. /// /// To each track, a hit pattern for trigger chambers is set. -/// The hit pattern is a UShort_t with 8 bits used: -/// -/// 1 1 0 1 1 1 0 1 -/// | | | -/// ----------- ------------ -/// chamber: 11 12 13 14 | 11 12 13 14 -/// cathode: bending | non-bending -/// +/// /// The main method is: -/// * GetHitPattern +/// * ExecuteValidation /// /// \author Diego Stocco -/// -//////////////////////////////////// +//----------------------------------------------------------------------------- #include "AliMUONTrackHitPattern.h" -#include "AliMUONRecData.h" -#include "AliMUONTrack.h" -#include "AliMUONTrackParam.h" -#include "AliMUONTrackExtrap.h" + #include "AliMUONConstants.h" +#include "AliMUONVDigit.h" +#include "AliMUONVDigitStore.h" #include "AliMUONGeometryTransformer.h" -#include "AliMUONDigit.h" #include "AliMUONLocalTrigger.h" -#include "AliMUONTriggerCrateStore.h" -#include "AliMUONLocalTriggerBoard.h" -#include "AliMUONTriggerCircuit.h" -#include "AliMUONDigitMaker.h" +#include "AliMUONRecoParam.h" +#include "AliMUONTrack.h" +#include "AliMUONTrackExtrap.h" +#include "AliMUONTrackParam.h" +#include "AliMUONVTrackStore.h" +#include "AliMUONVTriggerStore.h" +#include "AliMUONTriggerTrack.h" +#include "AliMUONVTriggerTrackStore.h" +#include "AliMUONTriggerUtilities.h" #include "AliMpPad.h" -#include "AliMpVSegmentation.h" #include "AliMpSegmentation.h" +#include "AliMpVSegmentation.h" +#include "AliMpDEManager.h" +#include "AliMpArea.h" +#include "AliMpConstants.h" #include "AliLog.h" -#include "AliTracker.h" -#include "AliMagF.h" +#include "AliESDMuonTrack.h" +#include "AliCodeTimer.h" #include -#include +#include #include #include -#include +#include +#include +#include /// \cond CLASSIMP ClassImp(AliMUONTrackHitPattern) // Class implementation in ROOT context @@ -71,242 +73,1096 @@ ClassImp(AliMUONTrackHitPattern) // Class implementation in ROOT context //______________________________________________________________________________ -AliMUONTrackHitPattern::AliMUONTrackHitPattern(AliMUONRecData *data) - : TObject(), - fMUONData(data), - fTransformer(new AliMUONGeometryTransformer(kTRUE)), - fCrateManager(new AliMUONTriggerCrateStore()), - fDigitMaker(new AliMUONDigitMaker()) +AliMUONTrackHitPattern::AliMUONTrackHitPattern(const AliMUONRecoParam* recoParam, + const AliMUONGeometryTransformer& transformer, + const AliMUONVDigitStore& digitStore, + const AliMUONTriggerUtilities* triggerUtilities) +: TObject(), +fkRecoParam(recoParam), +fkTransformer(transformer), +fkDigitStore(digitStore), +fkTriggerUtilities(triggerUtilities), +fkMaxDistance(99999.) // obsolete +{ + /// Default constructor + AliMUONTrackExtrap::SetField(); +} + + +//______________________________________________________________________________ +AliMUONTrackHitPattern::~AliMUONTrackHitPattern(void) +{ + /// Destructor +} + + +//______________________________________________________________________________ +void +AliMUONTrackHitPattern::ApplyMCSCorrections(AliMUONTrackParam& trackParam) const { - /// Default constructor + // + /// Returns uncertainties on extrapolated position. + /// Takes into account Branson plane corrections in the iron wall. + // + + const Float_t kZFilterOut = AliMUONConstants::MuonFilterZEnd(); + const Float_t kFilterThickness = kZFilterOut-AliMUONConstants::MuonFilterZBeg(); // cm + + AliMUONTrackExtrap::ExtrapToZCov(&trackParam, kZFilterOut); // Extrap to muon filter end + AliMUONTrackExtrap::AddMCSEffect(&trackParam, kFilterThickness, AliMUONConstants::MuonFilterX0()); // Add MCS effects + return; +} - // Set magnetic field - const AliMagF* kField = AliTracker::GetFieldMap(); - if (!kField) AliFatal("No field available"); - AliMUONTrackExtrap::SetField(kField); - // Geometry transformer - fTransformer->ReadGeometryData("volpath.dat", "geometry.root"); +//______________________________________________________________________________ +void AliMUONTrackHitPattern::ExecuteValidation(const AliMUONVTrackStore& trackStore, + const AliMUONVTriggerTrackStore& triggerTrackStore, + const AliMUONVTriggerStore& triggerStore) const +{ + // + /// Main method: + /// Loops on reco tracks, extrapolates them to trigger chambers + /// and searches for matching trigger tracks and digits + // - // Crate manager to retrieve local boards - fCrateManager->ReadFromFile(); + // Get the hit pattern for all trigger tracks + AliMUONTriggerTrack* triggerTrack; + TIter itTriggerTrack(triggerTrackStore.CreateIterator()); + while ( ( triggerTrack = static_cast(itTriggerTrack() ) ) ){ + AliMUONTrackParam trackParam; + trackParam.SetNonBendingCoor(triggerTrack->GetX11()); + trackParam.SetBendingCoor(triggerTrack->GetY11()); + trackParam.SetZ(triggerTrack->GetZ11()); + trackParam.SetNonBendingSlope(triggerTrack->GetSlopeX()); + trackParam.SetBendingSlope(triggerTrack->GetSlopeY()); + trackParam.SetInverseBendingMomentum(1.); + UInt_t pattern = GetHitPattern(trackParam, kTRUE); + // The pattern is a UInt_t, including the information + // on the matched local board, + // but for backward compatibility we fill a UShort_t + // which do not contain such info. + // In the old pattern, we use 15 bits out of 16, so the last one should + // be masked or it will be filled with 1 bit with the local board info. + triggerTrack->SetHitsPatternInTrigCh((UShort_t)(pattern & 0x7FFF)); + AliDebug(1, Form("Hit pattern (MTR): hits 0x%x slat %2i board %3i effFlag %i", + pattern & 0xFF, AliESDMuonTrack::GetSlatOrInfo(pattern),triggerTrack->GetLoTrgNum(), AliESDMuonTrack::GetEffFlag(pattern))); + } - // set to digit maker - fDigitMaker->SetCrateManager(fCrateManager); + // Match tracker tracks with trigger tracks. + TIter itTrack(trackStore.CreateIterator()); + AliMUONTrack* track; - for(Int_t ch=0; ch<4; ch++){ - fTriggerDigitsList[ch].Clear(); - } + const Int_t kFirstTrigCh = AliMUONConstants::NTrackingCh(); + + while ( ( track = static_cast(itTrack()) ) ) + { + AliMUONTrackParam trackParam(*((AliMUONTrackParam*) (track->GetTrackParamAtCluster()->Last()))); + + ApplyMCSCorrections(trackParam); + AliMUONTrackExtrap::ExtrapToZCov(&trackParam, AliMUONConstants::DefaultChamberZ(kFirstTrigCh)); // extrap to 1st trigger chamber + + AliMUONTriggerTrack *matchedTriggerTrack = MatchTriggerTrack(track, trackParam, triggerTrackStore, triggerStore); + if ( matchedTriggerTrack ) track->SetHitsPatternInTrigCh(matchedTriggerTrack->GetHitsPatternInTrigCh()); + + UInt_t pattern = GetHitPattern(trackParam, kFALSE); + track->SetHitsPatternInTrigChTrk(pattern); + AliDebug(1, Form("Hit pattern (MTK): hits 0x%x slat %2i board %3i effFlag %i", + pattern & 0xFF, AliESDMuonTrack::GetSlatOrInfo(pattern), AliESDMuonTrack::GetCrossedBoard(pattern), AliESDMuonTrack::GetEffFlag(pattern))); + } } //______________________________________________________________________________ -AliMUONTrackHitPattern::~AliMUONTrackHitPattern(void) +Bool_t AliMUONTrackHitPattern::FindMatchingPads(const AliMUONTrackParam* trackParam, + TArrayI& matchedDetElemId, TObjArray& pads, + const AliMUONVDigitStore& digitStore, + Bool_t isTriggerTrack) const +{ + // + /// Search for matching digits in trigger chamber + // + enum {kBending, kNonBending}; + + Double_t minMatchDist[2]; + Int_t padsInCheckArea[2]; + + AliMUONTrackParam trackParamAtPadZ(*trackParam); + + Int_t inputDetElemId = matchedDetElemId[0]; + + for(Int_t cath=0; cath<2; cath++){ + minMatchDist[cath] = 99999.; + padsInCheckArea[cath] = 0; + } + + Int_t iChamber = AliMpDEManager::GetChamberId(inputDetElemId); + Int_t iSlat = inputDetElemId%100; + + TIter next(digitStore.CreateTriggerIterator()); + AliMUONVDigit* mDigit; + + Double_t xPad = 0., yPad = 0., zPad = 0.; + Double_t sigmaX = 0., sigmaY = 0.; + + Double_t nSigmas = ( isTriggerTrack ) ? GetRecoParam()->GetStripCutForTrigger() : GetRecoParam()->GetSigmaCutForTrigger(); + Bool_t goodForEff = kTRUE; + + while ( ( mDigit = static_cast(next()) ) ) + { + Int_t currDetElemId = mDigit->DetElemId(); + Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId); + if ( currCh != iChamber ) continue; + Int_t currSlat = currDetElemId%100; + Int_t slatDiff = TMath::Abs(currSlat-iSlat); + if ( slatDiff>1 && slatDiff<17 ) continue; // Check neighbour slats + + Int_t cathode = mDigit->Cathode(); + Int_t ix = mDigit->PadX(); + Int_t iy = mDigit->PadY(); + const AliMpVSegmentation* seg = AliMpSegmentation::Instance() + ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode)); + AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE); + + // Get local pad coordinates + Double_t xPadLocal = pad.GetPositionX(); + Double_t yPadLocal = pad.GetPositionY(); + Double_t dpx = pad.GetDimensionX(); + Double_t dpy = pad.GetDimensionY(); + Double_t xWidth = 2. * dpx; + Double_t yWidth = 2. * dpy; + + // Get global pad coordinates + fkTransformer.Local2Global(currDetElemId, xPadLocal, yPadLocal, 0., xPad, yPad, zPad); + + // Get track parameters at pad z + if ( trackParamAtPadZ.CovariancesExist() ) AliMUONTrackExtrap::LinearExtrapToZCov(&trackParamAtPadZ, zPad); + else AliMUONTrackExtrap::LinearExtrapToZ(&trackParamAtPadZ, zPad); + + Double_t deltaX = TMath::Abs(xPad-trackParamAtPadZ.GetNonBendingCoor()) - dpx; + Double_t deltaY = TMath::Abs(yPad-trackParamAtPadZ.GetBendingCoor()) - dpy; + + + // Get sigmas + if ( isTriggerTrack ) { + Double_t checkWidth = TMath::Min(xWidth, yWidth); + Double_t maxCheckArea = GetRecoParam()->GetMaxStripAreaForTrigger() * checkWidth; + Double_t sigma = TMath::Max(checkWidth, 2.); + sigmaX = sigma; // in cm + sigmaY = sigma; // in cm + if ( deltaX <= maxCheckArea && deltaY <= maxCheckArea ) { + padsInCheckArea[cathode]++; + if ( padsInCheckArea[cathode] > 2 ) { + goodForEff = kFALSE; + AliDebug(2, Form("padsInCheckArea[%i] = %i\n",cathode,padsInCheckArea[cathode])); + } + } + } + else { + const TMatrixD& kCovParam = trackParamAtPadZ.GetCovariances(); + sigmaX = TMath::Sqrt(kCovParam(0,0)); // in cm + sigmaY = TMath::Sqrt(kCovParam(2,2)); // in cm + } + + AliDebug(2, Form("\nDetElemId %i Cath %i Dim = (%.2f,%.2f) Pad (%i,%i) = (%.2f,%.2f) Track = (%.2f,%.2f) Delta (%.2f,%.2f) Sigma (%.2f,%.2f) p %g\n", + currDetElemId,cathode,dpx,dpy,ix,iy,xPad,yPad,trackParamAtPadZ.GetNonBendingCoor(),trackParamAtPadZ.GetBendingCoor(),deltaX,deltaY,sigmaX,sigmaY,trackParamAtPadZ.P())); + //if ( deltaX <= maxCheckArea && deltaY <= maxCheckArea ) padsInCheckArea[cathode]++; + if ( deltaX > nSigmas * sigmaX || deltaY > nSigmas * sigmaY ) continue; + Double_t matchDist = TMath::Max(deltaX, deltaY); + if ( matchDist > minMatchDist[cathode] ) continue; + if ( pads.At(cathode) ) delete pads.RemoveAt(cathode); + pads.AddAt((AliMpPad*)pad.Clone(),cathode); + minMatchDist[cathode] = matchDist; + matchedDetElemId[cathode] = currDetElemId; // Set the input detection element id to the matched one + } // loop on digits + +// // If track matches many pads, it is not good for effciency determination. +// // However we still want to calculate the hit pattern. +// for ( Int_t cath=0; cath<2; cath++ ){ +// if ( padsInCheckArea[cath] > 2 ) { +// AliDebug(2, Form("padsInCheckArea[%i] = %i\n",cath,padsInCheckArea[cath])); +// return kFALSE; +// } +// } + + return goodForEff; +} + + +//_____________________________________________________________________________ +UInt_t AliMUONTrackHitPattern::GetHitPattern(const AliMUONTrackParam& trackParam, Bool_t isTriggerTrack) const +{ + // + /// Searches for matching digits around the track. + // + + AliCodeTimerAuto("",0); + + TArrayI digitPerTrack(2); + digitPerTrack.Reset(); + + UInt_t pattern = 0; + + TObjArray trackParamList, matchedPads(2), maskedPads(2), padsFromPos(4), validPads(2); + trackParamList.SetOwner(); matchedPads.SetOwner(); maskedPads.SetOwner(); padsFromPos.SetOwner(); + + Int_t firstSlat = -1, firstBoard = -1; + AliESDMuonTrack::EAliTriggerChPatternFlag goodForEff = AliESDMuonTrack::kBoardEff; + TArrayI matchedDetElemId(2), maskedDetElemId(2), detElemIdFromTrack(2), validDetElemId(2); + + for(Int_t ich=0; ichGetMaskedDigits()), isTriggerTrack); + if ( maskedPads.GetEntries() > 0 ) { + AliESDMuonTrack::AddEffInfo(pattern,AliESDMuonTrack::kTrackMatchesMasks); // pad is masked + goodForEff = AliESDMuonTrack::kNoEff; + for ( Int_t icath=0; icath<2; icath++ ) { + AliMpPad* currPad = (AliMpPad*)maskedPads.UncheckedAt(icath); + if ( ! currPad ) continue; + AliDebug(2,Form("DetElemId %i cath %i board %i strip %i is masked: effFlag 0", matchedDetElemId[icath], icath, currPad->GetLocalBoardId(0), currPad->GetLocalBoardChannel(0))); + } + // continue; + // We want to calculate the hit pattern in any case, so we do not "continue" + // However we set the flag in such a way not to use the track for efficiency calculations + } + + // If no masked pads matched, search for active pads + matchedDetElemId.Reset(detElemIdFromTrack[0]); + if ( ! FindMatchingPads((AliMUONTrackParam*)trackParamList.At(0), matchedDetElemId, matchedPads, fkDigitStore, isTriggerTrack) ) { + // if ! FindPadMatchingTrig => too many digits matching pad => + // => Event not clear => Do not use for efficiency calculation + AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesManyPads); + goodForEff = AliESDMuonTrack::kNoEff; + AliDebug(2, Form("Warning: track in %i matches many pads. Rejected!\n", matchedDetElemId[0])); + } + + Int_t nMatched = 0; + + Int_t mostProbDEmatched = detElemIdFromTrack[0]; + for ( Int_t icath=0; icath<2; icath++ ) { + if ( matchedPads.UncheckedAt(icath) ) { + nMatched++; + // Fill pattern anyway + AliESDMuonTrack::SetFiredChamber(pattern, icath, ich); + digitPerTrack[icath]++; + mostProbDEmatched = matchedDetElemId[icath]; + } + } + Int_t mostProbDEindex = 0; + for ( Int_t ifound=0; ifoundGetLocalBoardId(0); + + for ( Int_t icath=0; icath<2; icath++ ){ + + if ( goodForEff == AliESDMuonTrack::kBoardEff) { + Bool_t atLeastOneLoc = kFALSE; + AliMpPad* currPad = (AliMpPad*)validPads.UncheckedAt(icath); + for ( Int_t iloc=0; ilocGetNofLocations(); iloc++) { + if ( currPad->GetLocalBoardId(iloc) == firstBoard ) { + atLeastOneLoc = kTRUE; + break; + } + } // loop on locations + if ( ! atLeastOneLoc ) goodForEff = AliESDMuonTrack::kSlatEff; + } + } // loop on cathodes + // } // if track good for efficiency + } // end chamber loop + + if ( goodForEff == AliESDMuonTrack::kNoEff ) return pattern; + + for(Int_t cath=0; cath<2; cath++){ + if(digitPerTrack[cath]<3) { + // track is rejected since the number of associated + // digits found is less than 3. + AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesFewPads); + goodForEff = AliESDMuonTrack::kNoEff; + AliDebug(2, Form("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath)); + } + } // loop on cathodes + + if ( goodForEff == AliESDMuonTrack::kNoEff ) return pattern; + + AliESDMuonTrack::AddEffInfo(pattern, firstSlat, firstBoard, goodForEff); + return pattern; +} + + + +//_____________________________________________________________________________ +Int_t AliMUONTrackHitPattern::GetTrackParamAtChamber(const AliMUONTrackParam& inputTrackParam, Int_t chamber, + TObjArray& trackParamList, TArrayI& foundDetElemId, + TObjArray& padsFromPos) const { -/// Destructor - for(Int_t ch=0; ch<4; ch++){ - fTriggerDigitsList[ch].Delete(); + // + /// Return the extrapolated the track parameter at the given chamber + /// and returns the matching DetElemId + /// CAVEAT: at the border the result is not univoque + // + + Int_t nFound = 0; + foundDetElemId[0] = foundDetElemId[1] = 0; + AliMUONTrackParam trackParamCopy(inputTrackParam); + TVector3 globalPoint1(trackParamCopy.GetNonBendingCoor(), trackParamCopy.GetBendingCoor(), trackParamCopy.GetZ()); + AliMUONTrackExtrap::LinearExtrapToZ(&trackParamCopy, trackParamCopy.GetZ() + 20.); + TVector3 globalPoint2(trackParamCopy.GetNonBendingCoor(), trackParamCopy.GetBendingCoor(), trackParamCopy.GetZ()); + TVector3 localCoor; + + // AliMpArea pointArea(x, y, 2.*AliMpConstants::LengthTolerance(), 2.*AliMpConstants::LengthTolerance()); + AliMpDEIterator it; + Double_t xGlobal, yGlobal, zGlobal; + for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){ + Int_t detElemId = it.CurrentDEId(); + PosInDetElemIdLocal(localCoor, globalPoint1, globalPoint2, detElemId); + fkTransformer.Local2Global(detElemId, localCoor.X(), localCoor.Y(), localCoor.Z(), xGlobal, yGlobal, zGlobal); + AliMpArea pointArea(xGlobal, yGlobal, 2.*AliMpConstants::LengthTolerance(), 2.*AliMpConstants::LengthTolerance()); + AliMpArea* deArea = fkTransformer.GetDEArea(detElemId); + if ( deArea->Contains(pointArea) ) { + // Check if track matches valid pads + // (this is not trivial for cut RPC) + Int_t validPads = 0; + for ( Int_t icath=0; icath<2; icath++ ) { + const AliMpVSegmentation* seg = + AliMpSegmentation::Instance() + ->GetMpSegmentation(detElemId,AliMp::GetCathodType(icath)); + AliMpPad pad = seg->PadByPosition(localCoor.X(),localCoor.Y(),kFALSE); + if ( pad.IsValid() ) { + padsFromPos.AddAt(pad.Clone(), 2*nFound + icath); + validPads++; + } + } + if ( validPads < 2 ) continue; + AliMUONTrackParam* extrapTrackParam = new AliMUONTrackParam(inputTrackParam); + if ( extrapTrackParam->CovariancesExist() ) AliMUONTrackExtrap::LinearExtrapToZCov(extrapTrackParam, zGlobal); + else AliMUONTrackExtrap::LinearExtrapToZ(extrapTrackParam, zGlobal); + trackParamList.AddAt(extrapTrackParam,nFound); + foundDetElemId[nFound] = detElemId; + nFound++; + if ( nFound == 2 ) break; } - delete fCrateManager; + else if ( nFound > 0 ) break; + } // loop on detElemId + + return nFound; } //______________________________________________________________________________ -void AliMUONTrackHitPattern::GetHitPattern(TClonesArray *recTracksPtr) +AliMUONTriggerTrack * +AliMUONTrackHitPattern::MatchTriggerTrack(AliMUONTrack* track, + AliMUONTrackParam& trackParam, + const AliMUONVTriggerTrackStore& triggerTrackStore, + const AliMUONVTriggerStore& triggerStore) const { - // - /// Main method: - /// Loops on reco tracks, extrapolates them to trigger chambers - /// and searches for matching digits - // + // + /// Match track with trigger track + // + + Int_t matchTrigger = 0; + Int_t loTrgNum(-1); + TMatrixD paramDiff(3,1); + Double_t chi2; + Double_t chi2MatchTrigger = 0., minChi2MatchTrigger = 999.; + Int_t doubleMatch = -1; // Check if track matches 2 trigger tracks + Double_t doubleChi2 = -1.; + AliMUONTriggerTrack* doubleTriggerTrack = 0x0; + AliMUONTriggerTrack* matchedTriggerTrack = 0x0; - const Int_t mask[2][4]={{0x80, 0x40, 0x20, 0x10}, - {0x08, 0x04, 0x02, 0x01}}; - Bool_t isMatch[2]; - UShort_t pattern=0; - TriggerDigits(); - Int_t nRecTracks = (Int_t)recTracksPtr->GetEntriesFast(); - for(Int_t iTrack=0; iTrackAt(iTrack); - AliMUONTrackParam *trackParam = (AliMUONTrackParam*) ((muonTrack->GetTrackParamAtHit())->Last()); - for(Int_t ch=0; ch<4; ch++){ - AliMUONTrackExtrap::ExtrapToZCov(trackParam, AliMUONConstants::DefaultChamberZ(10+ch)); - FindPadMatchingTrack(trackParam, isMatch, ch); - for(Int_t cath=0; cath<2; cath++){ - if(isMatch[cath]) pattern |= mask[cath][ch]; - } + + // Covariance matrix 3x3 (X,Y,slopeY) for trigger tracks + TMatrixD trackCov(3,3); + + AliMUONTriggerTrack *triggerTrack; + TIter itTriggerTrack(triggerTrackStore.CreateIterator()); + while ( ( triggerTrack = static_cast(itTriggerTrack() ) ) ) + { + AliMUONTrackExtrap::LinearExtrapToZCov(&trackParam, triggerTrack->GetZ11()); + const TMatrixD& kParamCov = trackParam.GetCovariances(); + + Double_t xTrack = trackParam.GetNonBendingCoor(); + Double_t yTrack = trackParam.GetBendingCoor(); + Double_t ySlopeTrack = trackParam.GetBendingSlope(); + + paramDiff(0,0) = triggerTrack->GetX11() - xTrack; + paramDiff(1,0) = triggerTrack->GetY11() - yTrack; + paramDiff(2,0) = triggerTrack->GetSlopeY() - ySlopeTrack; + + // Covariance matrix 3x3 (X,Y,slopeY) for tracker tracks + trackCov.Zero(); + trackCov(0,0) = kParamCov(0,0); + trackCov(1,1) = kParamCov(2,2); + trackCov(2,2) = kParamCov(3,3); + trackCov(1,2) = kParamCov(2,3); + trackCov(2,1) = kParamCov(3,2); + + // Covariance matrix 3x3 (X,Y,slopeY) for trigger tracks + TMatrixD trigCov(triggerTrack->GetCovariances()); + + TMatrixD sumCov(trackCov,TMatrixD::kPlus,trigCov); + if (sumCov.Determinant() != 0) { + sumCov.Invert(); + + TMatrixD tmp(sumCov,TMatrixD::kMult,paramDiff); + TMatrixD chi2M(paramDiff,TMatrixD::kTransposeMult,tmp); + chi2 = chi2M(0,0); + } else { + AliWarning(" Determinant = 0"); + Double_t sigma2 = 0.; + chi2 = 0.; + for (Int_t iVar = 0; iVar < 3; iVar++) { + sigma2 = trackCov(iVar,iVar) + trigCov(iVar,iVar); + chi2 += paramDiff(iVar,0) * paramDiff(iVar,0) / sigma2; + } + } + + chi2 /= 3.; // Normalized Chi2: 3 degrees of freedom (X,Y,slopeY) + if (chi2 < GetRecoParam()->GetMaxNormChi2MatchTrigger()) + { + Bool_t isDoubleTrack = (TMath::Abs(chi2 - minChi2MatchTrigger)<1.); + if (chi2 < minChi2MatchTrigger && chi2 < GetRecoParam()->GetMaxNormChi2MatchTrigger()) + { + if(isDoubleTrack) + { + doubleMatch = loTrgNum; + doubleChi2 = chi2MatchTrigger; + doubleTriggerTrack = matchedTriggerTrack; } - muonTrack->SetHitsPatternInTrigCh(pattern); + minChi2MatchTrigger = chi2; + chi2MatchTrigger = chi2; + loTrgNum = triggerTrack->GetLoTrgNum(); + matchedTriggerTrack = triggerTrack; + AliMUONLocalTrigger* locTrg = triggerStore.FindLocal(loTrgNum); + matchTrigger = 1; + if(locTrg->LoLpt()>0) matchTrigger = 2; + if(locTrg->LoHpt()>0) matchTrigger = 3; + } + else if(isDoubleTrack) + { + doubleMatch = triggerTrack->GetLoTrgNum(); + doubleChi2 = chi2; + } + } + } + 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 = triggerStore.FindLocal(doubleMatch); + if((locTrg1->LoLpt()>0 && matchTrigger<2) || (locTrg1->LoHpt() && matchTrigger<3)) + { + if(locTrg1->LoHpt()>0) matchTrigger=3; + else matchTrigger = 2; + loTrgNum = doubleMatch; + chi2MatchTrigger = doubleChi2; + matchedTriggerTrack = doubleTriggerTrack; + } + } + + track->SetMatchTrigger(matchTrigger); + track->SetChi2MatchTrigger(chi2MatchTrigger); + + AliMUONLocalTrigger* locTrg = static_cast(triggerStore.FindLocal(loTrgNum)); + + if (locTrg) + { + track->SetLocalTrigger(locTrg->LoCircuit(), + locTrg->LoStripX(), + locTrg->LoStripY(), + locTrg->GetDeviation(), + locTrg->LoLpt(), + locTrg->LoHpt(), + locTrg->GetTriggerWithoutChamber()); + } + + return matchedTriggerTrack; +} + + +//_____________________________________________________________________________ +Bool_t AliMUONTrackHitPattern::PosInDetElemIdLocal(TVector3& localCoor, const TVector3& globalPoint1, + const TVector3& globalPoint2, Int_t detElemId) const +{ + /// Given two points belonging to a line (global coordinates) + /// it returns the intersection point with the detElemId (local coordinates) + + Double_t xloc, yloc, zloc; + fkTransformer.Global2Local(detElemId, globalPoint1.X(), globalPoint1.Y(), globalPoint1.Z(), xloc, yloc, zloc); + TVector3 localPoint1(xloc, yloc, zloc); + fkTransformer.Global2Local(detElemId, globalPoint2.X(), globalPoint2.Y(), globalPoint2.Z(), xloc, yloc, zloc); + TVector3 localPoint2(xloc, yloc, zloc); + localCoor = localPoint1 - ( localPoint1.Z() / ( localPoint2.Z() - localPoint1.Z() ) ) * ( localPoint2 - localPoint1 ); + + return kTRUE; +} + + +// THE FOLLOWING METHODS ARE OBSOLETE + +//______________________________________________________________________________ +UInt_t AliMUONTrackHitPattern::GetHitPattern(const AliMUONTriggerTrack* matchedTriggerTrack) const +{ + // + /// Get hit pattern on trigger chambers for the current trigger track + // + UInt_t pattern = 0; + PerformTrigTrackMatch(pattern, matchedTriggerTrack); + return pattern; +} + + +//______________________________________________________________________________ +UInt_t AliMUONTrackHitPattern::GetHitPattern(AliMUONTrackParam* trackParam) const +{ + // + /// Get hit pattern on trigger chambers for the current tracker track + // + UInt_t pattern = 0; + Bool_t isMatch[2]; + const Int_t kNTrackingCh = AliMUONConstants::NTrackingCh(); + + for(Int_t ch=0; ch<4; ++ch) + { + Int_t iChamber = kNTrackingCh+ch; + AliMUONTrackExtrap::ExtrapToZCov(trackParam, AliMUONConstants::DefaultChamberZ(iChamber)); + FindPadMatchingTrack(*trackParam, isMatch, iChamber); + for(Int_t cath=0; cath<2; ++cath) + { + if(isMatch[cath]) AliESDMuonTrack::SetFiredChamber(pattern, cath, ch); } - return; + } + + // pattern obtained by propagation of tracker track + // when it does not match the trigger. + AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackerTrackPattern); + + return pattern; } //______________________________________________________________________________ -void AliMUONTrackHitPattern::FindPadMatchingTrack(AliMUONTrackParam *trackParam, - Bool_t isMatch[2], Int_t iChamber) +void +AliMUONTrackHitPattern::FindPadMatchingTrack(const AliMUONTrackParam& trackParam, + Bool_t isMatch[2], Int_t iChamber) const { // - /// Given track position, searches for matching digits. + /// Given the tracker track position, searches for matching digits. // Float_t minMatchDist[2]; - for(Int_t cath=0; cath<2; cath++){ - isMatch[cath]=kFALSE; - minMatchDist[cath]=9999.; + for(Int_t cath=0; cath<2; ++cath) + { + isMatch[cath]=kFALSE; + minMatchDist[cath]=fkMaxDistance/10.; } - Int_t ndigits = (Int_t)fTriggerDigitsList[iChamber].GetEntries(); - AliMUONDigit * mDigit = 0x0; - for(Int_t idigit=0; idigitDetElemId(); - - Int_t cathode = mDigit->Cathode(); - Int_t ix = mDigit->PadX(); - Int_t iy = mDigit->PadY(); - Float_t xpad, ypad, zpad; - const AliMpVSegmentation* seg = AliMpSegmentation::Instance() - ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode)); - - AliMpPad pad = seg->PadByIndices(AliMpIntPair(ix,iy),kTRUE); - Float_t xlocal1 = pad.Position().X(); - Float_t ylocal1 = pad.Position().Y(); - Float_t dpx = pad.Dimensions().X(); - Float_t dpy = pad.Dimensions().Y(); - fTransformer->Local2Global(currDetElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad); - Float_t matchDist = MinDistanceFromPad(xpad, ypad, zpad, dpx, dpy, trackParam); - if(matchDist>minMatchDist[cathode])continue; - isMatch[cathode] = kTRUE; - minMatchDist[cathode] = matchDist; - } + TIter next(fkDigitStore.CreateTriggerIterator()); + AliMUONVDigit* mDigit; + + while ( ( mDigit = static_cast(next()) ) ) + { + Int_t currDetElemId = mDigit->DetElemId(); + Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId); + if(currCh!=iChamber) continue; + Int_t cathode = mDigit->Cathode(); + Int_t ix = mDigit->PadX(); + Int_t iy = mDigit->PadY(); + Float_t xpad, ypad, zpad; + const AliMpVSegmentation* seg = AliMpSegmentation::Instance() + ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode)); + + AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE); + Float_t xlocal1 = pad.GetPositionX(); + Float_t ylocal1 = pad.GetPositionY(); + Float_t dpx = pad.GetDimensionX(); + Float_t dpy = pad.GetDimensionY(); - return; + fkTransformer.Local2Global(currDetElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad); + Float_t matchDist = MinDistanceFromPad(xpad, ypad, zpad, dpx, dpy, trackParam); + if(matchDist>minMatchDist[cathode])continue; + isMatch[cathode] = kTRUE; + if(isMatch[0] && isMatch[1]) break; + minMatchDist[cathode] = matchDist; + } } //______________________________________________________________________________ -Float_t AliMUONTrackHitPattern::MinDistanceFromPad(Float_t xPad, Float_t yPad, Float_t zPad, - Float_t dpx, Float_t dpy, AliMUONTrackParam *trackParam) +Float_t +AliMUONTrackHitPattern::MinDistanceFromPad(Float_t xPad, Float_t yPad, Float_t zPad, + Float_t dpx, Float_t dpy, + const AliMUONTrackParam& trackParam) const { // - /// Decides if the digit belongs to the track. + /// Decides if the digit belongs to the tracker track. // - Float_t xTrackAtPad = trackParam->GetNonBendingCoor(); - Float_t yTrackAtPad = trackParam->GetBendingCoor(); - Float_t sigmaX, sigmaY, sigmaMS; - GetPosUncertainty(trackParam, zPad, sigmaX, sigmaY, sigmaMS); + AliMUONTrackParam trackParamAtPadZ(trackParam); + AliMUONTrackExtrap::LinearExtrapToZCov(&trackParamAtPadZ, zPad); + + Float_t xTrackAtPad = trackParamAtPadZ.GetNonBendingCoor(); + Float_t yTrackAtPad = trackParamAtPadZ.GetBendingCoor(); - Float_t maxDistX = 3.*(sigmaX + sigmaMS); // in cm - Float_t maxDistY = 3.*(sigmaY + sigmaMS); // in cm + const Float_t kNSigma = GetRecoParam()->GetSigmaCutForTrigger(); + + const TMatrixD& kCovParam = trackParamAtPadZ.GetCovariances(); + + Float_t sigmaX = TMath::Sqrt(kCovParam(0,0)); + Float_t sigmaY = TMath::Sqrt(kCovParam(2,2)); + + Float_t maxDistX = kNSigma * sigmaX; // in cm + Float_t maxDistY = kNSigma * sigmaY; // in cm Float_t deltaX = TMath::Abs(xPad-xTrackAtPad)-dpx; Float_t deltaY = TMath::Abs(yPad-yTrackAtPad)-dpy; - Float_t matchDist = 99999.; + Float_t matchDist = fkMaxDistance; if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY); + return matchDist; } -//______________________________________________________________________________ -void AliMUONTrackHitPattern::GetPosUncertainty(AliMUONTrackParam *trackParam, Float_t zChamber, - Float_t &sigmaX, Float_t &sigmaY, Float_t &sigmaMS) +//_____________________________________________________________________________ +Bool_t AliMUONTrackHitPattern::FindPadMatchingTrig(const TVector3& vec11, const TVector3& vec21, + Int_t matchedDetElemId[2], TObjArray& pads) const { - // - /// Returns uncertainties on extrapolated position. - /// Takes into account Branson plane corrections in the iron wall. - // - - const Float_t alpha = 0.1123; // GeV/c + // + /// Check slat and board number of digit matching trigger track + // + + enum {kBending, kNonBending}; + + Float_t minMatchDist[2]; + Int_t padsInCheckArea[2]; + + Int_t inputDetElemId = matchedDetElemId[0]; + + for(Int_t cath=0; cath<2; cath++){ + minMatchDist[cath] = fkMaxDistance/10.; + padsInCheckArea[cath] = 0; + } + + Int_t iChamber = AliMpDEManager::GetChamberId(inputDetElemId); + Int_t iSlat = inputDetElemId%100; + + TIter next(fkDigitStore.CreateTriggerIterator()); + AliMUONVDigit* mDigit; + TVector3 localExtrap; + + Int_t previousDetElemId = -1; + + while ( ( mDigit = static_cast(next()) ) ) + { + Int_t currDetElemId = mDigit->DetElemId(); + Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId); + if ( currCh != iChamber ) continue; + Int_t currSlat = currDetElemId%100; + Int_t slatDiff = TMath::Abs(currSlat-iSlat); + if ( slatDiff>1 && slatDiff<17 ) continue; // Check neighbour slats + Int_t cathode = mDigit->Cathode(); + Int_t ix = mDigit->PadX(); + Int_t iy = mDigit->PadY(); + const AliMpVSegmentation* seg = AliMpSegmentation::Instance() + ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode)); - // Find a better way to get such parameters ??? - const Float_t kZFilterIn = 1471.; // From STRUCT/SHILConst2.h - const Float_t kZFilterOut = kZFilterIn + 120.; // From STRUCT/SHILConst2.h + AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE); - const Float_t zBranson = - (kZFilterIn + (kZFilterOut - kZFilterIn)*2./3. ); // - sign because distance are positive - Float_t zDistFromWall = TMath::Abs(zChamber - zBranson); - Float_t zDistFromLastTrackCh = TMath::Abs(zChamber - AliMUONConstants::DefaultChamberZ(9)); - - TMatrixD *covParam = trackParam->GetCovariances(); + if ( currDetElemId != previousDetElemId ) { + PosInDetElemIdLocal(localExtrap, vec11, vec21, currDetElemId); + previousDetElemId = currDetElemId; + } - sigmaX = (*covParam)(0,0); - sigmaY = (*covParam)(2,2); + AliDebug(11, Form("\nDetElemId = %i Cathode = %i Pad = (%i,%i) = (%.2f,%.2f) Dim = (%.2f,%.2f) Track = (%.2f,%.2f)\n", + currDetElemId,cathode,ix,iy,pad.GetPositionX(),pad.GetPositionY(),pad.GetDimensionX(),pad.GetDimensionY(),localExtrap.X(),localExtrap.Y())); + Float_t matchDist = PadMatchTrack(pad, localExtrap); + if ( matchDist < fkMaxDistance/2. ) padsInCheckArea[cathode]++; + if ( matchDist > minMatchDist[cathode] ) continue; + if ( pads.At(cathode) ) delete pads.RemoveAt(cathode); + pads.AddAt((AliMpPad*)pad.Clone(),cathode); + minMatchDist[cathode] = matchDist; + matchedDetElemId[cathode] = currDetElemId; // Set the input detection element id to the matched one + } // loop on digits + + // If track matches many pads, it is not good for effciency determination. + // However we still want to calculate the hit pattern. + for ( Int_t cath=0; cath<2; cath++ ){ + if ( padsInCheckArea[cath] > 2 ) { + AliDebug(10, Form("padsInCheckArea[%i] = %i\n",cath,padsInCheckArea[cath])); + return kFALSE; + } + } + + return kTRUE; +} + +//_____________________________________________________________________________ +Float_t AliMUONTrackHitPattern::PadMatchTrack(const AliMpPad& pad, const TVector3& trackPosAtPad) const +{ + // + /// Decides if the digit belongs to the trigger track. + // + + Float_t xPad = pad.GetPositionX(); + Float_t yPad = pad.GetPositionY(); + Float_t dpx = pad.GetDimensionX(); + Float_t dpy = pad.GetDimensionY(); + - // If covariance matrix is not extrapolated, use "reasonable" errors - // (To be removed as soon as covariance matrix is correctly propagated). - if (sigmaX==0.)sigmaX = 0.003 * zDistFromLastTrackCh; - if (sigmaY==0.)sigmaY = 0.004 * zDistFromLastTrackCh; + Float_t maxDist = GetRecoParam()->GetStripCutForTrigger() * 2. * TMath::Min(dpx,dpy); // cm + if ( maxDist<2. ) maxDist = 2.; + Float_t maxDistCheckArea = GetRecoParam()->GetMaxStripAreaForTrigger() * 2. * TMath::Min(dpx,dpy); // cm - Float_t p = trackParam->P(); - Float_t thetaMS = alpha/p; - sigmaMS = zDistFromWall * TMath::Tan(thetaMS); + Float_t matchDist = fkMaxDistance; - return; + Float_t deltaX = TMath::Abs(xPad-trackPosAtPad.X())-dpx; + Float_t deltaY = TMath::Abs(yPad-trackPosAtPad.Y())-dpy; + Float_t maxDistX = maxDist; + Float_t maxDistY = maxDist; + + if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY); + else if(deltaX<=maxDistCheckArea && deltaY<=maxDistCheckArea) matchDist = fkMaxDistance/5.; + return matchDist; } -//____________________________________________________________________ -Bool_t AliMUONTrackHitPattern::TriggerDigits() +//_____________________________________________________________________________ +Int_t AliMUONTrackHitPattern::DetElemIdFromPos(Float_t x, Float_t y, + Int_t chamber, Int_t foundDetElemId[2]) const { - // - /// make (S)Digit for trigger - // + // + /// Given the (x,y) position in the chamber, + /// it returns the corresponding slats + /// Caveat: at the border the result is not univoque + // + + Int_t nFound = 0; + + foundDetElemId[0] = foundDetElemId[1] = 0; + AliMpArea pointArea(x, y, 2.*AliMpConstants::LengthTolerance(), 2.*AliMpConstants::LengthTolerance()); + AliMpDEIterator it; + for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){ + Int_t detElemId = it.CurrentDEId(); + AliMpArea* deArea = fkTransformer.GetDEArea(detElemId); + + if ( deArea->Contains(pointArea) ) { + foundDetElemId[nFound++] = detElemId; + if ( nFound == 2 ) break; + } + else if ( nFound > 0 ) break; + } // loop on detElemId + + return nFound; +} + - Int_t nBoard; +//_____________________________________________________________________________ +Bool_t AliMUONTrackHitPattern::PadsFromPos(const TVector3& vec11, const TVector3& vec21, + Int_t detElemId, TObjArray& pads) const +{ + // + /// Given the (x,y) position in the chamber, + /// it returns the corresponding local board + // + + pads.Delete(); + + TVector3 localCoor; + PosInDetElemIdLocal(localCoor, vec11, vec21, detElemId); + for ( Int_t icath=0; icath<2; icath++ ) { + const AliMpVSegmentation* seg = + AliMpSegmentation::Instance() + ->GetMpSegmentation(detElemId,AliMp::GetCathodType(icath)); + AliMpPad pad = seg->PadByPosition(localCoor.X(),localCoor.Y(),kFALSE); + if ( pad.IsValid() ) { + pads.AddAt(pad.Clone(), icath); + } + } + + return pads.GetEntries(); +} - TList digitList; - digitList.Clear(); +//_____________________________________________________________________________ +Bool_t AliMUONTrackHitPattern::IsCloseToAccEdge(TObjArray& pads, Int_t detElemId, Float_t coor[2]) const +{ + AliMpArea* deArea = fkTransformer.GetDEArea(detElemId); + Float_t dpx = ((AliMpPad*)pads.At(1))->GetDimensionX(); + Float_t dpy = ((AliMpPad*)pads.At(0))->GetDimensionY(); + Float_t resolution[2] = { static_cast(0.75*dpx), static_cast(0.75*dpy) }; + Float_t sign[3] = {0., 1., -1.}; + for ( Int_t ineighx=0; ineighx<3; ineighx++ ) { + for ( Int_t ineighy=0; ineighy<3; ineighy++ ) { + AliMpArea pointArea(coor[0]+sign[ineighx]*resolution[0], + coor[1]+sign[ineighy]*resolution[1], + 2.*AliMpConstants::LengthTolerance(), + 2.*AliMpConstants::LengthTolerance()); + if ( ! deArea->Contains(pointArea) ) return kTRUE; + } // loop on y neighbours + } // loop on x neighbours + return kFALSE; +} - AliMUONLocalTrigger *locTrg = 0x0; - fMUONData->SetTreeAddress("RC,TC"); - fMUONData->GetTrigger(); +//_____________________________________________________________________________ +Bool_t AliMUONTrackHitPattern::IsMasked(const AliMpPad& pad, Int_t detElemId, Int_t cathode, const TVector3& vec11, const TVector3& vec21) const +{ + // + /// Check if pad or its neighbours are masked + // + + Int_t nMasked = 0; + + if ( fkTriggerUtilities->IsMasked(pad, detElemId, cathode) ) ++nMasked; + + // Check closest neighbour + + TVector3 localCoor; + PosInDetElemIdLocal(localCoor, vec11, vec21, detElemId); + + Float_t padPos[2] = { static_cast(pad.GetPositionX()), static_cast(pad.GetPositionY())}; + Float_t padDim[2] = { static_cast(pad.GetDimensionX()), static_cast(pad.GetDimensionY())}; + Float_t inpactPos[2] = { static_cast(localCoor.X()), static_cast(localCoor.Y())}; + Float_t sign[2] = {-1., 1.}; + Int_t icoor = 1-cathode; + Int_t addSlatSign[3] = {0,1,-1}; + Int_t inputCh = AliMpDEManager::GetChamberId(detElemId)+1; + Int_t inputSlat = detElemId%100; + + Float_t newPos[2]; + for ( Int_t ineigh=0; ineigh<2; ineigh++ ) { + newPos[1-icoor] = inpactPos[1-icoor]; + newPos[icoor] = inpactPos[icoor] + 1.05 * sign[ineigh] * padDim[icoor]; + if ( TMath::Abs(newPos[icoor] - padPos[icoor]) < padDim[icoor] ) continue; + const AliMpVSegmentation* seg = + AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode)); + AliMpPad neighPad = seg->PadByPosition(newPos[0],newPos[1],kFALSE); + if ( neighPad.IsValid() ) { + if ( fkTriggerUtilities->IsMasked(neighPad, detElemId, cathode) ) ++nMasked; + } + else { + TVector3 deltaVec(newPos[0]-inpactPos[0],newPos[1]-inpactPos[1],0.); + TVector3 transVec11 = vec11+deltaVec; + TVector3 transVec21 = vec21+deltaVec; + TObjArray padsFromPos; + padsFromPos.SetOwner(); + for ( Int_t iAddSlat=0; iAddSlat<2; iAddSlat++ ) { + Int_t currSlat = (inputSlat + addSlatSign[iAddSlat])%18; + Int_t currDetElemId = 100 * inputCh + currSlat; + PadsFromPos(transVec11,transVec21,currDetElemId,padsFromPos); + AliMpPad* currPad = (AliMpPad*)padsFromPos.UncheckedAt(cathode); + Bool_t isMasked = ( currPad ) ? fkTriggerUtilities->IsMasked(*currPad, currDetElemId, cathode) : kFALSE; + padsFromPos.Delete(); + if ( isMasked ) ++nMasked; + } + } // loop on slats + } // loop on neigbours + + Double_t maskedProb = ((Double_t)nMasked)/3.; + if ( gRandom->Rndm() < maskedProb ) return kTRUE; + + return kFALSE; +} - TClonesArray *localTrigger = fMUONData->LocalTrigger(); - Int_t nLocTrig = (Int_t) localTrigger->GetEntriesFast(); - for(Int_t iLoc=0; iLocUncheckedAt(iLoc); +//_____________________________________________________________________________ +Bool_t AliMUONTrackHitPattern::PerformTrigTrackMatch(UInt_t &pattern, + const AliMUONTriggerTrack* matchedTrigTrack) const +{ + // + /// It searches for matching digits around the trigger track. + // + + AliCodeTimerAuto("",0); - TArrayS xyPattern[2]; - xyPattern[0].Set(4); - xyPattern[1].Set(4); + enum {kBending, kNonBending}; - xyPattern[0].AddAt(locTrg->GetX1Pattern(),0); - xyPattern[0].AddAt(locTrg->GetX2Pattern(),1); - xyPattern[0].AddAt(locTrg->GetX3Pattern(),2); - xyPattern[0].AddAt(locTrg->GetX4Pattern(),3); + TArrayF zMeanChamber(AliMUONConstants::NTriggerCh()); + zMeanChamber[0] = matchedTrigTrack->GetZ11(); + zMeanChamber[1] = matchedTrigTrack->GetZ11() + AliMUONConstants::DefaultChamberZ(11) - AliMUONConstants::DefaultChamberZ(10); + zMeanChamber[2] = matchedTrigTrack->GetZ21(); + zMeanChamber[3] = matchedTrigTrack->GetZ21() + AliMUONConstants::DefaultChamberZ(13) - AliMUONConstants::DefaultChamberZ(12); - xyPattern[1].AddAt(locTrg->GetY1Pattern(),0); - xyPattern[1].AddAt(locTrg->GetY2Pattern(),1); - xyPattern[1].AddAt(locTrg->GetY3Pattern(),2); - xyPattern[1].AddAt(locTrg->GetY4Pattern(),3); + TArrayI digitPerTrack(2); + digitPerTrack.Reset(); - for(Int_t cath=0; cath<2; cath++){ - for(Int_t ch=0; ch<4; ch++){ - if(xyPattern[cath][ch]==0) continue; - } - } + Float_t trackIntersectCh[2]; - nBoard = locTrg->LoCircuit(); - fDigitMaker->TriggerDigits(nBoard, xyPattern, digitList); + Float_t slopeX = matchedTrigTrack->GetSlopeX(); + Float_t slopeY = matchedTrigTrack->GetSlopeY(); + + Float_t z11 = matchedTrigTrack->GetZ11(); + Float_t x11 = slopeX * z11; + Float_t y11 = matchedTrigTrack->GetY11(); + Float_t z21 = matchedTrigTrack->GetZ21(); + Float_t x21 = slopeX * z21; + Float_t y21 = y11 + slopeY * (z21-z11); + TVector3 vec11(x11, y11, z11), vec21(x21, y21, z21); + + Int_t firstSlat = -1, firstBoard = -1; + AliESDMuonTrack::EAliTriggerChPatternFlag goodForEff = AliESDMuonTrack::kBoardEff; + TObjArray matchedPads(2), padsFromPos(2), validPads(2); + matchedPads.SetOwner(); padsFromPos.SetOwner(); + Int_t matchedDetElemId[2], detElemIdFromTrack[2]; + + for(Int_t ich=0; ich too many digits matching pad => + // => Event not clear => Do not use for efficiency calculation + AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesManyPads); + goodForEff = AliESDMuonTrack::kNoEff; + AliDebug(10, Form("Warning: track = %p (%i) matches many pads. Rejected!\n",(void *)matchedTrigTrack, matchedDetElemId[0])); + } + + Int_t nMatched = 0; + Int_t mostProbDEmatched = detElemIdFromTrack[0]; + for ( Int_t icath=0; icath<2; icath++ ) { + if ( matchedPads.UncheckedAt(icath) ) { + nMatched++; + // Fill pattern anyway + AliESDMuonTrack::SetFiredChamber(pattern, icath, ich); + digitPerTrack[icath]++; + mostProbDEmatched = matchedDetElemId[icath]; + } + } + Int_t mostProbDEfromTrack = detElemIdFromTrack[0]; + for ( Int_t ifound=0; ifoundDetElemId(); - Int_t iChamber = detElemId/100 - 11; //FIXEME should be given by mapping - fTriggerDigitsList[iChamber].Add(digit); + for ( Int_t cath=0; cath<2; cath++ ) { + if ( matchedPads.UncheckedAt(cath) ) validPads.AddAt(matchedPads.UncheckedAt(cath),cath); + else if ( padsFromPos.UncheckedAt(cath) ) { + AliMpPad* currPad = (AliMpPad*)padsFromPos.UncheckedAt(cath); + validPads.AddAt(currPad,cath); + if ( IsMasked(*currPad, mostProbDEfromTrack, cath, vec11, vec21) ) { + // Check if strip was masked (if inefficient strip is found) + AliESDMuonTrack::AddEffInfo(pattern,AliESDMuonTrack::kTrackMatchesMasks); // pad is masked + AliDebug(10,Form("DetElemId %i cath %i board %i strip %i is masked: effFlag 0", mostProbDEfromTrack, cath, currPad->GetLocalBoardId(0), currPad->GetLocalBoardChannel(0))); + goodForEff = AliESDMuonTrack::kNoEff; + } + } + else goodForEff = AliESDMuonTrack::kNoEff; + } // loop on cathodes + + if ( goodForEff != AliESDMuonTrack::kNoEff ) { + + if ( nMatched == 0 && IsCloseToAccEdge(padsFromPos, mostProbDEfromTrack, trackIntersectCh) ) { + // Non of cathodes is fired. + // If we are close to the edge of the RPC + // it could be a problem of acceptance + AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackOutsideGeometry); + goodForEff = AliESDMuonTrack::kNoEff; + AliDebug(10, "Warning: trigger track at the edge of the chamber\n"); + } + + Int_t currSlat = mostProbDEmatched%100; + if ( firstSlat < 0 ) firstSlat = currSlat; + else if ( currSlat != firstSlat ) { + goodForEff = AliESDMuonTrack::kChEff; + firstSlat = AliESDMuonTrack::kCrossDifferentSlats; + } + + if ( firstBoard < 0 ) firstBoard = ((AliMpPad*)validPads[kBending])->GetLocalBoardId(0); + + for ( Int_t cath=0; cath<2; cath++ ){ + + if ( goodForEff == AliESDMuonTrack::kBoardEff) { + Bool_t atLeastOneLoc = kFALSE; + AliMpPad* currPad = (AliMpPad*)validPads.UncheckedAt(cath); + for ( Int_t iloc=0; ilocGetNofLocations(); iloc++) { + if ( currPad->GetLocalBoardId(iloc) == firstBoard ) { + atLeastOneLoc = kTRUE; + break; + } + } // loop on locations + if ( ! atLeastOneLoc ) goodForEff = AliESDMuonTrack::kSlatEff; + } + } // loop on cathodes + } // if track good for efficiency + matchedPads.Delete(); + padsFromPos.Delete(); + } // end chamber loop + + if ( goodForEff == AliESDMuonTrack::kNoEff ) return kFALSE; + for(Int_t cath=0; cath<2; cath++){ + if(digitPerTrack[cath]<3) { + // track is rejected since the number of associated + // digits found is less than 3. + AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesFewPads); + goodForEff = AliESDMuonTrack::kNoEff; + AliDebug(10, Form("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath)); } + } // loop on cathodes - return kTRUE; + if ( goodForEff == AliESDMuonTrack::kNoEff ) return kFALSE; + + AliESDMuonTrack::AddEffInfo(pattern, firstSlat, firstBoard, goodForEff); + return kTRUE; }