LCOV - code coverage report
Current view: top level - MUON/MUONrec - AliMUONTrackHitPattern.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 252 559 45.1 %
Date: 2016-06-14 17:26:59 Functions: 13 24 54.2 %

          Line data    Source code
       1             : /**************************************************************************
       2             :  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
       3             :  *                                                                        *
       4             :  * Author: The ALICE Off-line Project.                                    *
       5             :  * Contributors are mentioned in the code where appropriate.              *
       6             :  *                                                                        *
       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             :  **************************************************************************/
      15             : 
      16             : /* $Id$ */
      17             : 
      18             : 
      19             : //-----------------------------------------------------------------------------
      20             : /// \class AliMUONTrackHitPattern
      21             : ///
      22             : /// This class propagates tracks to trigger chambers 
      23             : /// searching for matching trigger tracks and fired strips.
      24             : ///
      25             : /// To each track, a hit pattern for trigger chambers is set.
      26             : /// 
      27             : /// The main method is:
      28             : /// * ExecuteValidation
      29             : ///
      30             : ///  \author Diego Stocco
      31             : //-----------------------------------------------------------------------------
      32             : 
      33             : 
      34             : #include "AliMUONTrackHitPattern.h"
      35             : 
      36             : #include "AliMUONConstants.h"
      37             : #include "AliMUONVDigit.h"
      38             : #include "AliMUONVDigitStore.h"
      39             : #include "AliMUONGeometryTransformer.h"
      40             : #include "AliMUONLocalTrigger.h"
      41             : #include "AliMUONRecoParam.h"
      42             : #include "AliMUONTrack.h"
      43             : #include "AliMUONTrackExtrap.h"
      44             : #include "AliMUONTrackParam.h"
      45             : #include "AliMUONVTrackStore.h"
      46             : #include "AliMUONVTriggerStore.h"
      47             : #include "AliMUONTriggerTrack.h"
      48             : #include "AliMUONVTriggerTrackStore.h"
      49             : #include "AliMUONTriggerUtilities.h"
      50             : 
      51             : #include "AliMpPad.h"
      52             : #include "AliMpSegmentation.h"
      53             : #include "AliMpVSegmentation.h"
      54             : #include "AliMpDEManager.h"
      55             : #include "AliMpArea.h"
      56             : #include "AliMpConstants.h"
      57             : 
      58             : #include "AliLog.h"
      59             : #include "AliESDMuonTrack.h"
      60             : #include "AliCodeTimer.h"
      61             : 
      62             : #include <Riostream.h>
      63             : #include <TArrayI.h>
      64             : #include <TMath.h>
      65             : #include <TMatrixD.h>
      66             : #include <TVector3.h>
      67             : #include <TArrayF.h>
      68             : #include <TRandom.h>
      69             : 
      70             : /// \cond CLASSIMP
      71          18 : ClassImp(AliMUONTrackHitPattern) // Class implementation in ROOT context
      72             : /// \endcond
      73             : 
      74             : 
      75             : //______________________________________________________________________________
      76             : AliMUONTrackHitPattern::AliMUONTrackHitPattern(const AliMUONRecoParam* recoParam,
      77             :                                                const AliMUONGeometryTransformer& transformer,
      78             :                                                const AliMUONVDigitStore& digitStore,
      79             :                                                const AliMUONTriggerUtilities* triggerUtilities)
      80           2 : : TObject(),
      81           2 : fkRecoParam(recoParam),
      82           2 : fkTransformer(transformer),
      83           2 : fkDigitStore(digitStore),
      84           2 : fkTriggerUtilities(triggerUtilities),
      85           2 : fkMaxDistance(99999.) // obsolete
      86          10 : {
      87             :   /// Default constructor
      88           2 :   AliMUONTrackExtrap::SetField();
      89           4 : }
      90             : 
      91             : 
      92             : //______________________________________________________________________________
      93             : AliMUONTrackHitPattern::~AliMUONTrackHitPattern(void)
      94           8 : {
      95             :   /// Destructor
      96           8 : }
      97             : 
      98             : 
      99             : //______________________________________________________________________________
     100             : void 
     101             : AliMUONTrackHitPattern::ApplyMCSCorrections(AliMUONTrackParam& trackParam) const
     102             : {
     103             :   //
     104             :   /// Returns uncertainties on extrapolated position.
     105             :   /// Takes into account Branson plane corrections in the iron wall.
     106             :   //
     107             :   
     108          32 :   const Float_t kZFilterOut = AliMUONConstants::MuonFilterZEnd();
     109          16 :   const Float_t kFilterThickness = kZFilterOut-AliMUONConstants::MuonFilterZBeg(); // cm
     110             :   
     111          16 :   AliMUONTrackExtrap::ExtrapToZCov(&trackParam, kZFilterOut); // Extrap to muon filter end
     112          16 :   AliMUONTrackExtrap::AddMCSEffect(&trackParam, kFilterThickness, AliMUONConstants::MuonFilterX0()); // Add MCS effects
     113             :   return;
     114          16 : }
     115             : 
     116             : 
     117             : //______________________________________________________________________________
     118             : void AliMUONTrackHitPattern::ExecuteValidation(const AliMUONVTrackStore& trackStore,
     119             :                                                const AliMUONVTriggerTrackStore& triggerTrackStore,
     120             :                                                const AliMUONVTriggerStore& triggerStore) const
     121             : {
     122             :   //
     123             :   /// Main method:
     124             :   /// Loops on reco tracks, extrapolates them to trigger chambers
     125             :   /// and searches for matching trigger tracks and digits
     126             :   //
     127             : 
     128             :   // Get the hit pattern for all trigger tracks
     129             :   AliMUONTriggerTrack* triggerTrack;
     130          16 :   TIter itTriggerTrack(triggerTrackStore.CreateIterator());
     131          66 :   while ( ( triggerTrack = static_cast<AliMUONTriggerTrack*>(itTriggerTrack() ) ) ){
     132          14 :     AliMUONTrackParam trackParam;
     133          14 :     trackParam.SetNonBendingCoor(triggerTrack->GetX11());
     134          14 :     trackParam.SetBendingCoor(triggerTrack->GetY11());
     135          14 :     trackParam.SetZ(triggerTrack->GetZ11());
     136          14 :     trackParam.SetNonBendingSlope(triggerTrack->GetSlopeX());
     137          14 :     trackParam.SetBendingSlope(triggerTrack->GetSlopeY());
     138          14 :     trackParam.SetInverseBendingMomentum(1.);
     139          14 :     UInt_t pattern = GetHitPattern(trackParam, kTRUE);
     140             :     // The pattern is a UInt_t, including the information
     141             :     // on the matched local board,
     142             :     // but for backward compatibility we fill a UShort_t
     143             :     // which do not contain such info.
     144             :     // In the old pattern, we use 15 bits out of 16, so the last one should
     145             :     // be masked or it will be filled with 1 bit with the local board info.
     146          14 :     triggerTrack->SetHitsPatternInTrigCh((UShort_t)(pattern & 0x7FFF));
     147          70 :     AliDebug(1, Form("Hit pattern (MTR): hits 0x%x  slat %2i  board %3i  effFlag %i",
     148             :                      pattern & 0xFF, AliESDMuonTrack::GetSlatOrInfo(pattern),triggerTrack->GetLoTrgNum(), AliESDMuonTrack::GetEffFlag(pattern)));
     149          14 :   }
     150             : 
     151             :   // Match tracker tracks with trigger tracks.
     152          16 :   TIter itTrack(trackStore.CreateIterator());
     153             :   AliMUONTrack* track;
     154             : 
     155           8 :   const Int_t kFirstTrigCh = AliMUONConstants::NTrackingCh();
     156             : 
     157          72 :   while ( ( track = static_cast<AliMUONTrack*>(itTrack()) ) )
     158             :   { 
     159          48 :     AliMUONTrackParam trackParam(*((AliMUONTrackParam*) (track->GetTrackParamAtCluster()->Last())));
     160             : 
     161          16 :     ApplyMCSCorrections(trackParam);
     162          16 :     AliMUONTrackExtrap::ExtrapToZCov(&trackParam, AliMUONConstants::DefaultChamberZ(kFirstTrigCh)); // extrap to 1st trigger chamber
     163             : 
     164          16 :     AliMUONTriggerTrack *matchedTriggerTrack = MatchTriggerTrack(track, trackParam, triggerTrackStore, triggerStore);
     165          28 :     if ( matchedTriggerTrack ) track->SetHitsPatternInTrigCh(matchedTriggerTrack->GetHitsPatternInTrigCh());
     166             : 
     167          16 :     UInt_t pattern = GetHitPattern(trackParam, kFALSE);
     168          16 :     track->SetHitsPatternInTrigChTrk(pattern);
     169          80 :     AliDebug(1, Form("Hit pattern (MTK): hits 0x%x  slat %2i  board %3i  effFlag %i",
     170             :                      pattern & 0xFF, AliESDMuonTrack::GetSlatOrInfo(pattern), AliESDMuonTrack::GetCrossedBoard(pattern), AliESDMuonTrack::GetEffFlag(pattern)));
     171          16 :   }
     172           8 : }
     173             : 
     174             : 
     175             : //______________________________________________________________________________
     176             : Bool_t AliMUONTrackHitPattern::FindMatchingPads(const AliMUONTrackParam* trackParam,
     177             :                                                 TArrayI& matchedDetElemId, TObjArray& pads,
     178             :                                                 const AliMUONVDigitStore& digitStore,
     179             :                                                 Bool_t isTriggerTrack) const
     180             : {
     181             :   //
     182             :   /// Search for matching digits in trigger chamber
     183             :   //
     184             :   enum {kBending, kNonBending};
     185             :   
     186         240 :   Double_t minMatchDist[2];
     187         240 :   Int_t padsInCheckArea[2];
     188             :   
     189         240 :   AliMUONTrackParam trackParamAtPadZ(*trackParam);
     190             :   
     191         480 :   Int_t inputDetElemId = matchedDetElemId[0];
     192             :   
     193        1440 :   for(Int_t cath=0; cath<2; cath++){
     194         480 :     minMatchDist[cath] = 99999.;
     195         480 :     padsInCheckArea[cath] = 0;
     196             :   }
     197             :   
     198         240 :   Int_t iChamber = AliMpDEManager::GetChamberId(inputDetElemId);  
     199         240 :   Int_t iSlat = inputDetElemId%100;
     200             :   
     201         480 :   TIter next(digitStore.CreateTriggerIterator());
     202             :   AliMUONVDigit* mDigit;
     203             :   
     204         240 :   Double_t xPad = 0., yPad = 0., zPad = 0.;
     205             :   Double_t sigmaX = 0., sigmaY = 0.;
     206             :   
     207         720 :   Double_t nSigmas = ( isTriggerTrack ) ? GetRecoParam()->GetStripCutForTrigger() : GetRecoParam()->GetSigmaCutForTrigger();
     208             :   Bool_t goodForEff = kTRUE;
     209             :   
     210        7136 :   while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) )
     211             :   {
     212        3208 :     Int_t currDetElemId = mDigit->DetElemId();
     213        3208 :     Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId);
     214        5614 :     if ( currCh != iChamber ) continue;
     215         802 :     Int_t currSlat = currDetElemId%100;
     216         802 :     Int_t slatDiff = TMath::Abs(currSlat-iSlat);
     217        1006 :     if ( slatDiff>1 && slatDiff<17 ) continue; // Check neighbour slats
     218             :     
     219         598 :     Int_t cathode = mDigit->Cathode();
     220         598 :     Int_t ix = mDigit->PadX();
     221         598 :     Int_t iy = mDigit->PadY();
     222        1196 :     const AliMpVSegmentation* seg = AliMpSegmentation::Instance()
     223         598 :     ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode));
     224         598 :     AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE);
     225             :     
     226             :     // Get local pad coordinates
     227         598 :     Double_t xPadLocal = pad.GetPositionX();
     228         598 :     Double_t yPadLocal = pad.GetPositionY();
     229         598 :     Double_t dpx = pad.GetDimensionX();
     230         598 :     Double_t dpy = pad.GetDimensionY();
     231         598 :     Double_t xWidth = 2. * dpx;
     232         598 :     Double_t yWidth = 2. * dpy;
     233             :     
     234             :     // Get global pad coordinates
     235         598 :     fkTransformer.Local2Global(currDetElemId, xPadLocal, yPadLocal, 0., xPad, yPad, zPad);
     236             :     
     237             :     // Get track parameters at pad z
     238         908 :     if ( trackParamAtPadZ.CovariancesExist() ) AliMUONTrackExtrap::LinearExtrapToZCov(&trackParamAtPadZ, zPad);
     239         288 :     else AliMUONTrackExtrap::LinearExtrapToZ(&trackParamAtPadZ, zPad);
     240             :     
     241        1196 :     Double_t deltaX = TMath::Abs(xPad-trackParamAtPadZ.GetNonBendingCoor()) - dpx;
     242        1196 :     Double_t deltaY = TMath::Abs(yPad-trackParamAtPadZ.GetBendingCoor()) - dpy;
     243             :     
     244             :     
     245             :     // Get sigmas
     246         598 :     if ( isTriggerTrack ) {
     247         288 :       Double_t checkWidth = TMath::Min(xWidth, yWidth);
     248         288 :       Double_t maxCheckArea = GetRecoParam()->GetMaxStripAreaForTrigger() * checkWidth;
     249         288 :       Double_t sigma = TMath::Max(checkWidth, 2.);
     250             :       sigmaX = sigma; // in cm
     251             :       sigmaY = sigma; // in cm
     252         492 :       if ( deltaX <= maxCheckArea && deltaY <= maxCheckArea ) {
     253         166 :         padsInCheckArea[cathode]++;
     254         166 :         if ( padsInCheckArea[cathode] > 2 ) {
     255             :           goodForEff = kFALSE;
     256          50 :           AliDebug(2, Form("padsInCheckArea[%i] = %i\n",cathode,padsInCheckArea[cathode]));
     257             :         }
     258             :       }
     259         288 :     }
     260             :     else {
     261         310 :       const TMatrixD& kCovParam = trackParamAtPadZ.GetCovariances();
     262         620 :       sigmaX = TMath::Sqrt(kCovParam(0,0)); // in cm
     263         620 :       sigmaY = TMath::Sqrt(kCovParam(2,2)); // in cm
     264             :     }
     265             :     
     266        2990 :     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",
     267             :                       currDetElemId,cathode,dpx,dpy,ix,iy,xPad,yPad,trackParamAtPadZ.GetNonBendingCoor(),trackParamAtPadZ.GetBendingCoor(),deltaX,deltaY,sigmaX,sigmaY,trackParamAtPadZ.P()));
     268             :     //if ( deltaX <= maxCheckArea && deltaY <= maxCheckArea ) padsInCheckArea[cathode]++;
     269        1288 :     if ( deltaX > nSigmas * sigmaX || deltaY > nSigmas * sigmaY ) continue;
     270         342 :     Double_t matchDist = TMath::Max(deltaX, deltaY);
     271         391 :     if ( matchDist > minMatchDist[cathode] ) continue;
     272         745 :     if ( pads.At(cathode) ) delete pads.RemoveAt(cathode);
     273         586 :     pads.AddAt((AliMpPad*)pad.Clone(),cathode);
     274         293 :     minMatchDist[cathode] = matchDist;
     275         586 :     matchedDetElemId[cathode] = currDetElemId; // Set the input detection element id to the matched one
     276         891 :   } // loop on digits
     277             :   
     278             : //  // If track matches many pads, it is not good for effciency determination.
     279             : //  // However we still want to calculate the hit pattern.
     280             : //  for ( Int_t cath=0; cath<2; cath++ ){
     281             : //    if ( padsInCheckArea[cath] > 2 ) {
     282             : //      AliDebug(2, Form("padsInCheckArea[%i] = %i\n",cath,padsInCheckArea[cath]));
     283             : //      return kFALSE;
     284             : //    }
     285             : //  }
     286             :   
     287         240 :   return goodForEff;
     288         240 : }
     289             : 
     290             : 
     291             : //_____________________________________________________________________________
     292             : UInt_t AliMUONTrackHitPattern::GetHitPattern(const AliMUONTrackParam& trackParam, Bool_t isTriggerTrack) const
     293             : {
     294             :   //
     295             :   /// Searches for matching digits around the track.
     296             :   //
     297             :   
     298          30 :   AliCodeTimerAuto("",0);
     299             :   
     300          30 :   TArrayI digitPerTrack(2);
     301          30 :   digitPerTrack.Reset();
     302             :   
     303          30 :   UInt_t pattern = 0;
     304             :   
     305         150 :   TObjArray trackParamList, matchedPads(2), maskedPads(2), padsFromPos(4), validPads(2);
     306         120 :   trackParamList.SetOwner(); matchedPads.SetOwner(); maskedPads.SetOwner(); padsFromPos.SetOwner();
     307             :   
     308             :   Int_t firstSlat = -1, firstBoard = -1;
     309             :   AliESDMuonTrack::EAliTriggerChPatternFlag goodForEff = AliESDMuonTrack::kBoardEff;
     310         120 :   TArrayI matchedDetElemId(2), maskedDetElemId(2), detElemIdFromTrack(2), validDetElemId(2);
     311             :   
     312         450 :   for(Int_t ich=0; ich<AliMUONConstants::NTriggerCh(); ich++) { // chamber loop
     313             :     
     314         600 :     trackParamList.Delete(); matchedPads.Delete(); maskedPads.Delete(); padsFromPos.Delete(); validPads.Clear();
     315             :     
     316         120 :     Int_t nFound = GetTrackParamAtChamber(trackParam, 11+ich, trackParamList, detElemIdFromTrack, padsFromPos);
     317         120 :     if ( nFound == 0 ) {
     318             :       // track is rejected since the extrapolated track
     319             :       // does not match a slat (border effects)
     320           0 :       AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackOutsideGeometry);
     321             :       goodForEff = AliESDMuonTrack::kNoEff;
     322           0 :       AliDebug(2, "Warning: trigger track outside trigger chamber\n");
     323           0 :       continue;
     324             :     }
     325             :     
     326             :     // Search for masked pads
     327         240 :     maskedDetElemId.Reset(detElemIdFromTrack[0]);
     328         240 :     FindMatchingPads((AliMUONTrackParam*)trackParamList.At(0), maskedDetElemId, maskedPads, *(fkTriggerUtilities->GetMaskedDigits()), isTriggerTrack);
     329         240 :     if ( maskedPads.GetEntries() > 0 ) {
     330           0 :       AliESDMuonTrack::AddEffInfo(pattern,AliESDMuonTrack::kTrackMatchesMasks); // pad is masked
     331             :       goodForEff = AliESDMuonTrack::kNoEff;
     332           0 :       for ( Int_t icath=0; icath<2; icath++ ) {
     333           0 :         AliMpPad* currPad = (AliMpPad*)maskedPads.UncheckedAt(icath);
     334           0 :         if ( ! currPad ) continue;
     335           0 :         AliDebug(2,Form("DetElemId %i  cath %i  board %i  strip %i is masked: effFlag 0", matchedDetElemId[icath], icath, currPad->GetLocalBoardId(0), currPad->GetLocalBoardChannel(0)));
     336           0 :       }
     337             :       //      continue;
     338             :       // We want to calculate the hit pattern in any case, so we do not "continue"
     339             :       // However we set the flag in such a way not to use the track for efficiency calculations
     340           0 :     }
     341             :     
     342             :     // If no masked pads matched, search for active pads
     343         240 :     matchedDetElemId.Reset(detElemIdFromTrack[0]);
     344         360 :     if ( ! FindMatchingPads((AliMUONTrackParam*)trackParamList.At(0), matchedDetElemId, matchedPads, fkDigitStore, isTriggerTrack) ) {
     345             :       // if ! FindPadMatchingTrig => too many digits matching pad =>
     346             :       //                          => Event not clear => Do not use for efficiency calculation
     347           2 :       AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesManyPads);
     348             :       goodForEff = AliESDMuonTrack::kNoEff;
     349          10 :       AliDebug(2, Form("Warning: track in %i matches many pads. Rejected!\n", matchedDetElemId[0]));
     350             :     }
     351             :     
     352             :     Int_t nMatched = 0;
     353             :     
     354         240 :     Int_t mostProbDEmatched = detElemIdFromTrack[0];
     355         720 :     for ( Int_t icath=0; icath<2; icath++ ) {
     356         240 :       if ( matchedPads.UncheckedAt(icath) ) {
     357         240 :         nMatched++;
     358             :         // Fill pattern anyway
     359         240 :         AliESDMuonTrack::SetFiredChamber(pattern, icath, ich);
     360         480 :         digitPerTrack[icath]++;
     361         480 :         mostProbDEmatched = matchedDetElemId[icath];
     362         240 :       }
     363             :     }
     364             :     Int_t mostProbDEindex = 0;
     365         240 :     for ( Int_t ifound=0; ifound<nFound; ifound++ ) {
     366         240 :       if ( detElemIdFromTrack[ifound] == mostProbDEmatched ) {
     367             :         mostProbDEindex = ifound;
     368         120 :         break;
     369             :       }
     370             :     }
     371             :     
     372         124 :     if ( goodForEff == AliESDMuonTrack::kNoEff ) continue;
     373             :     
     374         696 :     for ( Int_t icath=0; icath<2; icath++ ) {
     375         232 :       if ( matchedPads.UncheckedAt(icath) ) {
     376         232 :         validPads.AddAt(matchedPads.UncheckedAt(icath),icath);
     377         696 :         validDetElemId[icath] = matchedDetElemId[icath];
     378         232 :       }
     379             :       else {
     380           0 :         validPads.AddAt(padsFromPos.UncheckedAt(2*mostProbDEindex + icath),icath);
     381           0 :         validDetElemId[icath] = detElemIdFromTrack[mostProbDEindex];
     382             :       }
     383             :     }
     384             :         
     385         116 :     Int_t currSlat = mostProbDEmatched%100;
     386         146 :     if ( firstSlat < 0 ) firstSlat = currSlat;
     387             :     
     388         464 :     if ( currSlat != firstSlat || validDetElemId[0] != validDetElemId[1] ) {
     389             :       goodForEff = AliESDMuonTrack::kChEff;
     390             :       firstSlat = AliESDMuonTrack::kCrossDifferentSlats;
     391           0 :     }
     392             :     
     393         176 :     if ( firstBoard < 0 ) firstBoard = ((AliMpPad*)validPads.UncheckedAt(0))->GetLocalBoardId(0);
     394             :     
     395         696 :     for ( Int_t icath=0; icath<2; icath++ ){      
     396             :       
     397         232 :       if ( goodForEff == AliESDMuonTrack::kBoardEff) {
     398             :         Bool_t atLeastOneLoc = kFALSE;
     399         182 :         AliMpPad* currPad = (AliMpPad*)validPads.UncheckedAt(icath);
     400         710 :         for ( Int_t iloc=0; iloc<currPad->GetNofLocations(); iloc++) {
     401         436 :           if ( currPad->GetLocalBoardId(iloc) == firstBoard ) {
     402             :             atLeastOneLoc = kTRUE;
     403         168 :             break;
     404             :           }
     405             :         } // loop on locations
     406         196 :         if ( ! atLeastOneLoc ) goodForEff = AliESDMuonTrack::kSlatEff;
     407         182 :       }
     408             :     } // loop on cathodes
     409             :     //    } // if track good for efficiency
     410         116 :   } // end chamber loop
     411             :   
     412          32 :   if ( goodForEff == AliESDMuonTrack::kNoEff ) return pattern;
     413             :   
     414         168 :   for(Int_t cath=0; cath<2; cath++){
     415         112 :     if(digitPerTrack[cath]<3) {
     416             :       // track is rejected since the number of associated
     417             :       // digits found is less than 3.
     418           0 :       AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesFewPads);
     419             :       goodForEff = AliESDMuonTrack::kNoEff;
     420           0 :       AliDebug(2, Form("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath));
     421             :     }
     422             :   } // loop on cathodes 
     423             :   
     424          28 :   if ( goodForEff == AliESDMuonTrack::kNoEff ) return pattern;
     425             :   
     426          28 :   AliESDMuonTrack::AddEffInfo(pattern, firstSlat, firstBoard, goodForEff);
     427          28 :   return pattern;
     428          30 : }
     429             : 
     430             : 
     431             : 
     432             : //_____________________________________________________________________________
     433             : Int_t AliMUONTrackHitPattern::GetTrackParamAtChamber(const AliMUONTrackParam& inputTrackParam, Int_t chamber,
     434             :                                                      TObjArray& trackParamList, TArrayI& foundDetElemId,
     435             :                                                      TObjArray& padsFromPos) const
     436             : {
     437             :   //
     438             :   /// Return the extrapolated the track parameter at the given chamber
     439             :   /// and returns the matching DetElemId
     440             :   /// CAVEAT: at the border the result is not univoque
     441             :   //
     442             :   
     443             :   Int_t nFound = 0;
     444         240 :   foundDetElemId[0] = foundDetElemId[1] = 0;
     445         120 :   AliMUONTrackParam trackParamCopy(inputTrackParam);
     446         360 :   TVector3 globalPoint1(trackParamCopy.GetNonBendingCoor(), trackParamCopy.GetBendingCoor(), trackParamCopy.GetZ());
     447         120 :   AliMUONTrackExtrap::LinearExtrapToZ(&trackParamCopy, trackParamCopy.GetZ() + 20.);
     448         360 :   TVector3 globalPoint2(trackParamCopy.GetNonBendingCoor(), trackParamCopy.GetBendingCoor(), trackParamCopy.GetZ());
     449         120 :   TVector3 localCoor;
     450             :   
     451             :   //  AliMpArea pointArea(x, y, 2.*AliMpConstants::LengthTolerance(), 2.*AliMpConstants::LengthTolerance());
     452         120 :   AliMpDEIterator it;
     453         120 :   Double_t xGlobal, yGlobal, zGlobal;
     454        3438 :   for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){
     455        1136 :     Int_t detElemId = it.CurrentDEId();
     456        1136 :     PosInDetElemIdLocal(localCoor, globalPoint1, globalPoint2, detElemId);
     457        1136 :     fkTransformer.Local2Global(detElemId, localCoor.X(), localCoor.Y(), localCoor.Z(), xGlobal, yGlobal, zGlobal);
     458        1136 :     AliMpArea pointArea(xGlobal, yGlobal, 2.*AliMpConstants::LengthTolerance(), 2.*AliMpConstants::LengthTolerance());
     459        1136 :     AliMpArea* deArea = fkTransformer.GetDEArea(detElemId);
     460        2272 :     if ( deArea->Contains(pointArea) ) {
     461             :       // Check if track matches valid pads
     462             :       // (this is not trivial for cut RPC)
     463             :       Int_t validPads = 0;
     464         720 :       for ( Int_t icath=0; icath<2; icath++ ) {
     465             :         const AliMpVSegmentation* seg = 
     466         480 :         AliMpSegmentation::Instance()
     467         240 :         ->GetMpSegmentation(detElemId,AliMp::GetCathodType(icath));
     468         240 :         AliMpPad pad = seg->PadByPosition(localCoor.X(),localCoor.Y(),kFALSE);
     469         240 :         if ( pad.IsValid() ) {
     470         480 :           padsFromPos.AddAt(pad.Clone(), 2*nFound + icath);
     471         240 :           validPads++;
     472         240 :         }
     473         240 :       }
     474         120 :       if ( validPads < 2 ) continue;
     475         240 :       AliMUONTrackParam* extrapTrackParam = new AliMUONTrackParam(inputTrackParam);
     476         184 :       if ( extrapTrackParam->CovariancesExist() ) AliMUONTrackExtrap::LinearExtrapToZCov(extrapTrackParam, zGlobal);
     477          56 :       else AliMUONTrackExtrap::LinearExtrapToZ(extrapTrackParam, zGlobal);
     478         120 :       trackParamList.AddAt(extrapTrackParam,nFound);
     479         240 :       foundDetElemId[nFound] = detElemId;
     480         120 :       nFound++;
     481         120 :       if ( nFound == 2 ) break;
     482         120 :     }
     483        1126 :     else if ( nFound > 0 ) break;
     484        2162 :   } // loop on detElemId
     485             :   
     486             :   return nFound;
     487         120 : }
     488             : 
     489             : 
     490             : //______________________________________________________________________________
     491             : AliMUONTriggerTrack * 
     492             : AliMUONTrackHitPattern::MatchTriggerTrack(AliMUONTrack* track,
     493             :                                           AliMUONTrackParam& trackParam,
     494             :                                           const AliMUONVTriggerTrackStore& triggerTrackStore,
     495             :                                           const AliMUONVTriggerStore& triggerStore) const
     496             : {
     497             :   //
     498             :   /// Match track with trigger track
     499             :   //
     500             : 
     501             :   Int_t matchTrigger = 0;
     502             :   Int_t loTrgNum(-1);
     503          32 :   TMatrixD paramDiff(3,1);
     504             :   Double_t chi2;
     505             :   Double_t chi2MatchTrigger = 0., minChi2MatchTrigger = 999.;
     506             :   Int_t doubleMatch = -1; // Check if track matches 2 trigger tracks
     507             :   Double_t doubleChi2 = -1.;
     508             :   AliMUONTriggerTrack* doubleTriggerTrack = 0x0;
     509             :   AliMUONTriggerTrack* matchedTriggerTrack = 0x0;
     510             :     
     511             : 
     512             :   // Covariance matrix 3x3 (X,Y,slopeY) for trigger tracks
     513          16 :   TMatrixD trackCov(3,3);
     514             : 
     515             :   AliMUONTriggerTrack *triggerTrack;
     516          32 :   TIter itTriggerTrack(triggerTrackStore.CreateIterator());
     517         116 :   while ( ( triggerTrack = static_cast<AliMUONTriggerTrack*>(itTriggerTrack() ) ) )
     518             :   {
     519          28 :     AliMUONTrackExtrap::LinearExtrapToZCov(&trackParam, triggerTrack->GetZ11());
     520          28 :     const TMatrixD& kParamCov = trackParam.GetCovariances();
     521             :     
     522          28 :     Double_t xTrack = trackParam.GetNonBendingCoor();
     523          28 :     Double_t yTrack = trackParam.GetBendingCoor();
     524          28 :     Double_t ySlopeTrack = trackParam.GetBendingSlope();
     525             : 
     526          56 :     paramDiff(0,0) = triggerTrack->GetX11() - xTrack;
     527          56 :     paramDiff(1,0) = triggerTrack->GetY11() - yTrack;
     528          56 :     paramDiff(2,0) = triggerTrack->GetSlopeY() - ySlopeTrack;
     529             : 
     530             :     // Covariance matrix 3x3 (X,Y,slopeY) for tracker tracks
     531          28 :     trackCov.Zero();
     532          84 :     trackCov(0,0) = kParamCov(0,0);
     533          84 :     trackCov(1,1) = kParamCov(2,2);
     534          84 :     trackCov(2,2) = kParamCov(3,3);
     535          84 :     trackCov(1,2) = kParamCov(2,3);
     536          84 :     trackCov(2,1) = kParamCov(3,2);
     537             : 
     538             :     // Covariance matrix 3x3 (X,Y,slopeY) for trigger tracks
     539          56 :     TMatrixD trigCov(triggerTrack->GetCovariances());
     540             : 
     541          28 :     TMatrixD sumCov(trackCov,TMatrixD::kPlus,trigCov);
     542          56 :     if (sumCov.Determinant() != 0) {
     543          28 :       sumCov.Invert();
     544             :       
     545          28 :       TMatrixD tmp(sumCov,TMatrixD::kMult,paramDiff);
     546          28 :       TMatrixD chi2M(paramDiff,TMatrixD::kTransposeMult,tmp);
     547          56 :       chi2 = chi2M(0,0);      
     548          28 :     } else {
     549           0 :       AliWarning(" Determinant = 0");
     550             :       Double_t sigma2 = 0.;
     551             :       chi2 = 0.;
     552           0 :       for (Int_t iVar = 0; iVar < 3; iVar++) {
     553           0 :         sigma2 = trackCov(iVar,iVar) + trigCov(iVar,iVar);
     554           0 :         chi2 += paramDiff(iVar,0) * paramDiff(iVar,0) / sigma2;
     555             :       }
     556             :     }
     557             : 
     558          28 :     chi2 /= 3.; // Normalized Chi2: 3 degrees of freedom (X,Y,slopeY)
     559          28 :     if (chi2 < GetRecoParam()->GetMaxNormChi2MatchTrigger()) 
     560             :     {
     561          14 :       Bool_t isDoubleTrack = (TMath::Abs(chi2 - minChi2MatchTrigger)<1.);
     562          26 :       if (chi2 < minChi2MatchTrigger && chi2 < GetRecoParam()->GetMaxNormChi2MatchTrigger()) 
     563             :       {
     564          12 :         if(isDoubleTrack)
     565             :         {
     566             :           doubleMatch = loTrgNum;
     567             :           doubleChi2 = chi2MatchTrigger;
     568             :           doubleTriggerTrack = matchedTriggerTrack;
     569           0 :         }
     570             :         minChi2MatchTrigger = chi2;
     571             :         chi2MatchTrigger = chi2;
     572          12 :         loTrgNum = triggerTrack->GetLoTrgNum();
     573             :         matchedTriggerTrack = triggerTrack;
     574          12 :         AliMUONLocalTrigger* locTrg = triggerStore.FindLocal(loTrgNum);
     575             :         matchTrigger = 1;
     576          24 :         if(locTrg->LoLpt()>0) matchTrigger = 2;
     577          24 :         if(locTrg->LoHpt()>0) matchTrigger = 3;
     578          12 :       }
     579           2 :       else if(isDoubleTrack) 
     580             :       {
     581           0 :         doubleMatch = triggerTrack->GetLoTrgNum();
     582             :         doubleChi2 = chi2;
     583           0 :       }
     584          14 :     }
     585          28 :   }
     586          16 :   if(doubleMatch>=0)
     587             :   { // If two trigger tracks match, select the one passing more trigger cuts
     588           0 :     AliDebug(1, Form("Two candidates found: %i and %i",loTrgNum,doubleMatch));
     589           0 :     AliMUONLocalTrigger* locTrg1 = triggerStore.FindLocal(doubleMatch);
     590           0 :     if((locTrg1->LoLpt()>0 && matchTrigger<2) || (locTrg1->LoHpt() && matchTrigger<3))
     591             :     {
     592           0 :       if(locTrg1->LoHpt()>0) matchTrigger=3;
     593             :       else matchTrigger = 2;
     594             :       loTrgNum = doubleMatch;
     595             :       chi2MatchTrigger = doubleChi2;
     596             :       matchedTriggerTrack = doubleTriggerTrack;
     597           0 :     }
     598           0 :   }
     599             :     
     600          16 :   track->SetMatchTrigger(matchTrigger);
     601          16 :   track->SetChi2MatchTrigger(chi2MatchTrigger);
     602             : 
     603          16 :   AliMUONLocalTrigger* locTrg = static_cast<AliMUONLocalTrigger*>(triggerStore.FindLocal(loTrgNum));
     604             : 
     605          16 :   if (locTrg)
     606             :   {    
     607          24 :     track->SetLocalTrigger(locTrg->LoCircuit(),
     608          12 :                            locTrg->LoStripX(),
     609          12 :                            locTrg->LoStripY(),
     610          12 :                            locTrg->GetDeviation(),
     611          12 :                            locTrg->LoLpt(),
     612          12 :                            locTrg->LoHpt(),
     613          12 :                            locTrg->GetTriggerWithoutChamber());
     614             :   }
     615             : 
     616             :   return matchedTriggerTrack;
     617          16 : }
     618             : 
     619             : 
     620             : //_____________________________________________________________________________
     621             : Bool_t AliMUONTrackHitPattern::PosInDetElemIdLocal(TVector3& localCoor, const TVector3& globalPoint1,
     622             :                                                    const TVector3& globalPoint2, Int_t detElemId) const
     623             : {
     624             :   /// Given two points belonging to a line (global coordinates)
     625             :   /// it returns the intersection point with the detElemId (local coordinates)
     626             :   
     627        2272 :   Double_t xloc, yloc, zloc;
     628        1136 :   fkTransformer.Global2Local(detElemId, globalPoint1.X(), globalPoint1.Y(), globalPoint1.Z(), xloc, yloc, zloc);
     629        1136 :   TVector3 localPoint1(xloc, yloc, zloc);
     630        1136 :   fkTransformer.Global2Local(detElemId, globalPoint2.X(), globalPoint2.Y(), globalPoint2.Z(), xloc, yloc, zloc);
     631        1136 :   TVector3 localPoint2(xloc, yloc, zloc);
     632        4544 :   localCoor = localPoint1 - ( localPoint1.Z() / ( localPoint2.Z() - localPoint1.Z() ) ) * ( localPoint2 - localPoint1 );
     633             :   
     634             :   return kTRUE;
     635        1136 : }
     636             : 
     637             : 
     638             : // THE FOLLOWING METHODS ARE OBSOLETE
     639             : 
     640             : //______________________________________________________________________________
     641             : UInt_t AliMUONTrackHitPattern::GetHitPattern(const AliMUONTriggerTrack* matchedTriggerTrack) const
     642             : {
     643             :   //
     644             :   /// Get hit pattern on trigger chambers for the current trigger track
     645             :   //
     646           0 :   UInt_t pattern = 0;
     647           0 :   PerformTrigTrackMatch(pattern, matchedTriggerTrack);
     648           0 :   return pattern;
     649           0 : }
     650             : 
     651             : 
     652             : //______________________________________________________________________________
     653             : UInt_t AliMUONTrackHitPattern::GetHitPattern(AliMUONTrackParam* trackParam) const
     654             : {
     655             :   //
     656             :   /// Get hit pattern on trigger chambers for the current tracker track
     657             :   //
     658           0 :   UInt_t pattern = 0;
     659           0 :   Bool_t isMatch[2];
     660           0 :   const Int_t kNTrackingCh = AliMUONConstants::NTrackingCh();
     661             :   
     662           0 :   for(Int_t ch=0; ch<4; ++ch)
     663             :   {
     664           0 :     Int_t iChamber = kNTrackingCh+ch;
     665           0 :     AliMUONTrackExtrap::ExtrapToZCov(trackParam, AliMUONConstants::DefaultChamberZ(iChamber));
     666           0 :     FindPadMatchingTrack(*trackParam, isMatch, iChamber);
     667           0 :     for(Int_t cath=0; cath<2; ++cath)
     668             :     {
     669           0 :       if(isMatch[cath]) AliESDMuonTrack::SetFiredChamber(pattern, cath, ch);
     670             :     }
     671             :   }
     672             :   
     673             :   // pattern obtained by propagation of tracker track
     674             :   // when it does not match the trigger.
     675           0 :   AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackerTrackPattern);
     676             :   
     677           0 :   return pattern;
     678           0 : }
     679             : 
     680             : 
     681             : //______________________________________________________________________________
     682             : void 
     683             : AliMUONTrackHitPattern::FindPadMatchingTrack(const AliMUONTrackParam& trackParam,
     684             :                                              Bool_t isMatch[2], Int_t iChamber) const
     685             : {
     686             :     //
     687             :     /// Given the tracker track position, searches for matching digits.
     688             :     //
     689             : 
     690           0 :     Float_t minMatchDist[2];
     691             : 
     692           0 :     for(Int_t cath=0; cath<2; ++cath)
     693             :     {
     694           0 :       isMatch[cath]=kFALSE;
     695           0 :       minMatchDist[cath]=fkMaxDistance/10.;
     696             :     }
     697             : 
     698           0 :     TIter next(fkDigitStore.CreateTriggerIterator());
     699             :     AliMUONVDigit* mDigit;
     700             : 
     701           0 :     while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) )
     702             :     {
     703           0 :       Int_t currDetElemId = mDigit->DetElemId();
     704           0 :       Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId);
     705           0 :       if(currCh!=iChamber) continue;
     706           0 :       Int_t cathode = mDigit->Cathode();
     707           0 :       Int_t ix = mDigit->PadX();
     708           0 :       Int_t iy = mDigit->PadY();
     709           0 :       Float_t xpad, ypad, zpad;
     710           0 :       const AliMpVSegmentation* seg = AliMpSegmentation::Instance()
     711           0 :         ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode));
     712             :       
     713           0 :       AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE);
     714           0 :       Float_t xlocal1 = pad.GetPositionX();
     715           0 :       Float_t ylocal1 = pad.GetPositionY();
     716           0 :       Float_t dpx = pad.GetDimensionX();
     717           0 :       Float_t dpy = pad.GetDimensionY();
     718             : 
     719           0 :       fkTransformer.Local2Global(currDetElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad);
     720           0 :       Float_t matchDist = MinDistanceFromPad(xpad, ypad, zpad, dpx, dpy, trackParam);
     721           0 :       if(matchDist>minMatchDist[cathode])continue;
     722           0 :       isMatch[cathode] = kTRUE;
     723           0 :       if(isMatch[0] && isMatch[1]) break;
     724           0 :       minMatchDist[cathode] = matchDist;
     725           0 :     }
     726           0 : }
     727             : 
     728             : 
     729             : //______________________________________________________________________________
     730             : Float_t 
     731             : AliMUONTrackHitPattern::MinDistanceFromPad(Float_t xPad, Float_t yPad, Float_t zPad,
     732             :                                            Float_t dpx, Float_t dpy, 
     733             :                                            const AliMUONTrackParam& trackParam) const
     734             : {
     735             :     //
     736             :     /// Decides if the digit belongs to the tracker track.
     737             :     //
     738             : 
     739           0 :     AliMUONTrackParam trackParamAtPadZ(trackParam);
     740           0 :     AliMUONTrackExtrap::LinearExtrapToZCov(&trackParamAtPadZ, zPad);
     741             : 
     742           0 :     Float_t xTrackAtPad = trackParamAtPadZ.GetNonBendingCoor();
     743           0 :     Float_t yTrackAtPad = trackParamAtPadZ.GetBendingCoor();
     744             : 
     745           0 :     const Float_t kNSigma = GetRecoParam()->GetSigmaCutForTrigger();
     746             : 
     747           0 :     const TMatrixD& kCovParam = trackParamAtPadZ.GetCovariances();
     748             :     
     749           0 :     Float_t sigmaX = TMath::Sqrt(kCovParam(0,0));
     750           0 :     Float_t sigmaY = TMath::Sqrt(kCovParam(2,2));
     751             : 
     752           0 :     Float_t maxDistX = kNSigma * sigmaX; // in cm
     753           0 :     Float_t maxDistY = kNSigma * sigmaY; // in cm
     754             : 
     755           0 :     Float_t deltaX = TMath::Abs(xPad-xTrackAtPad)-dpx;
     756           0 :     Float_t deltaY = TMath::Abs(yPad-yTrackAtPad)-dpy;
     757             : 
     758           0 :     Float_t matchDist = fkMaxDistance;
     759           0 :     if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY);
     760             : 
     761             :     return matchDist;
     762           0 : }
     763             : 
     764             : 
     765             : //_____________________________________________________________________________
     766             : Bool_t AliMUONTrackHitPattern::FindPadMatchingTrig(const TVector3& vec11, const TVector3& vec21,
     767             :                                                   Int_t matchedDetElemId[2], TObjArray& pads) const
     768             : {
     769             :   //
     770             :   /// Check slat and board number of digit matching trigger track
     771             :   //
     772             :   
     773             :   enum {kBending, kNonBending};
     774             :   
     775           0 :   Float_t minMatchDist[2];
     776           0 :   Int_t padsInCheckArea[2];
     777             :   
     778           0 :   Int_t inputDetElemId = matchedDetElemId[0];
     779             :   
     780           0 :   for(Int_t cath=0; cath<2; cath++){
     781           0 :     minMatchDist[cath] = fkMaxDistance/10.;
     782           0 :     padsInCheckArea[cath] = 0;
     783             :   }
     784             :   
     785           0 :   Int_t iChamber = AliMpDEManager::GetChamberId(inputDetElemId);  
     786           0 :   Int_t iSlat = inputDetElemId%100;
     787             :   
     788           0 :   TIter next(fkDigitStore.CreateTriggerIterator());
     789             :   AliMUONVDigit* mDigit;
     790           0 :   TVector3 localExtrap;
     791             :   
     792             :   Int_t previousDetElemId = -1;
     793             :   
     794           0 :   while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) )
     795             :   {
     796           0 :     Int_t currDetElemId = mDigit->DetElemId();
     797           0 :     Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId);
     798           0 :     if ( currCh != iChamber ) continue;
     799           0 :     Int_t currSlat = currDetElemId%100;
     800           0 :     Int_t slatDiff = TMath::Abs(currSlat-iSlat);
     801           0 :     if ( slatDiff>1 && slatDiff<17 ) continue; // Check neighbour slats
     802           0 :     Int_t cathode = mDigit->Cathode();
     803           0 :     Int_t ix = mDigit->PadX();
     804           0 :     Int_t iy = mDigit->PadY();
     805           0 :     const AliMpVSegmentation* seg = AliMpSegmentation::Instance()
     806           0 :     ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode));
     807             :     
     808           0 :     AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE);
     809             :     
     810           0 :     if ( currDetElemId != previousDetElemId ) {
     811           0 :       PosInDetElemIdLocal(localExtrap, vec11, vec21, currDetElemId);
     812             :       previousDetElemId = currDetElemId;
     813           0 :     }
     814             :     
     815           0 :     AliDebug(11, Form("\nDetElemId = %i  Cathode = %i  Pad = (%i,%i) = (%.2f,%.2f)  Dim = (%.2f,%.2f)  Track = (%.2f,%.2f)\n",
     816             :                      currDetElemId,cathode,ix,iy,pad.GetPositionX(),pad.GetPositionY(),pad.GetDimensionX(),pad.GetDimensionY(),localExtrap.X(),localExtrap.Y()));
     817           0 :     Float_t matchDist = PadMatchTrack(pad, localExtrap);
     818           0 :     if ( matchDist < fkMaxDistance/2. ) padsInCheckArea[cathode]++;
     819           0 :     if ( matchDist > minMatchDist[cathode] ) continue;
     820           0 :     if ( pads.At(cathode) ) delete pads.RemoveAt(cathode);
     821           0 :     pads.AddAt((AliMpPad*)pad.Clone(),cathode);
     822           0 :     minMatchDist[cathode] = matchDist;
     823           0 :     matchedDetElemId[cathode] = currDetElemId; // Set the input detection element id to the matched one
     824           0 :   } // loop on digits
     825             :   
     826             :   // If track matches many pads, it is not good for effciency determination.
     827             :   // However we still want to calculate the hit pattern.
     828           0 :   for ( Int_t cath=0; cath<2; cath++ ){
     829           0 :     if ( padsInCheckArea[cath] > 2 ) {
     830           0 :       AliDebug(10, Form("padsInCheckArea[%i] = %i\n",cath,padsInCheckArea[cath]));
     831           0 :       return kFALSE;
     832             :     }
     833             :   }
     834             :   
     835           0 :   return kTRUE;
     836           0 : }
     837             : 
     838             : //_____________________________________________________________________________
     839             : Float_t AliMUONTrackHitPattern::PadMatchTrack(const AliMpPad& pad, const TVector3& trackPosAtPad) const
     840             : {
     841             :   //
     842             :   /// Decides if the digit belongs to the trigger track.
     843             :   //
     844             :   
     845           0 :   Float_t xPad = pad.GetPositionX();
     846           0 :   Float_t yPad = pad.GetPositionY();
     847           0 :   Float_t dpx = pad.GetDimensionX();
     848           0 :   Float_t dpy = pad.GetDimensionY();  
     849             :   
     850             : 
     851           0 :   Float_t maxDist = GetRecoParam()->GetStripCutForTrigger() * 2. * TMath::Min(dpx,dpy); // cm
     852           0 :   if ( maxDist<2. ) maxDist = 2.;
     853           0 :   Float_t maxDistCheckArea = GetRecoParam()->GetMaxStripAreaForTrigger() * 2. *  TMath::Min(dpx,dpy); // cm
     854             : 
     855           0 :   Float_t matchDist = fkMaxDistance;
     856             : 
     857           0 :   Float_t deltaX = TMath::Abs(xPad-trackPosAtPad.X())-dpx;
     858           0 :   Float_t deltaY = TMath::Abs(yPad-trackPosAtPad.Y())-dpy;
     859             :   Float_t maxDistX = maxDist;
     860             :   Float_t maxDistY = maxDist;
     861             : 
     862           0 :   if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY);
     863           0 :   else if(deltaX<=maxDistCheckArea && deltaY<=maxDistCheckArea) matchDist = fkMaxDistance/5.;
     864           0 :   return matchDist;
     865             : }
     866             : 
     867             : 
     868             : //_____________________________________________________________________________
     869             : Int_t AliMUONTrackHitPattern::DetElemIdFromPos(Float_t x, Float_t y, 
     870             :                                                Int_t chamber, Int_t foundDetElemId[2]) const
     871             : {
     872             :   //
     873             :   /// Given the (x,y) position in the chamber,
     874             :   /// it returns the corresponding slats
     875             :   /// Caveat: at the border the result is not univoque
     876             :   //
     877             :   
     878             :   Int_t nFound = 0;
     879             :   
     880           0 :   foundDetElemId[0] = foundDetElemId[1] = 0;
     881           0 :   AliMpArea pointArea(x, y, 2.*AliMpConstants::LengthTolerance(), 2.*AliMpConstants::LengthTolerance());
     882           0 :   AliMpDEIterator it;
     883           0 :   for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){
     884           0 :     Int_t detElemId = it.CurrentDEId();
     885           0 :     AliMpArea* deArea = fkTransformer.GetDEArea(detElemId);
     886             :     
     887           0 :     if ( deArea->Contains(pointArea) ) {
     888           0 :       foundDetElemId[nFound++] = detElemId;
     889           0 :       if ( nFound == 2 ) break;
     890             :     }
     891           0 :     else if ( nFound > 0 ) break;
     892           0 :   } // loop on detElemId
     893             :   
     894             :   return nFound;
     895           0 : }
     896             : 
     897             : 
     898             : 
     899             : //_____________________________________________________________________________
     900             : Bool_t AliMUONTrackHitPattern::PadsFromPos(const TVector3& vec11, const TVector3& vec21,
     901             :                                            Int_t detElemId, TObjArray& pads) const
     902             : {
     903             :   //
     904             :   /// Given the (x,y) position in the chamber,
     905             :   /// it returns the corresponding local board
     906             :   //
     907             :   
     908           0 :   pads.Delete();
     909             :   
     910           0 :   TVector3 localCoor;
     911           0 :   PosInDetElemIdLocal(localCoor, vec11, vec21, detElemId);
     912           0 :   for ( Int_t icath=0; icath<2; icath++ ) {
     913             :     const AliMpVSegmentation* seg = 
     914           0 :     AliMpSegmentation::Instance()
     915           0 :     ->GetMpSegmentation(detElemId,AliMp::GetCathodType(icath));
     916           0 :     AliMpPad pad = seg->PadByPosition(localCoor.X(),localCoor.Y(),kFALSE);
     917           0 :     if ( pad.IsValid() ) {
     918           0 :       pads.AddAt(pad.Clone(), icath);
     919             :     }
     920           0 :   }
     921             :   
     922           0 :   return pads.GetEntries();
     923           0 : }
     924             : 
     925             : 
     926             : //_____________________________________________________________________________
     927             : Bool_t AliMUONTrackHitPattern::IsCloseToAccEdge(TObjArray& pads, Int_t detElemId, Float_t coor[2]) const
     928             : {
     929           0 :   AliMpArea* deArea = fkTransformer.GetDEArea(detElemId);
     930           0 :   Float_t dpx = ((AliMpPad*)pads.At(1))->GetDimensionX();
     931           0 :   Float_t dpy = ((AliMpPad*)pads.At(0))->GetDimensionY();
     932           0 :   Float_t resolution[2] = { static_cast<Float_t>(0.75*dpx), static_cast<Float_t>(0.75*dpy) };
     933           0 :   Float_t sign[3] = {0., 1., -1.};
     934           0 :   for ( Int_t ineighx=0; ineighx<3; ineighx++ ) {
     935           0 :     for ( Int_t ineighy=0; ineighy<3; ineighy++ ) {
     936           0 :       AliMpArea pointArea(coor[0]+sign[ineighx]*resolution[0],
     937           0 :                           coor[1]+sign[ineighy]*resolution[1],
     938           0 :                           2.*AliMpConstants::LengthTolerance(),
     939           0 :                           2.*AliMpConstants::LengthTolerance());
     940           0 :       if ( ! deArea->Contains(pointArea) ) return kTRUE;
     941           0 :     } // loop on y neighbours
     942             :   } // loop on x neighbours
     943           0 :   return kFALSE;
     944           0 : }
     945             : 
     946             : 
     947             : //_____________________________________________________________________________
     948             : Bool_t AliMUONTrackHitPattern::IsMasked(const AliMpPad& pad, Int_t detElemId, Int_t cathode, const TVector3& vec11, const TVector3& vec21) const
     949             : {
     950             :   //
     951             :   /// Check if pad or its neighbours are masked
     952             :   //
     953             :   
     954             :   Int_t nMasked = 0;
     955             :   
     956           0 :   if ( fkTriggerUtilities->IsMasked(pad, detElemId, cathode) ) ++nMasked;
     957             :   
     958             :   // Check closest neighbour
     959             :   
     960           0 :   TVector3 localCoor;
     961           0 :   PosInDetElemIdLocal(localCoor, vec11, vec21, detElemId);
     962             :   
     963           0 :   Float_t padPos[2] = { static_cast<Float_t>(pad.GetPositionX()), static_cast<Float_t>(pad.GetPositionY())};
     964           0 :   Float_t padDim[2] = { static_cast<Float_t>(pad.GetDimensionX()), static_cast<Float_t>(pad.GetDimensionY())};
     965           0 :   Float_t inpactPos[2] = { static_cast<Float_t>(localCoor.X()), static_cast<Float_t>(localCoor.Y())};
     966           0 :   Float_t sign[2] = {-1., 1.};
     967           0 :   Int_t icoor = 1-cathode;
     968           0 :   Int_t addSlatSign[3] = {0,1,-1};
     969           0 :   Int_t inputCh = AliMpDEManager::GetChamberId(detElemId)+1;
     970           0 :   Int_t inputSlat = detElemId%100;
     971             :   
     972           0 :   Float_t newPos[2];
     973           0 :   for ( Int_t ineigh=0; ineigh<2; ineigh++ ) {
     974           0 :     newPos[1-icoor] = inpactPos[1-icoor];
     975           0 :     newPos[icoor] = inpactPos[icoor] + 1.05 * sign[ineigh] * padDim[icoor];
     976           0 :     if ( TMath::Abs(newPos[icoor] - padPos[icoor]) < padDim[icoor] ) continue;
     977             :     const AliMpVSegmentation* seg = 
     978           0 :       AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
     979           0 :     AliMpPad neighPad = seg->PadByPosition(newPos[0],newPos[1],kFALSE);
     980           0 :     if ( neighPad.IsValid() ) {
     981           0 :       if ( fkTriggerUtilities->IsMasked(neighPad, detElemId, cathode) ) ++nMasked;
     982             :     }
     983             :     else {
     984           0 :       TVector3 deltaVec(newPos[0]-inpactPos[0],newPos[1]-inpactPos[1],0.);
     985           0 :       TVector3 transVec11 = vec11+deltaVec;
     986           0 :       TVector3 transVec21 = vec21+deltaVec;
     987           0 :       TObjArray padsFromPos;
     988           0 :       padsFromPos.SetOwner();
     989           0 :       for ( Int_t iAddSlat=0; iAddSlat<2; iAddSlat++ ) {
     990           0 :         Int_t currSlat = (inputSlat + addSlatSign[iAddSlat])%18;
     991           0 :         Int_t currDetElemId = 100 * inputCh + currSlat;
     992           0 :         PadsFromPos(transVec11,transVec21,currDetElemId,padsFromPos);
     993           0 :         AliMpPad* currPad = (AliMpPad*)padsFromPos.UncheckedAt(cathode);
     994           0 :         Bool_t isMasked = ( currPad ) ? fkTriggerUtilities->IsMasked(*currPad, currDetElemId, cathode) : kFALSE;
     995           0 :         padsFromPos.Delete();
     996           0 :         if ( isMasked ) ++nMasked;
     997             :       }
     998           0 :     } // loop on slats
     999           0 :   } // loop on neigbours
    1000             :   
    1001           0 :   Double_t maskedProb = ((Double_t)nMasked)/3.;
    1002           0 :   if ( gRandom->Rndm() < maskedProb ) return kTRUE;
    1003             :   
    1004           0 :   return kFALSE;
    1005           0 : }
    1006             : 
    1007             : 
    1008             : //_____________________________________________________________________________
    1009             : Bool_t AliMUONTrackHitPattern::PerformTrigTrackMatch(UInt_t &pattern,
    1010             :                                                      const AliMUONTriggerTrack* matchedTrigTrack) const
    1011             : {
    1012             :   //
    1013             :   /// It searches for matching digits around the trigger track.
    1014             :   //
    1015             :   
    1016           0 :   AliCodeTimerAuto("",0);
    1017             : 
    1018             :   enum {kBending, kNonBending};
    1019             : 
    1020           0 :   TArrayF zMeanChamber(AliMUONConstants::NTriggerCh());
    1021           0 :   zMeanChamber[0] = matchedTrigTrack->GetZ11();
    1022           0 :   zMeanChamber[1] = matchedTrigTrack->GetZ11() + AliMUONConstants::DefaultChamberZ(11) - AliMUONConstants::DefaultChamberZ(10);
    1023           0 :   zMeanChamber[2] = matchedTrigTrack->GetZ21();
    1024           0 :   zMeanChamber[3] = matchedTrigTrack->GetZ21() + AliMUONConstants::DefaultChamberZ(13) - AliMUONConstants::DefaultChamberZ(12);
    1025             : 
    1026           0 :   TArrayI digitPerTrack(2);
    1027           0 :   digitPerTrack.Reset();
    1028             : 
    1029           0 :   Float_t trackIntersectCh[2];
    1030             : 
    1031           0 :   Float_t slopeX = matchedTrigTrack->GetSlopeX();
    1032           0 :   Float_t slopeY = matchedTrigTrack->GetSlopeY();
    1033             :   
    1034           0 :   Float_t z11 = matchedTrigTrack->GetZ11();
    1035           0 :   Float_t x11 = slopeX * z11;
    1036           0 :   Float_t y11 = matchedTrigTrack->GetY11();
    1037           0 :   Float_t z21 =  matchedTrigTrack->GetZ21();
    1038           0 :   Float_t x21 = slopeX * z21;
    1039           0 :   Float_t y21 = y11 + slopeY * (z21-z11);
    1040           0 :   TVector3 vec11(x11, y11, z11), vec21(x21, y21, z21);
    1041             :   
    1042             :   Int_t firstSlat = -1, firstBoard = -1;
    1043             :   AliESDMuonTrack::EAliTriggerChPatternFlag goodForEff = AliESDMuonTrack::kBoardEff;
    1044           0 :   TObjArray matchedPads(2), padsFromPos(2), validPads(2);
    1045           0 :   matchedPads.SetOwner(); padsFromPos.SetOwner();
    1046           0 :   Int_t matchedDetElemId[2], detElemIdFromTrack[2];
    1047             :   
    1048           0 :   for(Int_t ich=0; ich<AliMUONConstants::NTriggerCh(); ich++) { // chamber loop
    1049             :     
    1050             :     // searching track intersection with chambers (first approximation)
    1051           0 :     Float_t deltaZ = zMeanChamber[ich] - zMeanChamber[0];
    1052           0 :     trackIntersectCh[0] = zMeanChamber[ich] * slopeX;
    1053           0 :     trackIntersectCh[1] = y11 + deltaZ * slopeY;
    1054           0 :     Int_t nFound = DetElemIdFromPos(trackIntersectCh[0], trackIntersectCh[1], 11+ich, detElemIdFromTrack);
    1055           0 :     if ( nFound == 0 ) {
    1056             :       // track is rejected since the extrapolated track
    1057             :       // does not match a slat (border effects)
    1058           0 :       AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackOutsideGeometry);
    1059             :       goodForEff = AliESDMuonTrack::kNoEff;
    1060           0 :       AliDebug(10, "Warning: trigger track outside trigger chamber\n");
    1061           0 :       continue;
    1062             :     }
    1063             :     
    1064           0 :     matchedDetElemId[0] = matchedDetElemId[1] = detElemIdFromTrack[0];
    1065             :     
    1066           0 :     if ( ! FindPadMatchingTrig(vec11, vec21, matchedDetElemId, matchedPads) ) {
    1067             :       // if ! FindPadMatchingTrig => too many digits matching pad =>
    1068             :       //                          => Event not clear => Do not use for efficiency calculation
    1069           0 :       AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesManyPads);
    1070             :       goodForEff = AliESDMuonTrack::kNoEff;
    1071           0 :       AliDebug(10, Form("Warning: track = %p (%i) matches many pads. Rejected!\n",(void *)matchedTrigTrack, matchedDetElemId[0]));
    1072             :     }
    1073             :     
    1074             :     Int_t nMatched = 0;
    1075             : 
    1076           0 :     Int_t mostProbDEmatched = detElemIdFromTrack[0];
    1077           0 :     for ( Int_t icath=0; icath<2; icath++ ) {
    1078           0 :       if ( matchedPads.UncheckedAt(icath) ) {
    1079           0 :         nMatched++;
    1080             :         // Fill pattern anyway
    1081           0 :         AliESDMuonTrack::SetFiredChamber(pattern, icath, ich);
    1082           0 :         digitPerTrack[icath]++;
    1083           0 :         mostProbDEmatched = matchedDetElemId[icath];
    1084           0 :       }
    1085             :     }
    1086           0 :     Int_t mostProbDEfromTrack = detElemIdFromTrack[0];
    1087           0 :     for ( Int_t ifound=0; ifound<nFound; ifound++ ) {
    1088           0 :       if ( detElemIdFromTrack[ifound] == mostProbDEmatched ) {
    1089             :         mostProbDEfromTrack = mostProbDEmatched;
    1090           0 :         break;
    1091             :       }
    1092             :     }
    1093             :     
    1094           0 :     if ( goodForEff == AliESDMuonTrack::kNoEff ) continue;
    1095             : 
    1096           0 :     if ( nMatched < 2 ) PadsFromPos(vec11, vec21, mostProbDEfromTrack, padsFromPos);
    1097             : 
    1098           0 :     for ( Int_t cath=0; cath<2; cath++ ) {
    1099           0 :       if ( matchedPads.UncheckedAt(cath) ) validPads.AddAt(matchedPads.UncheckedAt(cath),cath);
    1100           0 :       else if ( padsFromPos.UncheckedAt(cath) ) {
    1101           0 :         AliMpPad* currPad = (AliMpPad*)padsFromPos.UncheckedAt(cath);
    1102           0 :         validPads.AddAt(currPad,cath);
    1103           0 :         if ( IsMasked(*currPad, mostProbDEfromTrack, cath, vec11, vec21) ) {
    1104             :           // Check if strip was masked (if inefficient strip is found)
    1105           0 :           AliESDMuonTrack::AddEffInfo(pattern,AliESDMuonTrack::kTrackMatchesMasks); // pad is masked
    1106           0 :           AliDebug(10,Form("DetElemId %i  cath %i  board %i  strip %i is masked: effFlag 0", mostProbDEfromTrack, cath, currPad->GetLocalBoardId(0), currPad->GetLocalBoardChannel(0)));
    1107             :           goodForEff = AliESDMuonTrack::kNoEff;
    1108           0 :         }
    1109           0 :       }
    1110             :       else goodForEff = AliESDMuonTrack::kNoEff;
    1111             :     } // loop on cathodes
    1112             :         
    1113           0 :     if ( goodForEff != AliESDMuonTrack::kNoEff ) {
    1114             :       
    1115           0 :       if ( nMatched == 0 && IsCloseToAccEdge(padsFromPos, mostProbDEfromTrack, trackIntersectCh) ) {
    1116             :         // Non of cathodes is fired.
    1117             :         // If we are close to the edge of the RPC
    1118             :         // it could be a problem of acceptance 
    1119           0 :         AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackOutsideGeometry);
    1120             :         goodForEff = AliESDMuonTrack::kNoEff;
    1121           0 :         AliDebug(10, "Warning: trigger track at the edge of the chamber\n");
    1122             :       }
    1123             :       
    1124           0 :       Int_t currSlat = mostProbDEmatched%100;
    1125           0 :       if ( firstSlat < 0 ) firstSlat = currSlat;
    1126           0 :       else if ( currSlat != firstSlat ) {
    1127             :         goodForEff = AliESDMuonTrack::kChEff;
    1128             :         firstSlat = AliESDMuonTrack::kCrossDifferentSlats;
    1129           0 :       }
    1130             :     
    1131           0 :       if ( firstBoard < 0 ) firstBoard = ((AliMpPad*)validPads[kBending])->GetLocalBoardId(0);
    1132             :         
    1133           0 :       for ( Int_t cath=0; cath<2; cath++ ){      
    1134             :       
    1135           0 :         if ( goodForEff == AliESDMuonTrack::kBoardEff) {
    1136             :           Bool_t atLeastOneLoc = kFALSE;
    1137           0 :           AliMpPad* currPad = (AliMpPad*)validPads.UncheckedAt(cath);
    1138           0 :           for ( Int_t iloc=0; iloc<currPad->GetNofLocations(); iloc++) {
    1139           0 :             if ( currPad->GetLocalBoardId(iloc) == firstBoard ) {
    1140             :               atLeastOneLoc = kTRUE;
    1141           0 :               break;
    1142             :             }
    1143             :           } // loop on locations
    1144           0 :           if ( ! atLeastOneLoc ) goodForEff = AliESDMuonTrack::kSlatEff;
    1145           0 :         }
    1146             :       } // loop on cathodes
    1147           0 :     } // if track good for efficiency
    1148           0 :     matchedPads.Delete();
    1149           0 :     padsFromPos.Delete();
    1150           0 :   } // end chamber loop
    1151             :   
    1152           0 :   if ( goodForEff == AliESDMuonTrack::kNoEff ) return kFALSE;
    1153             : 
    1154           0 :   for(Int_t cath=0; cath<2; cath++){
    1155           0 :     if(digitPerTrack[cath]<3) {
    1156             :       // track is rejected since the number of associated
    1157             :       // digits found is less than 3.
    1158           0 :       AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesFewPads);
    1159             :       goodForEff = AliESDMuonTrack::kNoEff;
    1160           0 :       AliDebug(10, Form("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath));
    1161             :     }
    1162             :   } // loop on cathodes 
    1163             : 
    1164           0 :   if ( goodForEff == AliESDMuonTrack::kNoEff ) return kFALSE;
    1165             :   
    1166           0 :   AliESDMuonTrack::AddEffInfo(pattern, firstSlat, firstBoard, goodForEff);
    1167           0 :   return kTRUE;
    1168           0 : }

Generated by: LCOV version 1.11