LCOV - code coverage report
Current view: top level - HLT/MUON/OnlineAnalysis - AliHLTMUONHitReconstructor.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 1161 0.0 %
Date: 2016-06-14 17:26:59 Functions: 0 32 0.0 %

          Line data    Source code
       1             : /**************************************************************************
       2             :  * This file is property of and copyright by the ALICE HLT Project        * 
       3             :  * All rights reserved.                                                   *
       4             :  *                                                                        *
       5             :  * Primary Authors:                                                       *
       6             :  *   Indranil Das <indra.das@saha.ac.in>                                  *
       7             :  *                                                                        *
       8             :  * Permission to use, copy, modify and distribute this software and its   *
       9             :  * documentation strictly for non-commercial purposes is hereby granted   *
      10             :  * without fee, provided that the above copyright notice appears in all   *
      11             :  * copies and that both the copyright notice and this permission notice   *
      12             :  * appear in the supporting documentation. The authors make no claims     *
      13             :  * about the suitability of this software for any purpose. It is          * 
      14             :  * provided "as is" without express or implied warranty.                  *
      15             :  **************************************************************************/
      16             : 
      17             : // $Id$
      18             : 
      19             : ///////////////////////////////////////////////
      20             : //Author : Indranil Das, SINP, INDIA
      21             : //         Sukalyan Chattopadhyay, SINP, INDIA
      22             : //         
      23             : //Email :  indra.das@saha.ac.in
      24             : //         sukalyan.chattopadhyay@saha.ac.in 
      25             : //
      26             : // This class implements a hit reconstruction algorithm for the dimuon
      27             : // high level trigger.
      28             : // The algorithm finds 3 pad clusters by looking for unique pads with a charge
      29             : // above a certain threshold. A centre of gravity type calculation is applied
      30             : // to the three pads forming the cluster to find the hit's X or Y coordinate
      31             : // along the non-bending and bending planes individually.
      32             : // The sepperate X and Y coordinates are then merged to give the full coordinate
      33             : // of the hit.
      34             : /////////////////////////////////////////////////
      35             : 
      36             : #include "AliHLTMUONHitReconstructor.h"
      37             : #include "AliHLTMUONRecHitsBlockStruct.h"
      38             : #include "AliHLTMUONClustersBlockStruct.h"
      39             : #include "AliHLTMUONChannelsBlockStruct.h"
      40             : #include "AliHLTMUONUtils.h"
      41             : #include <cassert>
      42             : 
      43             : 
      44             : const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkDetectorId = 0xA00;
      45             : const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkDDLOffSet = 0;
      46             : const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkNofDDL = 20;
      47             : const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkDDLHeaderSize = gkAliHLTCommonHeaderCount;
      48             : const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkLutLine = 59648 + 1;
      49             : const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkMaxNofDataPerDetElem = 3000;
      50             : const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkNofDetElemInDDL[20] =   {  2,   2,   2,   2, 
      51             :                                                                               2,   2,   2,   2,
      52             :                                                                               36,  36,  36,  36,
      53             :                                                                               26,  26,  26,  26,
      54             :                                                                               26,  26,  26,  26};        
      55             : const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkMinDetElemIdInDDL[20] = {  100, 101, 200, 201,
      56             :                                                                               300, 301, 400, 401,
      57             :                                                                               505, 501, 510, 500,
      58             :                                                                               707, 700, 807, 800,
      59             :                                                                               907, 900,1007,1000};      
      60             : 
      61             : 
      62             : AliHLTMUONHitReconstructor::AliHLTMUONHitReconstructor() :
      63           0 :         AliHLTLogging(),
      64           0 :         fHLTMUONDecoder(),
      65           0 :         fkBlockHeaderSize(8),
      66           0 :         fkDspHeaderSize(8),
      67           0 :         fkBuspatchHeaderSize(4),
      68           0 :         fDCCut(-1),
      69           0 :         fPadData(NULL),
      70           0 :         fkLookUpTableData(NULL),
      71           0 :         fRecPoints(NULL),
      72           0 :         fRecPointsCount(NULL),
      73           0 :         fMaxRecPointsCount(0),
      74           0 :         fClusters(NULL),
      75           0 :         fClusterCount(0),
      76           0 :         fMaxClusters(0),
      77           0 :         fGenerateClusterInfo(false),
      78           0 :         fNewClusterId(0),
      79           0 :         fDDL(-1),
      80           0 :         fChannels(NULL),
      81           0 :         fChannelCount(0),
      82           0 :         fMaxChannels(0),
      83           0 :         fGenerateChannelInfo(false),
      84           0 :         fMaxChannelMult(6),
      85           0 :         fCentralCountB(0),
      86           0 :         fCentralCountNB(0),
      87           0 :         fDigitPerDDL(0),
      88           0 :         fDataCountListPerDetElem(NULL),
      89           0 :         fNofDataInDetElem(NULL),
      90           0 :         fCentralChargeB(NULL),
      91           0 :         fCentralChargeNB(NULL),
      92           0 :         fRecX(NULL),
      93           0 :         fRecY(NULL),
      94           0 :         fAvgChargeX(NULL),
      95           0 :         fAvgChargeY(NULL),
      96           0 :         fTotChargeX(NULL),
      97           0 :         fTotChargeY(NULL),
      98           0 :         fNofBChannel(NULL),
      99           0 :         fNofNBChannel(NULL),
     100           0 :         fNofYNeighbour(NULL),
     101           0 :         fkIdToEntry(),
     102           0 :         fkMaxEntryPerBusPatch(0),
     103           0 :         fRecoveryMode(kDontTryRecover)
     104           0 : {
     105             :         /// Default constructor
     106             :         
     107           0 :         fkBlockHeaderSize    = 8;
     108           0 :         fkDspHeaderSize      = 8;
     109           0 :         fkBuspatchHeaderSize = 4;
     110             :         
     111             :         try
     112             :         {
     113           0 :                 fPadData = new AliHLTMUONPad[fgkLutLine];
     114           0 :         }
     115             :         catch (const std::bad_alloc&)
     116             :         {
     117           0 :                 HLTError("Dynamic memory allocation failed for fPadData in constructor.");
     118           0 :                 throw;
     119           0 :         }
     120             :         
     121           0 :         fPadData[0].fDetElemId = 0;
     122           0 :         fPadData[0].fIX = 0 ;
     123           0 :         fPadData[0].fIY = 0 ;
     124           0 :         fPadData[0].fRealX = 0.0 ;
     125           0 :         fPadData[0].fRealY = 0.0 ;
     126           0 :         fPadData[0].fRealZ = 0.0 ;
     127           0 :         fPadData[0].fHalfPadSize = 0.0 ;
     128           0 :         fPadData[0].fPlane = 0 ;
     129           0 :         fPadData[0].fCharge = 0 ;
     130           0 :         fPadData[0].fBusPatch = -1;
     131           0 :         fPadData[0].fRawData = 0 ;
     132             :         
     133           0 :         bzero(fGetIdTotalData, 336*237*2*sizeof(int));
     134           0 : }
     135             : 
     136             : 
     137             : AliHLTMUONHitReconstructor::~AliHLTMUONHitReconstructor()
     138           0 : {
     139             :         /// Default destructor
     140             :         
     141           0 :         if (fPadData)
     142             :         {
     143           0 :                 delete [] fPadData;
     144           0 :                 fPadData = NULL;
     145           0 :         }
     146             :         
     147           0 :         if (fClusters != NULL)
     148             :         {
     149           0 :                 delete [] fClusters;
     150             :         }
     151           0 :         if (fChannels != NULL)
     152             :         {
     153           0 :                 delete [] fChannels;
     154             :         }
     155           0 : }
     156             : 
     157             : 
     158             : void AliHLTMUONHitReconstructor::SetLookUpTable(
     159             :                 const AliHLTMUONHitRecoLutRow* lookupTable,
     160             :                 const IdManuChannelToEntry* idToEntry,
     161             :                 const MaxEntryPerBusPatch* maxEntryPerBP
     162             :         )
     163             : {
     164             :         /// Sets the Lookup table (LUT) containing the position of each pad with
     165             :         /// electronic channel associated with it. Also the appropriate manu
     166             :         /// channel ID mapping to LUT row is also set.
     167             : 
     168           0 :         assert( lookupTable != NULL );
     169           0 :         assert( idToEntry != NULL );
     170           0 :         assert( maxEntryPerBP != NULL );
     171             :         
     172           0 :         fkLookUpTableData = lookupTable;
     173           0 :         fkIdToEntry = idToEntry;
     174           0 :         fkMaxEntryPerBusPatch = maxEntryPerBP;
     175           0 : }
     176             : 
     177             : bool AliHLTMUONHitReconstructor::DeInitDetElemInDDLArray()
     178             : {
     179             :   /// Deinitialisation
     180             : 
     181           0 :         if (fDataCountListPerDetElem)
     182             :         {
     183           0 :                 delete [] fDataCountListPerDetElem;
     184           0 :                 fDataCountListPerDetElem = NULL;
     185           0 :         }
     186             : 
     187           0 :         if (fNofDataInDetElem)
     188             :         {
     189           0 :                 delete [] fNofDataInDetElem;
     190           0 :                 fNofDataInDetElem = NULL;
     191           0 :         }
     192             : 
     193           0 :   return true;
     194             : }
     195             : 
     196             : bool AliHLTMUONHitReconstructor::InitDetElemInDDLArray()
     197             : {
     198             : 
     199             :   ///Initialisation
     200             : 
     201           0 :   if(GetkNofDetElemInDDL(fDDL)==-1){
     202           0 :     HLTError("Check if the DDLNumber(AliHLTInt32_t value) is Set before this method");
     203           0 :     return false;
     204             :   }
     205             :   
     206             :   try{
     207           0 :     fDataCountListPerDetElem = new AliHLTUInt16_t*[GetkNofDetElemInDDL(fDDL)];
     208           0 :   }catch (const std::bad_alloc&){
     209           0 :     HLTError("Dynamic memory allocation failed in constructor : fDataCountListPerDetElem");
     210           0 :     throw;
     211           0 :   }
     212             : 
     213           0 :   for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
     214             :     try{
     215           0 :       fDataCountListPerDetElem[idet] = new AliHLTUInt16_t[fgkMaxNofDataPerDetElem];
     216           0 :     }catch (const std::bad_alloc&){
     217           0 :       HLTError("Dynamic memory allocation failed in constructor : fDataCountListPerDetElem[%d]",idet);
     218           0 :       throw;
     219           0 :     }
     220             :   
     221             :   try{
     222           0 :     fNofDataInDetElem = new AliHLTUInt16_t[GetkNofDetElemInDDL(fDDL)];
     223           0 :   }catch (const std::bad_alloc&){
     224           0 :     HLTError("Dynamic memory allocation failed in constructor : fDataCountListPerDetElem");
     225           0 :     throw;
     226           0 :   }
     227             : 
     228           0 :   for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
     229           0 :     fNofDataInDetElem[idet] = 0;
     230             :   
     231           0 :   return true;
     232           0 : }
     233             : 
     234             : void AliHLTMUONHitReconstructor::TryRecover(ERecoveryMode mode)
     235             : {
     236             :         /// Sets if the decoder should enable the error recovery logic.
     237             :         
     238             :         // Here we setup the various flags to control exactly how the DDL raw data
     239             :         // decoder will behave and what output is generated during errors.
     240           0 :         fRecoveryMode = mode;
     241           0 :         switch (mode)
     242             :         {
     243             :         case kRecoverFull:
     244           0 :                 fHLTMUONDecoder.TryRecover(true);
     245           0 :                 fHLTMUONDecoder.ExitOnError(false);
     246           0 :                 fHLTMUONDecoder.GetHandler().WarnOnly(true);
     247           0 :                 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
     248           0 :                 break;
     249             :         case kRecoverJustSkip:
     250           0 :                 fHLTMUONDecoder.TryRecover(false);
     251           0 :                 fHLTMUONDecoder.ExitOnError(false);
     252           0 :                 fHLTMUONDecoder.GetHandler().WarnOnly(true);
     253           0 :                 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
     254           0 :                 break;
     255             :         case kRecoverFromParityErrorsOnly:
     256           0 :                 fHLTMUONDecoder.TryRecover(false);
     257           0 :                 fHLTMUONDecoder.ExitOnError(false);
     258           0 :                 fHLTMUONDecoder.GetHandler().WarnOnly(false);
     259           0 :                 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
     260           0 :                 break;
     261             :         default:
     262           0 :                 fRecoveryMode = kDontTryRecover;
     263           0 :                 fHLTMUONDecoder.TryRecover(false);
     264           0 :                 fHLTMUONDecoder.ExitOnError(true);
     265           0 :                 fHLTMUONDecoder.GetHandler().WarnOnly(false);
     266           0 :                 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(false);
     267           0 :                 break;
     268             :         }
     269           0 : }
     270             : 
     271             : 
     272             : bool AliHLTMUONHitReconstructor::Run(
     273             :                 AliHLTUInt32_t* rawData,
     274             :                 AliHLTUInt32_t rawDataSize,
     275             :                 AliHLTMUONRecHitStruct* const recHit,
     276             :                 AliHLTUInt32_t& nofHit
     277             :         ) 
     278             : {
     279             :   // main function called by HLTReconstructor to perform DHLT Hitreconstruction 
     280             : 
     281           0 :   fRecPoints = recHit;
     282           0 :   fMaxRecPointsCount = nofHit;
     283           0 :   fRecPointsCount = &nofHit;
     284           0 :   *fRecPointsCount = 0;
     285           0 :   fDigitPerDDL = 0;
     286           0 :   fClusterCount = 0;
     287           0 :   fChannelCount = 0;
     288             :   HLTDebug("Decoding for DDL : %d",fDDL);
     289           0 :   if(GetkMinDetElemIdInDDL(fDDL) == -1 or GetkNofDetElemInDDL(fDDL)==-1){
     290           0 :     HLTError("DDL value fDDL : %d, out of range",fDDL);
     291             :   }
     292           0 :   if (not DecodeDDL(rawData, rawDataSize)) {
     293             :     // Dont need to log any message again. Already done so in DecodeDDL.
     294           0 :     return false;
     295             :   }
     296             : 
     297           0 :   if (fDigitPerDDL == 1)
     298             :   {
     299             :     // There are no digits to process so stop here.
     300           0 :     return true;
     301             :   }
     302             :   
     303             :   // Allocate fClusters and fChannels if required to do so and only if the allocated
     304             :   // size of the arrays is too small.
     305             :   try
     306             :   {
     307           0 :     if (fGenerateClusterInfo and fMaxClusters < fMaxRecPointsCount)
     308             :     {
     309           0 :       if (fClusters != NULL)
     310             :       {
     311           0 :         delete [] fClusters;
     312           0 :         fMaxClusters = 0;
     313           0 :       }
     314           0 :       fClusters = new AliHLTMUONClusterStruct[fMaxRecPointsCount];
     315           0 :       fMaxClusters = fMaxRecPointsCount;
     316           0 :     }
     317           0 :     if (fGenerateChannelInfo and fMaxChannels < fMaxRecPointsCount*fMaxChannelMult)
     318             :     {
     319           0 :       if (fChannels != NULL)
     320             :       {
     321           0 :         delete [] fChannels;
     322           0 :         fMaxChannels = 0;
     323           0 :       }
     324           0 :       fChannels = new AliHLTMUONChannelStruct[fMaxRecPointsCount*fMaxChannelMult];
     325           0 :       fMaxChannels = fMaxRecPointsCount*fMaxChannelMult;
     326           0 :     }
     327           0 :   }
     328             :   catch(const std::bad_alloc&)
     329             :   {
     330           0 :     HLTError("Could not allocate memory for the extra cluster and channel information.");
     331             :     return false;
     332           0 :   }
     333             : 
     334           0 :   if (not FindRecHits()) {
     335           0 :     HLTError("Failed to generate RecHits");
     336           0 :     return false;
     337             :   }
     338             : 
     339           0 :   return true;
     340           0 : }
     341             : 
     342             : 
     343             : bool AliHLTMUONHitReconstructor::FillClusterData(
     344             :                 AliHLTMUONClusterStruct* clusters, AliHLTUInt32_t& nofClusters
     345             :         )
     346             : {
     347             :         /// Fills the output clusters array with extra cluster information.
     348             :         
     349           0 :         bool sizeOk = fClusterCount <= nofClusters;
     350           0 :         AliHLTUInt32_t n = sizeOk ? fClusterCount : nofClusters;
     351           0 :         memcpy(clusters, fClusters, sizeof(AliHLTMUONClusterStruct)*n);
     352           0 :         nofClusters = n;
     353           0 :         return sizeOk;
     354             : }
     355             : 
     356             : 
     357             : bool AliHLTMUONHitReconstructor::FillChannelData(
     358             :                 AliHLTMUONChannelStruct* channels, AliHLTUInt32_t& nofChannels
     359             :         )
     360             : {
     361             :         /// Fills the output channels array with extra channel information for each cluster.
     362             :         
     363           0 :         bool sizeOk = fChannelCount <= nofChannels;
     364           0 :         AliHLTUInt32_t n = sizeOk ? fChannelCount : nofChannels;
     365           0 :         memcpy(channels, fChannels, sizeof(AliHLTMUONChannelStruct)*n);
     366           0 :         nofChannels = n;
     367           0 :         return sizeOk;
     368             : }
     369             : 
     370             : 
     371             : bool AliHLTMUONHitReconstructor::DecodeDDL(AliHLTUInt32_t* rawData,AliHLTUInt32_t rawDataSize)
     372             : {
     373             :   //function to decode Raw Data 
     374             : 
     375           0 :   AliHLTMUONRawDecoder& handler = reinterpret_cast<AliHLTMUONRawDecoder&>(fHLTMUONDecoder.GetHandler());
     376           0 :   UInt_t bufferSize = UInt_t(rawDataSize*sizeof(AliHLTUInt32_t));
     377             : 
     378           0 :   handler.SetDCCut(fDCCut);
     379           0 :   handler.SetPadData(fPadData);
     380           0 :   handler.SetLookUpTable(fkLookUpTableData);
     381           0 :   handler.SetIdManuChannelToEntry(fkIdToEntry);
     382           0 :   handler.DDLNumber(fDDL);
     383           0 :   handler.SetNofFiredDetElemId(fNofDataInDetElem);
     384           0 :   handler.SetMaxFiredPerDetElem(fDataCountListPerDetElem);
     385           0 :   handler.SetMaxEntryPerBusPatch(fkMaxEntryPerBusPatch);
     386             :  
     387           0 :   if (not fHLTMUONDecoder.Decode(rawData,bufferSize))
     388             :   {
     389           0 :         switch (TryRecover())
     390             :         {
     391             :         case kRecoverFull:
     392             :                 // Do not print the following warning for option "-dontprintparityerrors" if there
     393             :                 // were only parity errors.
     394           0 :                 if (fHLTMUONDecoder.GetHandler().NonParityErrorFound() or
     395           0 :                     (fHLTMUONDecoder.GetHandler().ParityErrorFound() and not fHLTMUONDecoder.GetHandler().DontPrintParityErrors())
     396             :                    )
     397             :                 {
     398           0 :                         HLTWarning("There was a problem with the raw data."
     399             :                                 " Recovered as much data as possible."
     400             :                                 " Will continue processing the next event."
     401             :                         );
     402             :                 }
     403             :                 break;
     404             :         case kRecoverJustSkip:
     405           0 :                 if (fHLTMUONDecoder.GetHandler().NonParityErrorFound() or
     406           0 :                     (fHLTMUONDecoder.GetHandler().ParityErrorFound() and not fHLTMUONDecoder.GetHandler().DontPrintParityErrors())
     407             :                    )
     408             :                 {
     409           0 :                         HLTWarning("There was a problem with the raw data."
     410             :                                 " Skipped corrupted data structures."
     411             :                                 " Will continue processing the next event."
     412             :                         );
     413             :                 }
     414             :                 break;
     415             :         case kRecoverFromParityErrorsOnly:
     416           0 :                 if (fHLTMUONDecoder.GetHandler().NonParityErrorFound())
     417             :                 {
     418           0 :                         HLTError("Failed to decode the tracker DDL raw data.");
     419           0 :                         return false;
     420             :                 }
     421           0 :                 if (not fHLTMUONDecoder.GetHandler().DontPrintParityErrors())
     422             :                 {
     423           0 :                         assert( fHLTMUONDecoder.GetHandler().ParityErrorFound() );
     424           0 :                         HLTWarning("Found parity errors in the raw data,"
     425             :                                 " but will continue processing."
     426             :                         );
     427             :                 }
     428             :                 break;
     429             :         default:
     430           0 :                 HLTError("Failed to decode the tracker DDL raw data.");
     431           0 :                 return false;
     432             :         }
     433             :   }
     434             : 
     435           0 :   fDigitPerDDL = handler.GetDataCount();
     436             : 
     437             :   // fMaxFiredPerDetElem[fNofFiredDetElem-1] = handler.GetDataCount();
     438             :   
     439             :   // HLTDebug("fNofFiredDetElem : %d, NofDigits %d and max reco point limit is : %d, nofDetElems : %d",
     440             :   //         fNofFiredDetElem,fDigitPerDDL,fMaxRecPointsCount,fNofFiredDetElem);
     441             : 
     442             :   // for(int iDet=0; iDet<TMath::Max(fNofFiredDetElem,130); iDet++)
     443             :   //   HLTDebug("NofCount (fMaxFiredPerDetElem) in iDet %d is : %d", iDet, fMaxFiredPerDetElem[iDet]);
     444             :   
     445             :   // if(fNofFiredDetElem>129){
     446             :   //   HLTError("Number of fired detection elements is %d, which is more than 129.", fNofFiredDetElem);
     447             :   //   return false;
     448             :   // }
     449             :   
     450             :   if(fDigitPerDDL == 1){
     451             :     HLTDebug("An Empty DDL file was found.");
     452             :   }
     453             :   
     454           0 :   return true;
     455           0 : }
     456             : 
     457             : 
     458             : bool AliHLTMUONHitReconstructor::FindRecHits()
     459             : {
     460             :   // fuction that calls hit reconstruction detector element-wise.
     461             : 
     462           0 :   assert( fCentralChargeB == NULL );
     463           0 :   assert( fCentralChargeNB == NULL );
     464           0 :   assert( fRecX == NULL );
     465           0 :   assert( fRecY == NULL );
     466           0 :   assert( fAvgChargeX == NULL );
     467           0 :   assert( fAvgChargeY == NULL );
     468           0 :   assert( fTotChargeX == NULL );
     469           0 :   assert( fTotChargeY == NULL );
     470           0 :   assert( fNofBChannel == NULL );
     471           0 :   assert( fNofNBChannel == NULL );
     472           0 :   assert( fNofYNeighbour == NULL );
     473             :   
     474             :   bool resultOk = false;
     475             :   
     476             : 
     477             : 
     478           0 :   for(int iDet=0; iDet< GetkNofDetElemInDDL(fDDL) ; iDet++)
     479             :   {
     480           0 :     fCentralCountB = 0;
     481           0 :     fCentralCountNB = 0;
     482             : 
     483             :     try
     484             :     {
     485           0 :       fCentralChargeB = new int[fNofDataInDetElem[iDet]];
     486             :       HLTDebug("Allocated fCentralChargeB with %d elements.", fNofDataInDetElem[iDet]);
     487           0 :       fCentralChargeNB = new int[fNofDataInDetElem[iDet]];
     488             :       HLTDebug("Allocated fCentralChargeNB with %d elements.", fNofDataInDetElem[iDet]);
     489             :       resultOk = true;
     490           0 :     }
     491             :     catch(const std::bad_alloc&)
     492             :     {
     493           0 :       HLTError("Dynamic memory allocation failed for fCentralChargeNB and fCentralChargeB");
     494             :       resultOk = false;
     495             :       //break; Do not break. Might have smaller memory requirements in the next iteration.
     496           0 :     }
     497             : 
     498             :     // Continue processing, but check if everything is OK as we do, otherwise
     499             :     // do not execute the next steps.
     500           0 :     if (resultOk)
     501             :     {
     502             :       HLTDebug("Finding central hists for nofDigit  : %d, to in iDet  : %4d and min detelem : %4d",
     503             :                  fNofDataInDetElem[iDet],iDet,GetkMinDetElemIdInDDL(fDDL));
     504           0 :       FindCentralHits(iDet);
     505             :       
     506             :       HLTDebug("For iDet : %d, Found fCentralCountB : %d, fCentralCountNB : %d",iDet,fCentralCountB,fCentralCountNB);
     507           0 :       if(fCentralCountB==0 or fCentralCountNB==0)
     508             :       {
     509             :         HLTDebug("There is no fired pad in bending/nonbending plane...skipping this detection element");
     510           0 :         if (fCentralChargeB != NULL)
     511             :         {
     512           0 :           delete [] fCentralChargeB;
     513             :           HLTDebug("Released fCentralChargeB array.");
     514           0 :           fCentralChargeB = NULL;
     515           0 :         }
     516           0 :         if (fCentralChargeNB != NULL)
     517             :         {
     518           0 :           delete [] fCentralChargeNB;
     519             :           HLTDebug("Released fCentralChargeNB array.");
     520           0 :           fCentralChargeNB = NULL;
     521           0 :         }
     522             :         continue;
     523             :       }
     524             :     }
     525             : 
     526           0 :     if (resultOk)
     527             :     {
     528             :       try
     529             :       {
     530           0 :         fRecY = new float[fCentralCountB];
     531             :         HLTDebug("Allocated fRecY with %d elements.", fCentralCountB);
     532           0 :         fRecX = new float[fCentralCountNB];
     533             :         HLTDebug("Allocated fRecX with %d elements.", fCentralCountNB);
     534           0 :         fAvgChargeY = new float[fCentralCountB];
     535             :         HLTDebug("Allocated fAvgChargeY with %d elements.", fCentralCountB);
     536           0 :         fAvgChargeX = new float[fCentralCountNB];
     537             :         HLTDebug("Allocated fAvgChargeX with %d elements.", fCentralCountNB);
     538           0 :         fTotChargeY = new float[fCentralCountB];
     539             :         HLTDebug("Allocated fTotChargeY with %d elements.", fCentralCountB);
     540           0 :         fTotChargeX = new float[fCentralCountNB];
     541             :         HLTDebug("Allocated fTotChargeX with %d elements.", fCentralCountNB);
     542           0 :         fNofBChannel = new int[fCentralCountB];
     543             :         HLTDebug("Allocated fNofBChannel with %d elements.", fCentralCountB);
     544           0 :         fNofNBChannel = new int[fCentralCountNB];
     545             :         HLTDebug("Allocated fNofNBChannel with %d elements.", fCentralCountNB);
     546           0 :         fNofYNeighbour = new int[fCentralCountB];
     547             :         HLTDebug("Allocated fNofBChannel with %d elements.", fCentralCountB);
     548             :         resultOk = true;
     549           0 :       }
     550             :       catch(const std::bad_alloc&){
     551           0 :         HLTError("Dynamic memory allocation failed for internal arrays.");
     552             :         resultOk = false;
     553             :         //break; Must not break, this will prevent calling delete and memory cleanup, i.e. memory leak.
     554           0 :       }
     555             :     }
     556             : 
     557           0 :     if (resultOk) RecXRecY();
     558             :     
     559           0 :     if (resultOk)
     560             :     {
     561           0 :       if(fDDL<8)
     562           0 :         resultOk = MergeQuadRecHits();
     563             :       else
     564           0 :         resultOk = MergeSlatRecHits();
     565             :     }
     566             :     
     567             :     // minimum value in loop is 1 because dataCount in ReadDDL starts from 1 instead of 0;
     568           0 :     for(int i=0;i<fNofDataInDetElem[iDet];i++)
     569           0 :       fGetIdTotalData[fPadData[fDataCountListPerDetElem[iDet][i]].fIX]
     570           0 :         [fPadData[fDataCountListPerDetElem[iDet][i]].fIY]
     571           0 :         [fPadData[fDataCountListPerDetElem[iDet][i]].fPlane] = 0;
     572             : 
     573             :     // Make sure to release any memory that was allocated.
     574           0 :     if (fCentralChargeB != NULL)
     575             :     {
     576           0 :       delete [] fCentralChargeB;
     577             :       HLTDebug("Released fCentralChargeB array.");
     578           0 :       fCentralChargeB = NULL;
     579           0 :     }
     580           0 :     if (fCentralChargeNB != NULL)
     581             :     {
     582           0 :       delete [] fCentralChargeNB;
     583             :       HLTDebug("Released fCentralChargeNB array.");
     584           0 :       fCentralChargeNB = NULL;
     585           0 :     }
     586           0 :     if (fRecX != NULL)
     587             :     {
     588           0 :       delete [] fRecX;
     589             :       HLTDebug("Released fRecX array.");
     590           0 :       fRecX = NULL;
     591           0 :     }
     592           0 :     if (fRecY != NULL)
     593             :     {
     594           0 :       delete [] fRecY;
     595             :       HLTDebug("Released fRecY array.");
     596           0 :       fRecY = NULL;
     597           0 :     }
     598           0 :     if (fAvgChargeX != NULL)
     599             :     {
     600           0 :       delete [] fAvgChargeX;
     601             :       HLTDebug("Released fAvgChargeX array.");
     602           0 :       fAvgChargeX = NULL;
     603           0 :     }
     604           0 :     if (fAvgChargeY != NULL)
     605             :     {
     606           0 :       delete [] fAvgChargeY;
     607             :       HLTDebug("Released fAvgChargeY array.");
     608           0 :       fAvgChargeY = NULL;
     609           0 :     }
     610           0 :     if (fTotChargeX != NULL)
     611             :     {
     612           0 :       delete [] fTotChargeX;
     613             :       HLTDebug("Released fTotChargeX array.");
     614           0 :       fTotChargeX = NULL;
     615           0 :     }
     616           0 :     if (fTotChargeY != NULL)
     617             :     {
     618           0 :       delete [] fTotChargeY;
     619             :       HLTDebug("Released fTotChargeY array.");
     620           0 :       fTotChargeY = NULL;
     621           0 :     }
     622           0 :     if (fNofBChannel != NULL)
     623             :     {
     624           0 :       delete [] fNofBChannel;
     625             :       HLTDebug("Released fNofBChannel array.");
     626           0 :       fNofBChannel = NULL;
     627           0 :     }
     628           0 :     if (fNofNBChannel != NULL)
     629             :     {
     630           0 :       delete [] fNofNBChannel;
     631             :       HLTDebug("Released fNofNBChannel array.");
     632           0 :       fNofNBChannel = NULL;
     633           0 :     }
     634           0 :     if (fNofYNeighbour != NULL)
     635             :     {
     636           0 :       delete [] fNofYNeighbour;
     637             :       HLTDebug("Released fNofYNeighbour array.");
     638           0 :       fNofYNeighbour = NULL;
     639           0 :     }
     640             :   }
     641             : 
     642           0 :   Clear();  // clear internal arrays.
     643             : 
     644           0 :   return resultOk;
     645           0 : }
     646             : 
     647             : 
     648             : void AliHLTMUONHitReconstructor::FindCentralHits(int iDet)
     649             : {
     650             :   // to find central hit associated with each cluster
     651             : 
     652           0 :   assert( fCentralChargeB != NULL );
     653           0 :   assert( fCentralChargeNB != NULL );
     654             : 
     655             :   int b,nb;
     656             :   int idManuChannelCentral;
     657             :   bool hasFind;
     658             :   int iPad = 0;
     659             : 
     660           0 :   for(int iEntry=0;iEntry<fNofDataInDetElem[iDet];iEntry++){
     661             : 
     662           0 :     iPad = fDataCountListPerDetElem[iDet][iEntry];
     663             : 
     664             :     //if(fPadData[iPad].fDetElemId==102)
     665             :     HLTDebug("iPad : %d, detElem : %d, fCentralCountB : %d, fCentralCountNB : %d",iPad,fPadData[iPad].fDetElemId,fCentralCountB,fCentralCountNB);
     666             : 
     667           0 :     fGetIdTotalData[fPadData[iPad].fIX]
     668           0 :       [fPadData[iPad].fIY]
     669           0 :       [fPadData[iPad].fPlane] = iPad ;
     670             : 
     671           0 :     if(fPadData[iPad].fCharge <= fDCCut ) continue;
     672             :     
     673           0 :     if(fPadData[iPad].fPlane == 0 ){//&& fPadData[iPad].fIY > (0+1) && fPadData[iPad].fIY < (79 - 1)){
     674             :       //if(fPadData[iPad].fIY > 0){
     675           0 :       if(fCentralCountB>0){
     676             :         hasFind = false;
     677           0 :         for(b = 0;b<fCentralCountB;b++){
     678           0 :           idManuChannelCentral = fCentralChargeB[b];
     679           0 :           if(fPadData[iPad].fIX == fPadData[idManuChannelCentral].fIX
     680           0 :              &&
     681           0 :              (fPadData[iPad].fIY 
     682           0 :               == fPadData[idManuChannelCentral].fIY + 1 
     683           0 :               ||
     684             :               fPadData[iPad].fIY 
     685           0 :               == fPadData[idManuChannelCentral].fIY + 2 
     686           0 :               ||
     687             :               fPadData[iPad].fIY 
     688           0 :               == fPadData[idManuChannelCentral].fIY - 2 
     689           0 :               ||
     690             :               fPadData[iPad].fIY 
     691           0 :               == fPadData[idManuChannelCentral].fIY - 1)){
     692             :             
     693             :             hasFind = true;
     694           0 :             if(fPadData[iPad].fCharge > fPadData[idManuChannelCentral].fCharge){
     695           0 :               fCentralChargeB[b] = iPad;
     696           0 :             }// if condn on pad charge
     697             :           }// if condon on pad position
     698             :         }// for loop over b
     699           0 :         if(!hasFind){
     700           0 :           fCentralChargeB[fCentralCountB] = iPad;
     701           0 :           fCentralCountB++;
     702           0 :         }
     703             :       }
     704             :       else{
     705           0 :         fCentralChargeB[fCentralCountB] = iPad;
     706           0 :         fCentralCountB++;
     707             :       }// check the size of centralHitB
     708           0 :       for(b = 0;b<fCentralCountB;b++){
     709           0 :         idManuChannelCentral = fCentralChargeB[b];
     710             :       }
     711             :       //}// if cond on iY > 2 (to avoid edge value pb)
     712             :     }// B/Nb checking
     713             :     else{
     714           0 :       if(fCentralCountNB>0){
     715             :         hasFind = false;
     716           0 :         for(nb = 0;nb<fCentralCountNB;nb++){
     717           0 :           idManuChannelCentral = fCentralChargeNB[nb];
     718           0 :           if(fPadData[iPad].fIY == fPadData[idManuChannelCentral].fIY
     719           0 :              &&
     720           0 :              (fPadData[iPad].fIX 
     721           0 :               == fPadData[idManuChannelCentral].fIX + 1 
     722           0 :               ||
     723             :               fPadData[iPad].fIX
     724           0 :               == fPadData[idManuChannelCentral].fIX + 2
     725           0 :               ||
     726             :               fPadData[iPad].fIX
     727           0 :               == fPadData[idManuChannelCentral].fIX - 2
     728           0 :               ||
     729             :               fPadData[iPad].fIX
     730           0 :               == fPadData[idManuChannelCentral].fIX - 1)){
     731             :             
     732             :             hasFind = true;       
     733           0 :             if(fPadData[iPad].fCharge > fPadData[idManuChannelCentral].fCharge){
     734           0 :               fCentralChargeNB[nb] = iPad;
     735           0 :             }// if condn over to find higher charge
     736             :           }// if condn over to find position
     737             :         }// for loop over presently all nb values
     738           0 :         if(!hasFind){
     739           0 :           fCentralChargeNB[fCentralCountNB] = iPad;
     740           0 :           fCentralCountNB++;
     741           0 :         }
     742             :       }// centralHitNB size test
     743             :       else{
     744           0 :         fCentralChargeNB[fCentralCountNB] = iPad;
     745           0 :         fCentralCountNB++;
     746             :       }// centralHitNB size test
     747             :       
     748             :     }// fill for bending and nonbending hit
     749             :   }// detElemId loop
     750             : 
     751           0 : }
     752             : 
     753             : void AliHLTMUONHitReconstructor::RecXRecY()
     754             : {
     755             :   // find reconstructed X and Y for each plane separately
     756             : 
     757           0 :   assert( fRecX != NULL );
     758           0 :   assert( fRecY != NULL );
     759           0 :   assert( fAvgChargeX != NULL );
     760           0 :   assert( fAvgChargeY != NULL );
     761           0 :   assert( fTotChargeX != NULL );
     762           0 :   assert( fTotChargeY != NULL );
     763           0 :   assert( fNofBChannel != NULL );
     764           0 :   assert( fNofNBChannel != NULL );
     765           0 :   assert( fNofYNeighbour  != NULL );
     766             : 
     767             :   int b,nb;
     768             :   int idCentral;
     769             :   int idLower = 0;
     770             :   int idUpper = 0;
     771             :   int idRight = 0;
     772             :   int idLeft = 0;
     773             :   
     774           0 :   for(b=0;b<fCentralCountB;b++){
     775           0 :     idCentral = fCentralChargeB[b];
     776             : 
     777           0 :     if(fPadData[idCentral].fIY==0)
     778           0 :       idLower = 0;
     779             :     else
     780           0 :       idLower = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY-1][0];
     781             :     
     782           0 :     if(fPadData[idCentral].fIY==236)
     783           0 :       idUpper = 0;
     784             :     else
     785           0 :       idUpper = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY+1][0];
     786             : 
     787             :     
     788           0 :     fTotChargeY[b] = (fPadData[idCentral].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge);
     789           0 :     if(fTotChargeY[b]==0.0) continue;
     790           0 :     fAvgChargeY[b] = fTotChargeY[b]/3.0 ;
     791             : 
     792           0 :     fRecY[b] = (fPadData[idCentral].fRealY*fPadData[idCentral].fCharge
     793           0 :                +
     794           0 :                 fPadData[idUpper].fRealY*fPadData[idUpper].fCharge
     795           0 :                +
     796           0 :                 fPadData[idLower].fRealY*fPadData[idLower].fCharge
     797           0 :                 )/fTotChargeY[b];//(fPadData[idCentral].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge) ;
     798             :     
     799           0 :     fNofBChannel[b] = 0;
     800           0 :     fNofYNeighbour[b] = 0;
     801           0 :     if(fPadData[idLower].fCharge>0.0){
     802           0 :       fNofBChannel[b]++ ;
     803           0 :       fNofYNeighbour[b]++;
     804           0 :     }
     805           0 :     if(fPadData[idCentral].fCharge>0.0)
     806           0 :       fNofBChannel[b]++ ;
     807           0 :     if(fPadData[idUpper].fCharge>0.0){
     808           0 :       fNofBChannel[b]++ ;
     809           0 :       fNofYNeighbour[b]++;
     810           0 :     }
     811             : 
     812             :     HLTDebug("detelem : %d, Y charge : lower : %f, middle : %f, upper : %f",fPadData[idCentral].fDetElemId,fPadData[idLower].fCharge,
     813             :             fPadData[idCentral].fCharge,fPadData[idUpper].fCharge);
     814             : 
     815             :     //collect left coloumn
     816           0 :     if((fPadData[idCentral].fIX-1)>=0){
     817             :       
     818           0 :       idLeft = fGetIdTotalData[fPadData[idCentral].fIX-1][fPadData[idCentral].fIY][0];
     819             :       
     820           0 :       if(fPadData[idLeft].fIY==0)
     821           0 :         idLower = 0;
     822             :       else
     823           0 :         idLower = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY-1][0];
     824             :       
     825           0 :       if(fPadData[idLeft].fIY==236)
     826           0 :         idUpper = 0;
     827             :       else
     828           0 :         idUpper = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY+1][0];
     829             : 
     830           0 :       fTotChargeY[b] += (fPadData[idLeft].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge);
     831             : 
     832           0 :       if(fPadData[idLower].fCharge>0.0)
     833           0 :         fNofBChannel[b]++ ;
     834           0 :       if(fPadData[idLeft].fCharge>0.0)
     835           0 :         fNofBChannel[b]++ ;
     836           0 :       if(fPadData[idUpper].fCharge>0.0)
     837           0 :         fNofBChannel[b]++ ;
     838             : 
     839             :     }
     840             :     ////////////////////////////////////////////////////
     841             : 
     842             :     //collect right coloumn
     843           0 :     if((fPadData[idCentral].fIX+1)<=335){
     844             : 
     845           0 :       idRight = fGetIdTotalData[fPadData[idCentral].fIX+1][fPadData[idCentral].fIY][0];
     846             :     
     847           0 :       if(fPadData[idRight].fIY==0)
     848           0 :         idLower = 0;
     849             :       else
     850           0 :         idLower = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY-1][0];
     851             :       
     852           0 :       if(fPadData[idRight].fIY==236)
     853           0 :         idUpper = 0;
     854             :       else
     855           0 :         idUpper = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY+1][0];
     856             :   
     857           0 :       fTotChargeY[b] += (fPadData[idRight].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge);
     858             : 
     859           0 :       if(fPadData[idLower].fCharge>0.0)
     860           0 :         fNofBChannel[b]++ ;
     861           0 :       if(fPadData[idRight].fCharge>0.0)
     862           0 :         fNofBChannel[b]++ ;
     863           0 :       if(fPadData[idUpper].fCharge>0.0)
     864           0 :         fNofBChannel[b]++ ;
     865             : 
     866             :     }
     867             :     //////////////////////////////////////////////////////////////////////////////////
     868             :     HLTDebug("RecY[%d] : %f, nofChannel : %d, detelem : %d",b,fRecY[b],fNofBChannel[b],fPadData[idCentral].fDetElemId);
     869             :    
     870             :   }
     871             :       
     872           0 :   for(nb=0;nb<fCentralCountNB;nb++){
     873           0 :     idCentral = fCentralChargeNB[nb];
     874             : 
     875           0 :     if(fPadData[idCentral].fIX==0)
     876           0 :       idLeft = 0;
     877             :     else
     878           0 :       idLeft = fGetIdTotalData[fPadData[idCentral].fIX-1][fPadData[idCentral].fIY][1];
     879             :     
     880           0 :     if(fPadData[idCentral].fIX==335)
     881           0 :       idRight = 0 ;
     882             :     else
     883           0 :       idRight = fGetIdTotalData[fPadData[idCentral].fIX+1][fPadData[idCentral].fIY][1];
     884             : 
     885           0 :     fTotChargeX[nb] = (fPadData[idCentral].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
     886           0 :     if(fTotChargeX[nb]==0.0) continue;
     887           0 :     fAvgChargeX[nb] = fTotChargeX[nb]/3.0 ;
     888             :     
     889           0 :     fRecX[nb] = (fPadData[idCentral].fRealX*fPadData[idCentral].fCharge
     890           0 :                  +
     891           0 :                  fPadData[idRight].fRealX*fPadData[idRight].fCharge
     892           0 :                  +
     893           0 :                  fPadData[idLeft].fRealX*fPadData[idLeft].fCharge
     894           0 :                  )/fTotChargeX[nb];//(fPadData[idCentral].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
     895             :     
     896             : 
     897           0 :     fNofNBChannel[nb] = 0;
     898           0 :     if(fPadData[idLeft].fCharge>0.0)
     899           0 :       fNofNBChannel[nb]++ ;
     900           0 :     if(fPadData[idCentral].fCharge>0.0)
     901           0 :       fNofNBChannel[nb]++ ;
     902           0 :     if(fPadData[idRight].fCharge>0.0)
     903           0 :       fNofNBChannel[nb]++ ;
     904             :     
     905             :     HLTDebug("detelem : %d, X charge left : %f, middle : %f, right : %f",fPadData[idCentral].fDetElemId,fPadData[idLeft].fCharge,
     906             :             fPadData[idCentral].fCharge,fPadData[idRight].fCharge);
     907             : 
     908             : 
     909             :     // lower row 
     910           0 :     if((fPadData[idCentral].fIY-1)>=0){
     911             : 
     912           0 :       idLower = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY-1][1];
     913             :       
     914           0 :       if(fPadData[idLower].fIX==0)
     915           0 :         idLeft = 0;
     916             :       else
     917           0 :         idLeft = fGetIdTotalData[fPadData[idLower].fIX-1][fPadData[idLower].fIY][1];
     918             :     
     919           0 :       if(fPadData[idLower].fIX==335)
     920           0 :         idRight = 0 ;
     921             :       else
     922           0 :         idRight = fGetIdTotalData[fPadData[idLower].fIX+1][fPadData[idLower].fIY][1];
     923             : 
     924           0 :       fTotChargeX[nb] += (fPadData[idLower].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
     925             : 
     926           0 :       if(fPadData[idLeft].fCharge>0.0)
     927           0 :         fNofNBChannel[nb]++ ;
     928           0 :       if(fPadData[idLower].fCharge>0.0)
     929           0 :         fNofNBChannel[nb]++ ;
     930           0 :       if(fPadData[idRight].fCharge>0.0)
     931           0 :         fNofNBChannel[nb]++ ;
     932             : 
     933             :     }
     934             :     ////////////////////////////////////////////////////////////
     935             : 
     936             :     // Upper row
     937           0 :     if((fPadData[idCentral].fIY+1)<=236){
     938             : 
     939           0 :       idUpper = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY+1][1];
     940             : 
     941           0 :       if(fPadData[idUpper].fIX==0)
     942           0 :         idLeft = 0;
     943             :       else
     944           0 :         idLeft = fGetIdTotalData[fPadData[idUpper].fIX-1][fPadData[idUpper].fIY][1];
     945             :       
     946           0 :       if(fPadData[idUpper].fIX==335)
     947           0 :         idRight = 0 ;
     948             :       else
     949           0 :         idRight = fGetIdTotalData[fPadData[idUpper].fIX+1][fPadData[idUpper].fIY][1];
     950             :       
     951           0 :       fTotChargeX[nb] += (fPadData[idUpper].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
     952             :       
     953           0 :       if(fPadData[idLeft].fCharge>0.0)
     954           0 :         fNofNBChannel[nb]++ ;
     955           0 :       if(fPadData[idRight].fCharge>0.0)
     956           0 :         fNofNBChannel[nb]++ ;
     957           0 :       if(fPadData[idRight].fCharge>0.0)
     958           0 :         fNofNBChannel[nb]++ ;
     959             : 
     960             :     }
     961             :     ////////////////////////////////////////////////////////////
     962             : 
     963             :     HLTDebug("RecX[%d] : %f, nofChannel : %d",nb,fRecX[nb],fNofNBChannel[nb]);
     964             : 
     965             :    
     966             : 
     967             :   }
     968           0 : }
     969             : 
     970             : 
     971             : bool AliHLTMUONHitReconstructor::MergeQuadRecHits()
     972             : {
     973             :   // Merge reconstructed hits first over same plane then bending plane with non-bending plane
     974             : 
     975           0 :   assert( fRecX != NULL );
     976           0 :   assert( fRecY != NULL );
     977           0 :   assert( fAvgChargeX != NULL );
     978           0 :   assert( fAvgChargeY != NULL );
     979           0 :   assert( fTotChargeX != NULL );
     980           0 :   assert( fTotChargeY != NULL );
     981           0 :   assert( fNofBChannel != NULL );
     982           0 :   assert( fNofNBChannel != NULL );
     983           0 :   assert( fNofYNeighbour  != NULL );
     984             : 
     985             :   int idCentralB=0,idCentralNB=0 ;
     986             :   float padCenterXB;
     987             :   float padCenterYNB;
     988             :   float diffX,diffY;
     989             :   float minPadArea;
     990             :   float halfPadLengthX,halfPadLengthY;
     991           0 :   bool *isMergedY = new bool[fCentralCountB];
     992           0 :   bool *isMergedX = new bool[fCentralCountNB];
     993             :   float outsideSpacePoint = 1000000.0 ; /// A space point outside the detector
     994             : 
     995             :   // MERGE Bending Plane hits, which are placed side by side
     996           0 :   for(int i=0;i<fCentralCountB-1;i++){
     997           0 :     isMergedY[i] = false;
     998           0 :     if(fRecY[i] != outsideSpacePoint){
     999           0 :       for(int j=i+1;j<fCentralCountB;j++){
    1000             :                  
    1001           0 :         if(fCentralChargeB[i]==fCentralChargeB[j]){
    1002           0 :           fRecY[j] = outsideSpacePoint;
    1003           0 :           continue;
    1004             :         }
    1005             :         else if(
    1006           0 :            (
    1007           0 :             fPadData[fCentralChargeB[i]].fIY == fPadData[fCentralChargeB[j]].fIY
    1008             :             )
    1009           0 :            &&
    1010             :            (
    1011           0 :             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX + 1
    1012           0 :             ||
    1013           0 :             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX - 1
    1014             :             )
    1015           0 :            &&
    1016           0 :            fRecY[j] != outsideSpacePoint
    1017           0 :            &&
    1018           0 :            fRecY[i] != outsideSpacePoint
    1019             :            ){
    1020             : 
    1021           0 :           if(fAvgChargeY[i] > fAvgChargeY[j]){
    1022           0 :             fRecY[i] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
    1023           0 :                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
    1024           0 :             fRecY[j] = outsideSpacePoint;
    1025           0 :           }
    1026             :           else{
    1027           0 :             fRecY[j] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
    1028             :                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
    1029           0 :             fRecY[i] = outsideSpacePoint;
    1030             : 
    1031             :           }// search for higher charge
    1032             :         }//pad position
    1033             :       }//j for loop
    1034           0 :     }//if fRecY[i] != outsideSpacePoint
    1035             :   }// i for loop
    1036           0 :   isMergedY[fCentralCountB-1] = false;
    1037             :   
    1038             :   // MERGE Non Bending Plane hits, which are placed side by side
    1039           0 :   for(int i=0;i<fCentralCountNB-1;i++){
    1040           0 :     isMergedX[i] = false;
    1041           0 :     if(fRecX[i] != outsideSpacePoint){
    1042           0 :       for(int j=i+1;j<fCentralCountNB;j++){
    1043             : 
    1044           0 :         if(fCentralChargeNB[i]==fCentralChargeNB[j]){
    1045           0 :           fRecX[j] = outsideSpacePoint;
    1046           0 :           continue;
    1047             :         }
    1048             :         else if(
    1049           0 :            (
    1050           0 :             fPadData[fCentralChargeNB[i]].fIX == fPadData[fCentralChargeNB[j]].fIX
    1051             :             )
    1052           0 :            &&
    1053             :            (
    1054           0 :             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY + 1
    1055           0 :             ||
    1056           0 :             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY - 1
    1057             :             )
    1058           0 :            &&
    1059           0 :            fRecX[j] != outsideSpacePoint
    1060           0 :            &&
    1061           0 :            fRecX[i] != outsideSpacePoint
    1062             :            ){
    1063             : 
    1064           0 :           if(fAvgChargeX[i] > fAvgChargeX[j]){
    1065           0 :             fRecX[i] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
    1066           0 :                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
    1067           0 :             fRecX[j] = outsideSpacePoint;
    1068           0 :           }
    1069             :           else{
    1070           0 :             fRecX[j] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
    1071             :                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
    1072           0 :             fRecX[i] = outsideSpacePoint;
    1073             :           }// search for higher charge
    1074             :         }//pad position
    1075             :       }//j for loop
    1076           0 :     }//if fRecX[i] != outsideSpacePoint
    1077             :   }// i for loop
    1078           0 :   isMergedX[fCentralCountNB-1] = false;
    1079             :   
    1080             :   // Merge bending Plane hits with Non Bending
    1081           0 :   for(int b=0;b<fCentralCountB;b++){
    1082           0 :     if(fRecY[b]!=outsideSpacePoint){
    1083           0 :       idCentralB = fCentralChargeB[b];
    1084           0 :       padCenterXB = fPadData[idCentralB].fRealX; 
    1085             :       
    1086           0 :       halfPadLengthX = fPadData[idCentralB].fHalfPadSize ;
    1087             : 
    1088           0 :       for(int nb=0;nb<fCentralCountNB;nb++){
    1089           0 :         if(fRecX[nb]!=outsideSpacePoint){
    1090           0 :           idCentralNB = fCentralChargeNB[nb];
    1091             : 
    1092           0 :           padCenterYNB = fPadData[idCentralNB].fRealY;
    1093             : 
    1094           0 :           halfPadLengthY = fPadData[idCentralNB].fHalfPadSize ;
    1095             : 
    1096           0 :           if(fabsf(fRecX[nb]) > fabsf(padCenterXB))
    1097           0 :             diffX = fabsf(fRecX[nb]) -  fabsf(padCenterXB);
    1098             :           else
    1099           0 :             diffX = fabsf(padCenterXB) -  fabsf(fRecX[nb]);
    1100             :           
    1101           0 :           if(fabsf(padCenterYNB)>fabsf(fRecY[b]))
    1102           0 :             diffY = fabsf(padCenterYNB) - fabsf(fRecY[b]);
    1103             :           else
    1104           0 :             diffY =  fabsf(fRecY[b]) - fabsf(padCenterYNB);
    1105             : 
    1106           0 :           if(diffX < halfPadLengthX && diffY < halfPadLengthY ){//&& fPadData[idCentralB].fIY != 0){
    1107             :             
    1108           0 :             isMergedY[b] = true;
    1109           0 :             isMergedX[nb] = true;
    1110             :             
    1111           0 :             if(fNofYNeighbour[b]==2){
    1112           0 :               if(fPadData[idCentralB].fDetElemId<104)
    1113           0 :                 fRecY[b] += 0.02*sin(14.5*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
    1114           0 :               else if(fPadData[idCentralB].fDetElemId>=200 && fPadData[idCentralB].fDetElemId<204)
    1115           0 :                 fRecY[b] += 0.02*sin(14.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
    1116             :               else
    1117           0 :                 fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
    1118             :             }
    1119             :             
    1120           0 :             if(fPadData[idCentralNB].fDetElemId<204)
    1121           0 :               fRecX[nb] += 0.095*sin(10.5*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
    1122             :             else //if(fPadData[idCentralNB].fDetElemId>=300 && fPadData[idCentralNB].fDetElemId<404)
    1123           0 :               fRecX[nb] += 0.085*sin(9.0*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
    1124             :             
    1125             :             
    1126             :             // First check that we have not overflowed the buffer.
    1127           0 :             if((*fRecPointsCount) == fMaxRecPointsCount){
    1128           0 :               HLTWarning("Number of RecHits (i.e. %d) exceeds the max number of RecHit limit %d."
    1129             :                         " Output buffer is too small.",
    1130             :                        (*fRecPointsCount),fMaxRecPointsCount
    1131             :               );
    1132           0 :               delete [] isMergedY;
    1133           0 :               delete [] isMergedX;
    1134           0 :               return true;
    1135             :             }
    1136             : 
    1137           0 :             AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
    1138           0 :                  (fPadData[idCentralB].fDetElemId / 100) - 1,
    1139           0 :                  fPadData[idCentralB].fDetElemId
    1140             :               );
    1141           0 :             fRecPoints[(*fRecPointsCount)].fFlags = idflags;
    1142           0 :             fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
    1143           0 :             fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
    1144           0 :             fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
    1145             :             
    1146           0 :             if (fGenerateClusterInfo)
    1147             :             {
    1148           0 :               if (fClusterCount >= fMaxClusters)
    1149             :               {
    1150           0 :                 HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
    1151           0 :                 delete [] isMergedY;
    1152           0 :                 delete [] isMergedX;
    1153           0 :                 return false;
    1154             :               }
    1155             :               
    1156           0 :               fClusters[fClusterCount].fId = (fNewClusterId << 5) | fDDL;
    1157             :               
    1158             :               // Increment the cluster ID and warp it around at 0x03FFFFFF since
    1159             :               // the bottom 5 bits are filled with the source DDL number and the
    1160             :               // sign bit in fClusters[fClusterCount].fId must be positive.
    1161           0 :               fNewClusterId = (fNewClusterId + 1) & 0x03FFFFFF;
    1162             :               
    1163           0 :               fClusters[fClusterCount].fHit = fRecPoints[(*fRecPointsCount)];
    1164           0 :               fClusters[fClusterCount].fDetElemId = fPadData[idCentralB].fDetElemId;
    1165           0 :               fClusters[fClusterCount].fNchannelsB = fNofBChannel[b];
    1166           0 :               fClusters[fClusterCount].fNchannelsNB = fNofNBChannel[nb];
    1167           0 :               fClusters[fClusterCount].fChargeB = fTotChargeY[b];
    1168           0 :               fClusters[fClusterCount].fChargeNB = fTotChargeX[nb];
    1169           0 :               fClusterCount++;
    1170           0 :             }
    1171             :             
    1172           0 :             if (fGenerateChannelInfo)
    1173             :             {
    1174             :               // 3 by 3 pad structure around the central pad for the 2 planes.
    1175           0 :               int pad[2][3][3] = {{
    1176           0 :                   {0,      0,      0},
    1177           0 :                   {0, idCentralB,  0},
    1178           0 :                   {0,      0,      0}
    1179           0 :                 },{
    1180           0 :                   {0,      0,      0},
    1181           0 :                   {0, idCentralNB, 0},
    1182           0 :                   {0,      0,      0}
    1183             :               }};
    1184             :               
    1185             :               // Find the pad index numbers for the central pads and the pads surrounding them.
    1186             :               // All these pads would have contributed to the cluster as long as their charge is != 0.
    1187           0 :               if (fPadData[idCentralB].fIY > 0)
    1188           0 :                 pad[0][0][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY-1][0];
    1189           0 :               if (fPadData[idCentralB].fIY < 236)
    1190           0 :                 pad[0][2][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY+1][0];
    1191           0 :               if (fPadData[idCentralB].fIX > 0)
    1192             :               {
    1193           0 :                 int idLeft = fGetIdTotalData[fPadData[idCentralB].fIX-1][fPadData[idCentralB].fIY][0];
    1194           0 :                 pad[0][1][0] = idLeft;
    1195           0 :                 if (fPadData[idLeft].fIY > 0)
    1196           0 :                   pad[0][0][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY-1][0];
    1197           0 :                 if (fPadData[idLeft].fIY < 236)
    1198           0 :                   pad[0][2][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY+1][0];
    1199           0 :               }
    1200           0 :               if (fPadData[idCentralB].fIX < 335)
    1201             :               {
    1202           0 :                 int idRight = fGetIdTotalData[fPadData[idCentralB].fIX+1][fPadData[idCentralB].fIY][0];
    1203           0 :                 pad[0][1][2] = idRight;
    1204           0 :                 if (fPadData[idRight].fIY > 0)
    1205           0 :                   pad[0][0][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY-1][0];
    1206           0 :                 if (fPadData[idRight].fIY < 236)
    1207           0 :                   pad[0][2][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY+1][0];
    1208           0 :               }
    1209             :               
    1210           0 :               if (fPadData[idCentralNB].fIX > 0)
    1211           0 :                 pad[1][1][0] = fGetIdTotalData[fPadData[idCentralNB].fIX-1][fPadData[idCentralNB].fIY][1];
    1212           0 :               if (fPadData[idCentralNB].fIX < 335)
    1213           0 :                 pad[1][1][2] = fGetIdTotalData[fPadData[idCentralNB].fIX+1][fPadData[idCentralNB].fIY][1];
    1214           0 :               if (fPadData[idCentralNB].fIY > 0)
    1215             :               {
    1216           0 :                 int idLower = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY-1][1];
    1217           0 :                 pad[1][0][1] = idLower;
    1218           0 :                 if (fPadData[idLower].fIX > 0)
    1219           0 :                   pad[1][0][0] = fGetIdTotalData[fPadData[idLower].fIX-1][fPadData[idLower].fIY][1];
    1220           0 :                 if (fPadData[idLower].fIX < 335)
    1221           0 :                   pad[1][0][2] = fGetIdTotalData[fPadData[idLower].fIX+1][fPadData[idLower].fIY][1];
    1222           0 :               }
    1223           0 :               if (fPadData[idCentralNB].fIY < 236)
    1224             :               {
    1225           0 :                 int idUpper = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY+1][1];
    1226           0 :                 pad[1][2][1] = idUpper;
    1227           0 :                 if (fPadData[idUpper].fIX > 0)
    1228           0 :                   pad[1][2][0] = fGetIdTotalData[fPadData[idUpper].fIX-1][fPadData[idUpper].fIY][1];
    1229           0 :                 if (fPadData[idUpper].fIX < 335)
    1230           0 :                   pad[1][2][2] = fGetIdTotalData[fPadData[idUpper].fIX+1][fPadData[idUpper].fIY][1];
    1231           0 :               }
    1232             :               
    1233           0 :               AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
    1234             :               
    1235             :               // Now generate the pad structures from all the pad indices found above.
    1236           0 :               for (int i = 0; i < 2; i++)
    1237           0 :               for (int j = 0; j < 3; j++)
    1238           0 :               for (int k = 0; k < 3; k++)
    1239             :               {
    1240           0 :                 AliHLTMUONPad& p = fPadData[pad[i][j][k]];
    1241             :                 // Skip pads that have zero charge because they would not have
    1242             :                 // contributed to the cluster.
    1243           0 :                 if (p.fCharge <= 0) continue;
    1244             :                 
    1245           0 :                 UShort_t manuId; UChar_t channelId; UShort_t adc;
    1246           0 :                 AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
    1247             :                 
    1248           0 :                 fChannels[fChannelCount].fClusterId = clusterId;
    1249           0 :                 fChannels[fChannelCount].fBusPatch = p.fBusPatch;
    1250           0 :                 fChannels[fChannelCount].fManu = manuId;
    1251           0 :                 fChannels[fChannelCount].fChannelAddress = channelId;
    1252           0 :                 fChannels[fChannelCount].fSignal = adc;
    1253           0 :                 fChannels[fChannelCount].fRawDataWord = p.fRawData;
    1254           0 :                 fChannelCount++;
    1255           0 :               }
    1256           0 :             }
    1257             : 
    1258             :             HLTDebug("Part 1 : Reconstructed hit (X,Y,Z) : (%f,%f,%f)",
    1259             :                      fRecPoints[(*fRecPointsCount)].fX,
    1260             :                      fRecPoints[(*fRecPointsCount)].fY,
    1261             :                      fRecPoints[(*fRecPointsCount)].fZ
    1262             :             );
    1263           0 :             (*fRecPointsCount)++;
    1264           0 :           }//if lies wihtin 5.0 mm
    1265             :         }// condn over fRecX ! = 0.0
    1266             :       }// loop over NB side
    1267             :     }// condn on fRecY[b] !=  0.0
    1268             :   }// loop over B side;
    1269             :   
    1270             :   //Hit only in bending plane and in zone 1 which has not merged and which has number of channels > 2 are considered as valid hits
    1271           0 :   for(int b=0;b<fCentralCountB;b++){
    1272           0 :     if(fRecY[b]!=outsideSpacePoint and !isMergedY[b] and fNofBChannel[b]>2){
    1273           0 :       idCentralB = fCentralChargeB[b];
    1274             :       
    1275           0 :       minPadArea = (fPadData[idCentralB].fDetElemId < 204) ? 10.0*2.0*0.315*10.0*2.0*0.21 : 10.0*2.0*0.375*10.0*2.0*0.25 ;
    1276             : 
    1277           0 :       if(TMath::Abs(400.0*fPadData[idCentralB].fHalfPadSize*fPadData[idCentralB].fPadSizeXY - minPadArea)> 1.0e-5) continue;
    1278             :       
    1279           0 :       if(fNofYNeighbour[b]==2){
    1280           0 :         if(fPadData[idCentralB].fDetElemId<104)
    1281           0 :           fRecY[b] += 0.02*sin(14.5*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
    1282           0 :         else if(fPadData[idCentralB].fDetElemId>=200 && fPadData[idCentralB].fDetElemId<204)
    1283           0 :           fRecY[b] += 0.02*sin(14.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
    1284             :         else
    1285           0 :           fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
    1286             :       }
    1287             :       
    1288           0 :       padCenterXB = fPadData[idCentralB].fRealX; 
    1289             :       // if(fPadData[idCentralB].fDetElemId<204)
    1290             :       //        padCenterXB += 0.095*sin(10.5*(padCenterXB - fPadData[idCentralB].fRealX)) ;
    1291             :       // else //if(fPadData[idCentralNB].fDetElemId>=300 && fPadData[idCentralNB].fDetElemId<404)
    1292             :       //        padCenterXB += 0.085*sin(9.0*(padCenterXB - fPadData[idCentralB].fRealX)) ;
    1293             :             
    1294             :       // First check that we have not overflowed the buffer.
    1295           0 :       if((*fRecPointsCount) == fMaxRecPointsCount){
    1296           0 :         HLTWarning("Number of RecHits (i.e. %d) exceeds the max number of RecHit limit %d."
    1297             :                  " Output buffer is too small.",
    1298             :                  (*fRecPointsCount),fMaxRecPointsCount
    1299             :                  );
    1300           0 :         delete [] isMergedY;
    1301           0 :         delete [] isMergedX;
    1302           0 :         return true;
    1303             :       }
    1304             :       
    1305           0 :       AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
    1306           0 :                  (fPadData[idCentralB].fDetElemId / 100) - 1,
    1307           0 :                  fPadData[idCentralB].fDetElemId
    1308             :               );
    1309           0 :       fRecPoints[(*fRecPointsCount)].fFlags = idflags;
    1310           0 :       fRecPoints[(*fRecPointsCount)].fX = padCenterXB;
    1311           0 :       fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
    1312           0 :       fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
    1313             :             
    1314           0 :       if (fGenerateClusterInfo)
    1315             :         {
    1316           0 :           if (fClusterCount >= fMaxClusters)
    1317             :             {
    1318           0 :               HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
    1319           0 :               delete [] isMergedY;
    1320           0 :               delete [] isMergedX;
    1321           0 :               return false;
    1322             :             }
    1323             :               
    1324           0 :           fClusters[fClusterCount].fId = (fNewClusterId << 5) | fDDL;
    1325             :               
    1326             :           // Increment the cluster ID and warp it around at 0x03FFFFFF since
    1327             :           // the bottom 5 bits are filled with the source DDL number and the
    1328             :           // sign bit in fClusters[fClusterCount].fId must be positive.
    1329           0 :           fNewClusterId = (fNewClusterId + 1) & 0x03FFFFFF;
    1330             :           
    1331           0 :           fClusters[fClusterCount].fHit = fRecPoints[(*fRecPointsCount)];
    1332           0 :           fClusters[fClusterCount].fDetElemId = fPadData[idCentralB].fDetElemId;
    1333           0 :           fClusters[fClusterCount].fNchannelsB = fNofBChannel[b];
    1334           0 :           fClusters[fClusterCount].fNchannelsNB = fNofBChannel[b];
    1335           0 :           fClusters[fClusterCount].fChargeB = fTotChargeY[b];
    1336           0 :           fClusters[fClusterCount].fChargeNB = fTotChargeY[b];
    1337           0 :           fClusterCount++;
    1338           0 :         }
    1339             :       
    1340           0 :       if (fGenerateChannelInfo)
    1341             :         {
    1342             :           // 3 by 3 pad structure around the central pad for the 2 planes.
    1343           0 :           int pad[2][3][3] = {{
    1344           0 :               {0,      0,      0},
    1345           0 :               {0, idCentralB,  0},
    1346           0 :               {0,      0,      0}
    1347           0 :             },{
    1348           0 :               {0,      0,      0},
    1349           0 :               {0,      0     , 0},
    1350           0 :               {0,      0,      0}
    1351             :             }};
    1352             :           
    1353             :           // Find the pad index numbers for the central pads and the pads surrounding them.
    1354             :           // All these pads would have contributed to the cluster as long as their charge is != 0.
    1355           0 :           if (fPadData[idCentralB].fIY > 0)
    1356           0 :             pad[0][0][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY-1][0];
    1357           0 :           if (fPadData[idCentralB].fIY < 236)
    1358           0 :             pad[0][2][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY+1][0];
    1359           0 :           if (fPadData[idCentralB].fIX > 0)
    1360             :             {
    1361           0 :               int idLeft = fGetIdTotalData[fPadData[idCentralB].fIX-1][fPadData[idCentralB].fIY][0];
    1362           0 :               pad[0][1][0] = idLeft;
    1363           0 :               if (fPadData[idLeft].fIY > 0)
    1364           0 :                 pad[0][0][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY-1][0];
    1365           0 :               if (fPadData[idLeft].fIY < 236)
    1366           0 :                 pad[0][2][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY+1][0];
    1367           0 :             }
    1368           0 :           if (fPadData[idCentralB].fIX < 335)
    1369             :             {
    1370           0 :               int idRight = fGetIdTotalData[fPadData[idCentralB].fIX+1][fPadData[idCentralB].fIY][0];
    1371           0 :               pad[0][1][2] = idRight;
    1372           0 :               if (fPadData[idRight].fIY > 0)
    1373           0 :                 pad[0][0][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY-1][0];
    1374           0 :               if (fPadData[idRight].fIY < 236)
    1375           0 :                 pad[0][2][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY+1][0];
    1376           0 :             }
    1377             : 
    1378             :           // For hits only in bending plane no need to copy the information to the non-bending side
    1379             :           // for(int i=0;i<3;i++)
    1380             :           //   for(int j=0;j<3;j++)
    1381             :           //     pad[1][i][j] = pad[0][i][j];
    1382             : 
    1383             :               
    1384           0 :           AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
    1385             :           
    1386             :           // Now generate the pad structures from all the pad indices found above.
    1387           0 :           for (int i = 0; i < 1; i++)
    1388           0 :             for (int j = 0; j < 3; j++)
    1389           0 :               for (int k = 0; k < 3; k++)
    1390             :                 {
    1391           0 :                   AliHLTMUONPad& p = fPadData[pad[i][j][k]];
    1392             :                   // Skip pads that have zero charge because they would not have
    1393             :                   // contributed to the cluster.
    1394           0 :                   if (p.fCharge <= 0) continue;
    1395             :                   
    1396           0 :                   UShort_t manuId; UChar_t channelId; UShort_t adc;
    1397           0 :                   AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
    1398             :                   
    1399           0 :                   fChannels[fChannelCount].fClusterId = clusterId;
    1400           0 :                   fChannels[fChannelCount].fBusPatch = p.fBusPatch;
    1401           0 :                   fChannels[fChannelCount].fManu = manuId;
    1402           0 :                   fChannels[fChannelCount].fChannelAddress = channelId;
    1403           0 :                   fChannels[fChannelCount].fSignal = adc;
    1404           0 :                   fChannels[fChannelCount].fRawDataWord = p.fRawData;
    1405           0 :                   fChannelCount++;
    1406           0 :                 }
    1407           0 :         }
    1408             :       
    1409             :       HLTDebug("Part 2 : Reconstructed hit (X,Y,Z) : (%f,%f,%f)",
    1410             :                fRecPoints[(*fRecPointsCount)].fX,
    1411             :                fRecPoints[(*fRecPointsCount)].fY,
    1412             :                fRecPoints[(*fRecPointsCount)].fZ
    1413             :                );
    1414           0 :       (*fRecPointsCount)++;
    1415             : 
    1416           0 :     }// condn on fRecY[b] !=  0.0
    1417             :   }// loop over B side;
    1418             : 
    1419             : 
    1420             :   //Hit only in non-bending plane and in zone 1 which has not merged and which has number of channels > 2 are considered as valid hits
    1421           0 :   for(int nb=0;nb<fCentralCountNB;nb++){
    1422             : 
    1423           0 :     idCentralNB = fCentralChargeNB[nb];
    1424           0 :     if(fRecX[nb]!=outsideSpacePoint and !isMergedX[nb] and fNofNBChannel[nb]>2){
    1425             :       
    1426           0 :       minPadArea = (fPadData[idCentralNB].fDetElemId < 204) ? 10.0*2.0*0.315*10.0*2.0*0.21 : 10.0*2.0*0.375*10.0*2.0*0.25 ;
    1427             : 
    1428           0 :       if(TMath::Abs(400.0*fPadData[idCentralNB].fHalfPadSize*fPadData[idCentralNB].fPadSizeXY - minPadArea)> 1.0e-5) continue;
    1429             :       
    1430           0 :       padCenterYNB = fPadData[idCentralNB].fRealY;
    1431             :       
    1432             :       
    1433             :       // if(fPadData[idCentralNB].fDetElemId<104)
    1434             :       //        padCenterYNB += 0.02*sin(14.5*(padCenterYNB - fPadData[idCentralNB].fRealY)) ;
    1435             :       // else if(fPadData[idCentralNB].fDetElemId>=200 && fPadData[idCentralNB].fDetElemId<204)
    1436             :       //        padCenterYNB += 0.02*sin(14.0*(padCenterYNB - fPadData[idCentralNB].fRealY)) ;
    1437             :       // else
    1438             :       //        padCenterYNB += 0.025*sin(12.0*(padCenterYNB - fPadData[idCentralNB].fRealY)) ;
    1439             :       
    1440             :       
    1441           0 :       if(fPadData[idCentralNB].fDetElemId<204)
    1442           0 :         fRecX[nb] += 0.095*sin(10.5*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
    1443             :       else //if(fPadData[idCentralNB].fDetElemId>=300 && fPadData[idCentralNB].fDetElemId<404)
    1444           0 :         fRecX[nb] += 0.085*sin(9.0*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
    1445             :       
    1446             :       
    1447             :       // First check that we have not overflowed the buffer.
    1448           0 :       if((*fRecPointsCount) == fMaxRecPointsCount){
    1449           0 :         HLTWarning("Number of RecHits (i.e. %d) exceeds the max number of RecHit limit %d."
    1450             :                  " Output buffer is too small.",
    1451             :                  (*fRecPointsCount),fMaxRecPointsCount
    1452             :                  );
    1453           0 :         delete [] isMergedY;
    1454           0 :         delete [] isMergedX;
    1455           0 :         return true;
    1456             :       }
    1457             : 
    1458           0 :       AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
    1459           0 :                  (fPadData[idCentralNB].fDetElemId / 100) - 1,
    1460           0 :                  fPadData[idCentralNB].fDetElemId
    1461             :               );
    1462           0 :       fRecPoints[(*fRecPointsCount)].fFlags = idflags;
    1463           0 :       fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
    1464           0 :       fRecPoints[(*fRecPointsCount)].fY = padCenterYNB;
    1465           0 :       fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralNB].fRealZ;
    1466             :       
    1467           0 :       if (fGenerateClusterInfo)
    1468             :         {
    1469           0 :           if (fClusterCount >= fMaxClusters)
    1470             :             {
    1471           0 :               HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
    1472           0 :               delete [] isMergedY;
    1473           0 :               delete [] isMergedX;
    1474           0 :               return false;
    1475             :             }
    1476             :           
    1477           0 :           fClusters[fClusterCount].fId = (fNewClusterId << 5) | fDDL;
    1478             :           
    1479             :           // Increment the cluster ID and warp it around at 0x03FFFFFF since
    1480             :           // the bottom 5 bits are filled with the source DDL number and the
    1481             :           // sign bit in fClusters[fClusterCount].fId must be positive.
    1482           0 :           fNewClusterId = (fNewClusterId + 1) & 0x03FFFFFF;
    1483             :               
    1484           0 :           fClusters[fClusterCount].fHit = fRecPoints[(*fRecPointsCount)];
    1485           0 :           fClusters[fClusterCount].fDetElemId = fPadData[idCentralNB].fDetElemId;
    1486           0 :           fClusters[fClusterCount].fNchannelsB = fNofNBChannel[nb];
    1487           0 :           fClusters[fClusterCount].fNchannelsNB = fNofNBChannel[nb];
    1488           0 :           fClusters[fClusterCount].fChargeB = fTotChargeX[nb];
    1489           0 :           fClusters[fClusterCount].fChargeNB = fTotChargeX[nb];
    1490           0 :           fClusterCount++;
    1491           0 :         }
    1492             :       
    1493           0 :       if (fGenerateChannelInfo)
    1494             :         {
    1495             :           // 3 by 3 pad structure around the central pad for the 2 planes.
    1496           0 :           int pad[2][3][3] = {{
    1497           0 :               {0,      0,      0},
    1498           0 :               {0,      0,      0},
    1499           0 :               {0,      0,      0}
    1500           0 :                 },{
    1501           0 :               {0,      0,      0},
    1502           0 :               {0, idCentralNB, 0},
    1503           0 :               {0,      0,      0}
    1504             :             }};
    1505             :               
    1506             :           // Find the pad index numbers for the central pads and the pads surrounding them.
    1507             :           // All these pads would have contributed to the cluster as long as their charge is != 0.
    1508             :               
    1509           0 :           if (fPadData[idCentralNB].fIX > 0)
    1510           0 :             pad[1][1][0] = fGetIdTotalData[fPadData[idCentralNB].fIX-1][fPadData[idCentralNB].fIY][1];
    1511           0 :           if (fPadData[idCentralNB].fIX < 335)
    1512           0 :             pad[1][1][2] = fGetIdTotalData[fPadData[idCentralNB].fIX+1][fPadData[idCentralNB].fIY][1];
    1513           0 :           if (fPadData[idCentralNB].fIY > 0)
    1514             :             {
    1515           0 :               int idLower = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY-1][1];
    1516           0 :               pad[1][0][1] = idLower;
    1517           0 :               if (fPadData[idLower].fIX > 0)
    1518           0 :                 pad[1][0][0] = fGetIdTotalData[fPadData[idLower].fIX-1][fPadData[idLower].fIY][1];
    1519           0 :               if (fPadData[idLower].fIX < 335)
    1520           0 :                 pad[1][0][2] = fGetIdTotalData[fPadData[idLower].fIX+1][fPadData[idLower].fIY][1];
    1521           0 :             }
    1522           0 :           if (fPadData[idCentralNB].fIY < 236)
    1523             :             {
    1524           0 :               int idUpper = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY+1][1];
    1525           0 :                 pad[1][2][1] = idUpper;
    1526           0 :                 if (fPadData[idUpper].fIX > 0)
    1527           0 :                   pad[1][2][0] = fGetIdTotalData[fPadData[idUpper].fIX-1][fPadData[idUpper].fIY][1];
    1528           0 :                 if (fPadData[idUpper].fIX < 335)
    1529           0 :                   pad[1][2][2] = fGetIdTotalData[fPadData[idUpper].fIX+1][fPadData[idUpper].fIY][1];
    1530           0 :             }
    1531             : 
    1532             :           // For hits only in non-bending plane no need to copy the information to the bending side
    1533             :           // for(int i=0;i<3;i++)
    1534             :           //   for(int j=0;j<3;j++)
    1535             :           //     pad[0][i][j] = pad[1][i][j];
    1536             :           
    1537             :               
    1538           0 :           AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
    1539             :           
    1540             :           // Now generate the pad structures from all the pad indices found above.
    1541           0 :           for (int i = 1; i < 2; i++)
    1542           0 :             for (int j = 0; j < 3; j++)
    1543           0 :               for (int k = 0; k < 3; k++)
    1544             :                 {
    1545           0 :                   AliHLTMUONPad& p = fPadData[pad[i][j][k]];
    1546             :                   // Skip pads that have zero charge because they would not have
    1547             :                   // contributed to the cluster.
    1548           0 :                   if (p.fCharge <= 0) continue;
    1549             :                   
    1550           0 :                   UShort_t manuId; UChar_t channelId; UShort_t adc;
    1551           0 :                   AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
    1552             :                   
    1553           0 :                   fChannels[fChannelCount].fClusterId = clusterId;
    1554           0 :                   fChannels[fChannelCount].fBusPatch = p.fBusPatch;
    1555           0 :                   fChannels[fChannelCount].fManu = manuId;
    1556           0 :                   fChannels[fChannelCount].fChannelAddress = channelId;
    1557           0 :                   fChannels[fChannelCount].fSignal = adc;
    1558           0 :                   fChannels[fChannelCount].fRawDataWord = p.fRawData;
    1559           0 :                   fChannelCount++;
    1560           0 :                 }
    1561           0 :         }
    1562             :       
    1563             :       HLTDebug("Part 3 : Reconstructed hit (X,Y,Z) : (%f,%f,%f), detelemId : %d",
    1564             :                  fRecPoints[(*fRecPointsCount)].fX,
    1565             :                  fRecPoints[(*fRecPointsCount)].fY,
    1566             :                  fRecPoints[(*fRecPointsCount)].fZ,
    1567             :                  fPadData[idCentralNB].fDetElemId
    1568             :                  );
    1569           0 :       (*fRecPointsCount)++;
    1570           0 :     }//if lies wihtin 5.0 mm
    1571             :   }// condn over fRecX ! = 0.0
    1572             : 
    1573           0 :   delete [] isMergedY;
    1574           0 :   delete [] isMergedX;
    1575             :   
    1576           0 :   return true;
    1577           0 : }
    1578             : 
    1579             : bool AliHLTMUONHitReconstructor::MergeSlatRecHits()
    1580             : {
    1581             :   // Merge reconstructed hits first over same plane then bending plane with non-bending plane
    1582             : 
    1583           0 :   assert( fRecX != NULL );
    1584           0 :   assert( fRecY != NULL );
    1585           0 :   assert( fAvgChargeX != NULL );
    1586           0 :   assert( fAvgChargeY != NULL );
    1587           0 :   assert( fTotChargeX != NULL );
    1588           0 :   assert( fTotChargeY != NULL );
    1589           0 :   assert( fNofBChannel != NULL );
    1590           0 :   assert( fNofNBChannel != NULL );
    1591           0 :   assert( fNofYNeighbour  != NULL );
    1592             : 
    1593             :   int idCentralB,idCentralNB ;
    1594             :   float padCenterXB;
    1595             :   float padCenterYNB;
    1596             :   float diffX,diffY;
    1597             :   float halfPadLengthX,halfPadLengthY;
    1598           0 :   bool *isMergedY = new bool[fCentralCountB];
    1599           0 :   bool *isMergedX = new bool[fCentralCountNB];
    1600             :   float outsideSpacePoint = 1000000.0 ; /// A space point outside the detector
    1601             : 
    1602             :   // MERGE Bending Plane hits, which are placed side by side
    1603           0 :   for(int i=0;i<fCentralCountB-1;i++){
    1604           0 :     isMergedY[i] = false;
    1605           0 :     if(fRecY[i] != outsideSpacePoint){
    1606           0 :       for(int j=i+1;j<fCentralCountB;j++){
    1607             :                  
    1608           0 :         if(fCentralChargeB[i]==fCentralChargeB[j]){
    1609           0 :           fRecY[j] = outsideSpacePoint;
    1610           0 :           continue;
    1611             :         }
    1612             :         else if(
    1613           0 :            (
    1614           0 :             fPadData[fCentralChargeB[i]].fIY == fPadData[fCentralChargeB[j]].fIY
    1615             :             )
    1616           0 :            &&
    1617             :            (
    1618           0 :             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX + 1
    1619           0 :             ||
    1620           0 :             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX - 1
    1621             :             )
    1622           0 :            &&
    1623           0 :            fRecY[j] != outsideSpacePoint
    1624           0 :            &&
    1625           0 :            fRecY[i] != outsideSpacePoint
    1626             :            ){
    1627             : 
    1628           0 :           if(fAvgChargeY[i] > fAvgChargeY[j]){
    1629           0 :             fRecY[i] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
    1630           0 :                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
    1631           0 :             fRecY[j] = outsideSpacePoint;
    1632           0 :           }
    1633             :           else{
    1634           0 :             fRecY[j] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
    1635             :                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
    1636           0 :             fRecY[i] = outsideSpacePoint;
    1637             : 
    1638             :           }// search for higher charge
    1639             :         }//pad position
    1640             :       }//j for loop
    1641           0 :     }//if fRecY[i] != outsideSpacePoint
    1642             :   }// i for loop
    1643           0 :   isMergedY[fCentralCountB-1] = false;
    1644             :   
    1645             :   // MERGE Non Bending Plane hits, which are placed side by side
    1646           0 :   for(int i=0;i<fCentralCountNB-1;i++){
    1647           0 :     isMergedX[i] = false;
    1648           0 :     if(fRecX[i] != 0.0){
    1649           0 :       for(int j=i+1;j<fCentralCountNB;j++){
    1650             : 
    1651           0 :         if(fCentralChargeNB[i]==fCentralChargeNB[j]){
    1652           0 :           fRecX[j] = outsideSpacePoint;
    1653           0 :           continue;
    1654             :         }
    1655             :         else if(
    1656           0 :            (
    1657           0 :             fPadData[fCentralChargeNB[i]].fIX == fPadData[fCentralChargeNB[j]].fIX
    1658             :             )
    1659           0 :            &&
    1660             :            (
    1661           0 :             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY + 1
    1662           0 :             ||
    1663           0 :             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY - 1
    1664             :             )
    1665           0 :            &&
    1666           0 :            fRecX[j] != outsideSpacePoint
    1667           0 :            &&
    1668           0 :            fRecX[i] != outsideSpacePoint
    1669             :            ){
    1670             : 
    1671           0 :           if(fAvgChargeX[i] > fAvgChargeX[j]){
    1672           0 :             fRecX[i] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
    1673           0 :                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
    1674           0 :             fRecX[j] = outsideSpacePoint;
    1675           0 :           }
    1676             :           else{
    1677           0 :             fRecX[j] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
    1678             :                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
    1679           0 :             fRecX[i] = outsideSpacePoint;
    1680             :           }// search for higher charge
    1681             :         }//pad position
    1682             :       }//j for loop
    1683           0 :     }//if fRecX[i] != outsideSpacePoint
    1684             :   }// i for loop
    1685           0 :   isMergedX[fCentralCountNB-1] = false;
    1686             : 
    1687             :   // Merge bending Plane hits with Non Bending
    1688           0 :   for(int b=0;b<fCentralCountB;b++){
    1689           0 :     if(fRecY[b]!=outsideSpacePoint){
    1690           0 :       idCentralB = fCentralChargeB[b];
    1691           0 :       padCenterXB = fPadData[idCentralB].fRealX; 
    1692             :       
    1693           0 :       halfPadLengthX = fPadData[idCentralB].fHalfPadSize ;
    1694             : 
    1695           0 :       for(int nb=0;nb<fCentralCountNB;nb++){
    1696           0 :         if(fRecX[nb]!=outsideSpacePoint){
    1697           0 :           idCentralNB = fCentralChargeNB[nb];
    1698             : 
    1699           0 :           padCenterYNB = fPadData[idCentralNB].fRealY;
    1700             : 
    1701           0 :           halfPadLengthY = fPadData[idCentralNB].fHalfPadSize ;
    1702             : 
    1703           0 :           if(fabsf(fRecX[nb]) > fabsf(padCenterXB))
    1704           0 :             diffX = fabsf(fRecX[nb]) -  fabsf(padCenterXB);
    1705             :           else
    1706           0 :             diffX = fabsf(padCenterXB) -  fabsf(fRecX[nb]);
    1707             :           
    1708           0 :           if(fabsf(padCenterYNB)>fabsf(fRecY[b]))
    1709           0 :             diffY = fabsf(padCenterYNB) - fabsf(fRecY[b]);
    1710             :           else
    1711           0 :             diffY =  fabsf(fRecY[b]) - fabsf(padCenterYNB);
    1712             : 
    1713           0 :           if(diffX < halfPadLengthX && diffY < halfPadLengthY ){//&& fPadData[idCentralB].fIY != 0){
    1714             :             
    1715           0 :             isMergedY[b] = true;
    1716           0 :             isMergedX[nb] = true;
    1717             :             
    1718           0 :             if(fNofYNeighbour[b]==2){
    1719           0 :               fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
    1720           0 :             }
    1721             :             
    1722           0 :             fRecX[nb] += 0.075*sin(9.5*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
    1723             :             
    1724             :             
    1725             :             // First check that we have not overflowed the buffer.
    1726           0 :             if((*fRecPointsCount) == fMaxRecPointsCount){
    1727           0 :               HLTWarning("Number of RecHits (i.e. %d) exceeds the max number of RecHit limit %d."
    1728             :                         " Output buffer is too small.",
    1729             :                        (*fRecPointsCount),fMaxRecPointsCount
    1730             :               );
    1731           0 :               delete [] isMergedY;
    1732           0 :               delete [] isMergedX;
    1733           0 :               return true;
    1734             :             }
    1735             : 
    1736           0 :             AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
    1737           0 :                  (fPadData[idCentralB].fDetElemId / 100) - 1,
    1738           0 :                  fPadData[idCentralB].fDetElemId
    1739             :               );
    1740           0 :             fRecPoints[(*fRecPointsCount)].fFlags = idflags;
    1741           0 :             fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
    1742           0 :             fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
    1743           0 :             fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
    1744             :             
    1745           0 :             if (fGenerateClusterInfo)
    1746             :             {
    1747           0 :               if (fClusterCount >= fMaxClusters)
    1748             :               {
    1749           0 :                 HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
    1750           0 :                 delete [] isMergedY;
    1751           0 :                 delete [] isMergedX;
    1752           0 :                 return false;
    1753             :               }
    1754             :               
    1755           0 :               fClusters[fClusterCount].fId = (fNewClusterId << 5) | fDDL;
    1756             :               
    1757             :               // Increment the cluster ID and warp it around at 0x03FFFFFF since
    1758             :               // the bottom 5 bits are filled with the source DDL number and the
    1759             :               // sign bit in fClusters[fClusterCount].fId must be positive.
    1760           0 :               fNewClusterId = (fNewClusterId + 1) & 0x03FFFFFF;
    1761             :               
    1762           0 :               fClusters[fClusterCount].fHit = fRecPoints[(*fRecPointsCount)];
    1763           0 :               fClusters[fClusterCount].fDetElemId = fPadData[idCentralB].fDetElemId;
    1764           0 :               fClusters[fClusterCount].fNchannelsB = fNofBChannel[b];
    1765           0 :               fClusters[fClusterCount].fNchannelsNB = fNofNBChannel[nb];
    1766           0 :               fClusters[fClusterCount].fChargeB = fTotChargeY[b];
    1767           0 :               fClusters[fClusterCount].fChargeNB = fTotChargeX[nb];
    1768           0 :               fClusterCount++;
    1769           0 :             }
    1770             :             
    1771           0 :             if (fGenerateChannelInfo)
    1772             :             {
    1773             :               // 3 by 3 pad structure around the central pad for the 2 planes.
    1774           0 :               int pad[2][3][3] = {{
    1775           0 :                   {0,      0,      0},
    1776           0 :                   {0, idCentralB,  0},
    1777           0 :                   {0,      0,      0}
    1778           0 :                 },{
    1779           0 :                   {0,      0,      0},
    1780           0 :                   {0, idCentralNB, 0},
    1781           0 :                   {0,      0,      0}
    1782             :               }};
    1783             :               
    1784             :               // Find the pad index numbers for the central pads and the pads surrounding them.
    1785             :               // All these pads would have contributed to the cluster as long as their charge is != 0.
    1786           0 :               if (fPadData[idCentralB].fIY > 0)
    1787           0 :                 pad[0][0][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY-1][0];
    1788           0 :               if (fPadData[idCentralB].fIY < 236)
    1789           0 :                 pad[0][2][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY+1][0];
    1790           0 :               if (fPadData[idCentralB].fIX > 0)
    1791             :               {
    1792           0 :                 int idLeft = fGetIdTotalData[fPadData[idCentralB].fIX-1][fPadData[idCentralB].fIY][0];
    1793           0 :                 pad[0][1][0] = idLeft;
    1794           0 :                 if (fPadData[idLeft].fIY > 0)
    1795           0 :                   pad[0][0][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY-1][0];
    1796           0 :                 if (fPadData[idLeft].fIY < 236)
    1797           0 :                   pad[0][2][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY+1][0];
    1798           0 :               }
    1799           0 :               if (fPadData[idCentralB].fIX < 335)
    1800             :               {
    1801           0 :                 int idRight = fGetIdTotalData[fPadData[idCentralB].fIX+1][fPadData[idCentralB].fIY][0];
    1802           0 :                 pad[0][1][2] = idRight;
    1803           0 :                 if (fPadData[idRight].fIY > 0)
    1804           0 :                   pad[0][0][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY-1][0];
    1805           0 :                 if (fPadData[idRight].fIY < 236)
    1806           0 :                   pad[0][2][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY+1][0];
    1807           0 :               }
    1808             :               
    1809           0 :               if (fPadData[idCentralNB].fIX > 0)
    1810           0 :                 pad[1][1][0] = fGetIdTotalData[fPadData[idCentralNB].fIX-1][fPadData[idCentralNB].fIY][1];
    1811           0 :               if (fPadData[idCentralNB].fIX < 335)
    1812           0 :                 pad[1][1][2] = fGetIdTotalData[fPadData[idCentralNB].fIX+1][fPadData[idCentralNB].fIY][1];
    1813           0 :               if (fPadData[idCentralNB].fIY > 0)
    1814             :               {
    1815           0 :                 int idLower = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY-1][1];
    1816           0 :                 pad[1][0][1] = idLower;
    1817           0 :                 if (fPadData[idLower].fIX > 0)
    1818           0 :                   pad[1][0][0] = fGetIdTotalData[fPadData[idLower].fIX-1][fPadData[idLower].fIY][1];
    1819           0 :                 if (fPadData[idLower].fIX < 335)
    1820           0 :                   pad[1][0][2] = fGetIdTotalData[fPadData[idLower].fIX+1][fPadData[idLower].fIY][1];
    1821           0 :               }
    1822           0 :               if (fPadData[idCentralNB].fIY < 236)
    1823             :               {
    1824           0 :                 int idUpper = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY+1][1];
    1825           0 :                 pad[1][2][1] = idUpper;
    1826           0 :                 if (fPadData[idUpper].fIX > 0)
    1827           0 :                   pad[1][2][0] = fGetIdTotalData[fPadData[idUpper].fIX-1][fPadData[idUpper].fIY][1];
    1828           0 :                 if (fPadData[idUpper].fIX < 335)
    1829           0 :                   pad[1][2][2] = fGetIdTotalData[fPadData[idUpper].fIX+1][fPadData[idUpper].fIY][1];
    1830           0 :               }
    1831             :               
    1832           0 :               AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
    1833             :               
    1834             :               // Now generate the pad structures from all the pad indices found above.
    1835           0 :               for (int i = 0; i < 2; i++)
    1836           0 :               for (int j = 0; j < 3; j++)
    1837           0 :               for (int k = 0; k < 3; k++)
    1838             :               {
    1839           0 :                 AliHLTMUONPad& p = fPadData[pad[i][j][k]];
    1840             :                 // Skip pads that have zero charge because they would not have
    1841             :                 // contributed to the cluster.
    1842           0 :                 if (p.fCharge <= 0) continue;
    1843             :                 
    1844           0 :                 UShort_t manuId; UChar_t channelId; UShort_t adc;
    1845           0 :                 AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
    1846             :                 
    1847           0 :                 fChannels[fChannelCount].fClusterId = clusterId;
    1848           0 :                 fChannels[fChannelCount].fBusPatch = p.fBusPatch;
    1849           0 :                 fChannels[fChannelCount].fManu = manuId;
    1850           0 :                 fChannels[fChannelCount].fChannelAddress = channelId;
    1851           0 :                 fChannels[fChannelCount].fSignal = adc;
    1852           0 :                 fChannels[fChannelCount].fRawDataWord = p.fRawData;
    1853           0 :                 fChannelCount++;
    1854           0 :               }
    1855           0 :             }
    1856             : 
    1857             :             HLTDebug("Part 4(Slat) : Reconstructed hit (X,Y,Z) : (%f,%f,%f)",
    1858             :                      fRecPoints[(*fRecPointsCount)].fX,
    1859             :                      fRecPoints[(*fRecPointsCount)].fY,
    1860             :                      fRecPoints[(*fRecPointsCount)].fZ
    1861             :             );
    1862           0 :             (*fRecPointsCount)++;
    1863           0 :           }//if lies wihtin 5.0 mm
    1864             :         }// condn over fRecX ! = 0.0
    1865             :       }// loop over NB side
    1866             :     }// condn on fRecY[b] !=  0.0
    1867             :   }// loop over B side;
    1868             :   
    1869             :   
    1870           0 :   delete [] isMergedY;
    1871           0 :   delete [] isMergedX;
    1872           0 :   return true;
    1873           0 : }
    1874             : 
    1875             : 
    1876             : void AliHLTMUONHitReconstructor::Clear()
    1877             : {
    1878             :   // function to clear internal arrays.
    1879             : 
    1880             :   HLTDebug("Clearing fPadData and fNofDataInDetElem buffers.");
    1881             : 
    1882             : 
    1883           0 :   for(int iPad=1;iPad<fDigitPerDDL;iPad++){
    1884           0 :     fGetIdTotalData[fPadData[iPad].fIX][fPadData[iPad].fIY][fPadData[iPad].fPlane] = 0;
    1885           0 :     fPadData[iPad].fDetElemId = 0;
    1886           0 :     fPadData[iPad].fIX = 0 ;
    1887           0 :     fPadData[iPad].fIY = 0 ;
    1888           0 :     fPadData[iPad].fRealX = 0.0 ;
    1889           0 :     fPadData[iPad].fRealY = 0.0 ;
    1890           0 :     fPadData[iPad].fRealZ = 0.0 ;
    1891           0 :     fPadData[iPad].fHalfPadSize = -1 ;
    1892           0 :     fPadData[iPad].fPlane = 0 ;
    1893           0 :     fPadData[iPad].fCharge = 0 ;
    1894           0 :     fPadData[iPad].fBusPatch = -1;
    1895           0 :     fPadData[iPad].fRawData = 0;
    1896             :   }  
    1897             : 
    1898           0 :   for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
    1899           0 :     fNofDataInDetElem[idet] = 0;
    1900             :   
    1901             :   // for(int i=0;i<130;i++)
    1902             :   //   fMaxFiredPerDetElem[i] = 0;
    1903           0 : }
    1904             : 
    1905             : 
    1906             : AliHLTInt32_t AliHLTMUONHitReconstructor::GetkNofDetElemInDDL(Int_t iDDL)
    1907             : {
    1908             :         /// Returns the number of detection elements for a DDL.
    1909             :         
    1910           0 :         if(iDDL>=0 && iDDL<=19)
    1911           0 :                 return fgkNofDetElemInDDL[iDDL];
    1912             :         else
    1913           0 :                 return -1;
    1914           0 : }
    1915             : 
    1916             : 
    1917             : AliHLTInt32_t AliHLTMUONHitReconstructor::GetkMinDetElemIdInDDL(Int_t iDDL)
    1918             : {
    1919             :         /// Returns the first detection element ID for a DDL.
    1920             :         
    1921           0 :         if(iDDL>=0 && iDDL<=19)
    1922           0 :                 return fgkMinDetElemIdInDDL[iDDL];
    1923             :         else
    1924           0 :                 return -1;
    1925           0 : }
    1926             : 
    1927             : 
    1928           0 : AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::AliHLTMUONRawDecoder() :
    1929           0 :         fkBufferStart(NULL),
    1930           0 :         fBusPatchId(0),
    1931           0 :         fDCCut(-1),
    1932           0 :         fPadData(NULL),
    1933           0 :         fkLookUpTableData(NULL),
    1934           0 :         fkIdToEntry(),
    1935           0 :         fkMaxEntryPerBusPatch(),
    1936           0 :         fDDL(-1),
    1937           0 :         fDataCount(1),
    1938           0 :         fPrevDetElemId(0),
    1939           0 :         fPadCharge(0),
    1940           0 :         fCharge(0.0),
    1941           0 :         fIdManuChannel(0x0),
    1942           0 :         fLutEntry(0),
    1943           0 :         fDataCountListPerDetElem(NULL),
    1944           0 :         fNofDataInDetElem(NULL),
    1945           0 :         fWarnOnly(false),
    1946           0 :         fSkipParityErrors(false),
    1947           0 :         fDontPrintParityErrors(false),
    1948           0 :         fPrintParityErrorAsWarning(false),
    1949           0 :         fParityErrorFound(false),
    1950           0 :         fNonParityErrorFound(false),
    1951           0 :         fIsMuchNoisy(false)
    1952           0 : {
    1953             :         // ctor
    1954           0 : }
    1955             : 
    1956             : 
    1957           0 : AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::~AliHLTMUONRawDecoder()
    1958           0 : {
    1959             :         // dtor
    1960           0 : }
    1961             : 
    1962             : 
    1963             : void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnNewBuffer(const void* buffer, UInt_t /*bufferSize*/)
    1964             : {
    1965             :         /// Called for every new raw DDL data payload being processed.
    1966             :         /// Just clears internal counters.
    1967             :         /// \param buffer  The pointer to the raw data buffer.
    1968             : 
    1969           0 :         assert( buffer != NULL );
    1970           0 :         fkBufferStart = buffer;
    1971             :         // dataCount starts from 1 because the 0-th element of fPadData is used as null value.
    1972           0 :         fDataCount = 1;
    1973           0 :         for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
    1974           0 :           fNofDataInDetElem[idet] = 0;
    1975           0 :         fPrevDetElemId = 0;
    1976           0 :         fParityErrorFound = false;
    1977           0 :         fNonParityErrorFound = false;
    1978           0 : };
    1979             : 
    1980             : 
    1981             : void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnError(ErrorCode code, const void* location)
    1982             : {
    1983             :         /// Called if there was an error detected in the raw DDL data.
    1984             :         /// Logs an error message.
    1985             :         /// \param code  The error code describing the problem.
    1986             :         /// \param location  A pointer to the location in the raw data buffer
    1987             :         ///      where the problem was found.
    1988             :         
    1989           0 :         if (code == kParityError)
    1990             :         {
    1991           0 :                 fParityErrorFound = true;
    1992           0 :         }
    1993             :         else
    1994             :         {
    1995           0 :                 fNonParityErrorFound = true;
    1996             :         }
    1997           0 :         if (fDontPrintParityErrors and code == kParityError) return;
    1998             :         
    1999           0 :         long bytepos = long(location) - long(fkBufferStart);
    2000           0 :         if (fWarnOnly or (fPrintParityErrorAsWarning and code == kParityError))
    2001             :         {
    2002           0 :                 HLTWarning("There is a problem with decoding the raw data."
    2003             :                         " %s (Error code: %d, at byte %d). Trying to recover from corrupt data.",
    2004             :                         ErrorCodeToMessage(code), code, bytepos
    2005             :                 );
    2006             :         }
    2007             :         else
    2008             :         {
    2009           0 :                 HLTError("There is a problem with decoding the raw data. %s (Error code: %d, at byte %d)",
    2010             :                         ErrorCodeToMessage(code), code, bytepos
    2011             :                 );
    2012             :         }
    2013           0 : };
    2014             : 
    2015             : void  AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnNewBusPatch(const AliMUONBusPatchHeaderStruct* header, const void* /*data*/) 
    2016             : {
    2017             :   // operation to perform on new data
    2018           0 :   fBusPatchId = int(header->fBusPatchId);
    2019             :   MaxEntryPerBusPatch& maxEntryPerBusPatch 
    2020           0 :     = * const_cast<MaxEntryPerBusPatch*>(fkMaxEntryPerBusPatch);
    2021           0 :   fIsMuchNoisy = false;
    2022           0 :   if(AliHLTInt32_t(header->fLength)> maxEntryPerBusPatch[fBusPatchId])
    2023           0 :     fIsMuchNoisy = true;
    2024             :   
    2025           0 : };
    2026             : 
    2027             : void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnData(UInt_t dataWord, bool parityError)
    2028             : {
    2029             :   //function to arrange the decoded Raw Data
    2030             : 
    2031           0 :   if (fSkipParityErrors and parityError) return;
    2032             :   
    2033           0 :   if(fIsMuchNoisy) return;
    2034             : 
    2035           0 :   fIdManuChannel = 0x0;
    2036           0 :   fIdManuChannel = (fIdManuChannel|fBusPatchId)<<17;
    2037           0 :   fIdManuChannel |= (dataWord >> 12) & 0x1FFFF;
    2038             :   
    2039           0 :   IdManuChannelToEntry& idToEntry = * const_cast<IdManuChannelToEntry*>(fkIdToEntry);
    2040           0 :   fLutEntry = idToEntry[fIdManuChannel];
    2041           0 :   if(fLutEntry==0)
    2042             :   {
    2043             :     HLTDebug("Failed to find a valid LUT entry.");
    2044           0 :     return;
    2045             :   }
    2046           0 :   fPadCharge = int(((unsigned short)(dataWord & 0xFFF)) - fkLookUpTableData[fLutEntry].fPed);
    2047             :   
    2048           0 :   fCharge = 0;    
    2049           0 :   if(fPadCharge > 2.0*fkLookUpTableData[fLutEntry].fSigma){  // (charge > 4) is due cut out the noise level                       
    2050             :       
    2051           0 :     fPadData[fDataCount].fDetElemId = fkLookUpTableData[fLutEntry].fDetElemId;
    2052           0 :     fPadData[fDataCount].fIX = AliHLTInt32_t(AliHLTUInt32_t(fkLookUpTableData[fLutEntry].fIX) % 336);  // modulus protectes against overflow.
    2053           0 :     fPadData[fDataCount].fIY = AliHLTInt32_t(AliHLTUInt32_t(fkLookUpTableData[fLutEntry].fIY) % 237);  // modulus protectes against overflow.
    2054           0 :     fPadData[fDataCount].fRealX = fkLookUpTableData[fLutEntry].fRealX;
    2055           0 :     fPadData[fDataCount].fRealY = fkLookUpTableData[fLutEntry].fRealY;
    2056           0 :     fPadData[fDataCount].fRealZ = fkLookUpTableData[fLutEntry].fRealZ;
    2057           0 :     fPadData[fDataCount].fHalfPadSize = fkLookUpTableData[fLutEntry].fHalfPadSize;
    2058           0 :     fPadData[fDataCount].fPadSizeXY = fkLookUpTableData[fLutEntry].fPadSizeXY;
    2059           0 :     fPadData[fDataCount].fPlane = fkLookUpTableData[fLutEntry].fPlane & 0x1;  // The mask makes sure the plane value is within range.
    2060           0 :     fPadData[fDataCount].fBusPatch = fBusPatchId;
    2061           0 :     fPadData[fDataCount].fRawData = dataWord;
    2062             :     
    2063           0 :     if ( fPadCharge < fkLookUpTableData[fLutEntry].fThres ) {
    2064           0 :       fCharge = (fkLookUpTableData[fLutEntry].fA0)*fPadCharge;
    2065           0 :     }else{
    2066           0 :       fCharge = (fkLookUpTableData[fLutEntry].fA0)*(fkLookUpTableData[fLutEntry].fThres) 
    2067           0 :         + (fkLookUpTableData[fLutEntry].fA0)*(fPadCharge-fkLookUpTableData[fLutEntry].fThres) 
    2068           0 :         + (fkLookUpTableData[fLutEntry].fA1)*(fPadCharge-fkLookUpTableData[fLutEntry].fThres)*(fPadCharge-fkLookUpTableData[fLutEntry].fThres);
    2069             :     }
    2070             :     
    2071           0 :     fPadData[fDataCount].fCharge = fCharge;
    2072             :     
    2073           0 :     if(fkLookUpTableData[fLutEntry].fDetElemId/100 == 6){
    2074           0 :       fDataCountListPerDetElem[
    2075           0 :                                ((fkLookUpTableData[fLutEntry].fDetElemId-(GetkMinDetElemIdInDDL(fDDL)+100))%GetkNofDetElemInDDL(fDDL) 
    2076           0 :                                 + GetkNofDetElemInDDL(fDDL)/2)
    2077             :                                ]
    2078           0 :         [fNofDataInDetElem[((fkLookUpTableData[fLutEntry].fDetElemId-(GetkMinDetElemIdInDDL(fDDL)+100))%GetkNofDetElemInDDL(fDDL) 
    2079           0 :                             + GetkNofDetElemInDDL(fDDL)/2)
    2080           0 :                            ]++] = fDataCount;
    2081           0 :     }else{
    2082           0 :       fDataCountListPerDetElem[(fkLookUpTableData[fLutEntry].fDetElemId-GetkMinDetElemIdInDDL(fDDL))%GetkNofDetElemInDDL(fDDL)]
    2083           0 :         [fNofDataInDetElem[(fkLookUpTableData[fLutEntry].fDetElemId-GetkMinDetElemIdInDDL(fDDL))%GetkNofDetElemInDDL(fDDL)]++] = fDataCount;
    2084             :     }
    2085             :     
    2086             :     // if(fkLookUpTableData[fLutEntry].fDetElemId != fPrevDetElemId){
    2087             :     //   if((*fNofFiredDetElem)>0){
    2088             :     //  fMaxFiredPerDetElem[(*fNofFiredDetElem)-1] = fDataCount;
    2089             :     //   }
    2090             :     
    2091             :     //   HLTDebug("detElem : %d, prevDetElem : %d, datacount : %d, maxFiredPerDetElem[%d] : %d",
    2092             :     //            fkLookUpTableData[fLutEntry].fDetElemId,fPrevDetElemId,fDataCount,
    2093             :     //            ((*fNofFiredDetElem)-1),fMaxFiredPerDetElem[(*fNofFiredDetElem)-1]
    2094             :     //         );
    2095             :     
    2096             :     //   (*fNofFiredDetElem)++;
    2097             :     //   fPrevDetElemId =  fkLookUpTableData[fLutEntry].fDetElemId ;
    2098             :     // }
    2099             :     
    2100             :     //if(fPadData[fDataCount].fDetElemId==102)
    2101             :     
    2102             :     HLTDebug("%x, fLutEntry : %d, id : %d, (fDDL,buspatch,detele,plane) : (%2d,%4d,%4d,%1d) (manu,channel) : (%4d,%2d) \n(iX,iY) : (%3d,%3d) (X,Y) : (%f, %f, %f), adc : %d, charge : %f, ped : %f, sigma : %f, padsize : %f",
    2103             :                fkLookUpTableData,fLutEntry,fIdManuChannel,fDDL,
    2104             :                fBusPatchId,fPadData[fDataCount].fDetElemId,fPadData[fDataCount].fPlane,
    2105             :              ((dataWord >> 18) & 0x7FF),((dataWord >> 12) & 0x3F),
    2106             :              fPadData[fDataCount].fIX,fPadData[fDataCount].fIY,
    2107             :              fPadData[fDataCount].fRealX,fPadData[fDataCount].fRealY,fPadData[fDataCount].fRealZ,
    2108             :              (dataWord & 0xFFF),fPadData[fDataCount].fCharge,fkLookUpTableData[fLutEntry].fPed,fkLookUpTableData[fLutEntry].fSigma,
    2109             :              fkLookUpTableData[fLutEntry].fHalfPadSize);
    2110             :     
    2111             :     // HLTDebug("%x, fLutEntry : %d, buspatch : %d, detele : %d, id : %d, manu : %d, channel : %d, iX : %d, iY: %d, (X,Y) : (%f, %f, %f), charge : %f, padsize : %f, plane : %d, ped : %f, sigma : %f",
    2112             :     //       fkLookUpTableData,fLutEntry,fBusPatchId,fPadData[fDataCount].fDetElemId,
    2113             :     //       fIdManuChannel,((dataWord >> 18) & 0x7FF),((dataWord >> 12) & 0x3F),
    2114             :     //       fPadData[fDataCount].fIX,fPadData[fDataCount].fIY,
    2115             :     //       fPadData[fDataCount].fRealX,fPadData[fDataCount].fRealY,fPadData[fDataCount].fRealZ,
    2116             :     //       fPadData[fDataCount].fCharge,fkLookUpTableData[fLutEntry].fHalfPadSize,fPadData[fDataCount].fPlane,fkLookUpTableData[fLutEntry].fPed,fkLookUpTableData[fLutEntry].fSigma);
    2117             :     
    2118           0 :     fDataCount++;
    2119           0 :   }// if charge is more than DC Cut limit condition
    2120             :   
    2121           0 : }

Generated by: LCOV version 1.11