]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/OnlineAnalysis/AliHLTMUONHitReconstructor.cxx
Bug fix: The component was not behaving correctly when processing empty DDL data...
[u/mrichter/AliRoot.git] / HLT / MUON / OnlineAnalysis / AliHLTMUONHitReconstructor.cxx
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 <strings.h>
37 #include "AliHLTMUONHitReconstructor.h"
38 #include "AliHLTMUONRecHitsBlockStruct.h"
39
40
41 const int AliHLTMUONHitReconstructor::fgkDetectorId = 0xA00;
42 const int AliHLTMUONHitReconstructor::fgkDDLOffSet = 12 ;
43 const int AliHLTMUONHitReconstructor::fgkNofDDL = 8 ;
44
45 const int AliHLTMUONHitReconstructor::fgkDDLHeaderSize = 8;
46
47 const int AliHLTMUONHitReconstructor::fgkEvenLutSize = 1645632 + 1;
48 const int AliHLTMUONHitReconstructor::fgkOddLutSize = 3363840 + 1;
49
50 const int AliHLTMUONHitReconstructor::fgkLutLine[2] = {54208, 59648};
51
52 const int AliHLTMUONHitReconstructor::fgkMinIdManuChannel[2] = {917696, 64};
53 const int AliHLTMUONHitReconstructor::fgkMaxIdManuChannel[2] = {2563327, 3363903};
54
55 const float AliHLTMUONHitReconstructor::fgkHalfPadSize[3] = {1.25, 2.50, 5.00};
56
57
58 AliHLTMUONHitReconstructor::AliHLTMUONHitReconstructor():
59   fkBlockHeaderSize(8),
60   fkDspHeaderSize(8),
61   fkBuspatchHeaderSize(4),
62   fDCCut(0),
63   fPadData(NULL),
64   fLookUpTableData(NULL),
65   fRecPoints(NULL),
66   fRecPointsCount(NULL),
67   fMaxRecPointsCount(0),
68   fCentralCountB(0),
69   fCentralCountNB(0),
70   fIdOffSet(0),
71   fDDLId(0),
72   fDigitPerDDL(0),
73   fDetManuChannelIdList(NULL),
74   fCentralChargeB(NULL),
75   fCentralChargeNB(NULL),
76   fRecX(NULL),
77   fRecY(NULL),
78   fAvgChargeX(NULL),
79   fAvgChargeY(NULL),
80   fNofFiredDetElem(0),
81   fDebugLevel(0),
82   fBusToDetElem(),
83   fBusToDDL()
84 {
85   // ctor 
86   
87   if(AliHLTMUONHitReconstructor::fgkEvenLutSize > AliHLTMUONHitReconstructor::fgkOddLutSize){
88     fPadData = new DHLTPad[AliHLTMUONHitReconstructor::fgkEvenLutSize];
89   }
90   else{
91     fPadData = new DHLTPad[AliHLTMUONHitReconstructor::fgkOddLutSize];
92   }
93
94   fkBlockHeaderSize    = 8;
95   fkDspHeaderSize      = 8;
96   fkBuspatchHeaderSize = 4;
97
98   bzero(fGetIdTotalData,336*80*2*sizeof(int));
99 }
100
101
102 AliHLTMUONHitReconstructor::~AliHLTMUONHitReconstructor()
103 {
104   // dtor
105
106   delete []fPadData;
107   delete []fLookUpTableData;
108 }
109
110
111 int AliHLTMUONHitReconstructor::GetLutLine(int iDDL) const
112 {
113         return ( iDDL<16 ) ? fgkLutLine[0] : fgkLutLine[1] ;
114 }
115
116
117 bool AliHLTMUONHitReconstructor::LoadLookUpTable(DHLTLut* lookUpTableData, int lookUpTableId)
118 {
119   // function that loads LookUpTable (= position of each pad with electronic channel associated with it)
120
121   if(lookUpTableId<fgkDDLOffSet || lookUpTableId>= fgkDDLOffSet + fgkNofDDL){
122     HLTError("DDL number is out of range (must be %d<=iDDL<%d)\n",fgkDDLOffSet,fgkDDLOffSet+fgkNofDDL);
123     return false;
124   }
125   
126   fDDLId = lookUpTableId;
127
128   int lutSize = ((lookUpTableId%2)==0) ? fgkEvenLutSize : fgkOddLutSize ;
129   int nofLutLine = GetLutLine(lookUpTableId);
130   int idOffSet = fgkMinIdManuChannel[lookUpTableId%2];
131
132   int detManuChannelId;
133
134   fLookUpTableData = new DHLTLut[lutSize];
135
136   fLookUpTableData[0].fIdManuChannel = 0;
137   fLookUpTableData[0].fIX = 0 ;
138   fLookUpTableData[0].fIY = 0 ;
139   fLookUpTableData[0].fRealX = 0.0 ;
140   fLookUpTableData[0].fRealY = 0.0 ;
141   fLookUpTableData[0].fRealZ = 0.0 ;
142   fLookUpTableData[0].fPlane = -1 ;
143   fLookUpTableData[0].fPcbZone = -1 ;
144
145   for(int i=0; i<nofLutLine; i++){
146
147     detManuChannelId = lookUpTableData[i].fIdManuChannel - idOffSet + 1;
148     fLookUpTableData[detManuChannelId].fIdManuChannel = lookUpTableData[i].fIdManuChannel - idOffSet;
149     fLookUpTableData[detManuChannelId].fIX = lookUpTableData[i].fIX ;
150     fLookUpTableData[detManuChannelId].fIY = lookUpTableData[i].fIY ;
151     fLookUpTableData[detManuChannelId].fRealX = lookUpTableData[i].fRealX ;
152     fLookUpTableData[detManuChannelId].fRealY = lookUpTableData[i].fRealY ;
153     fLookUpTableData[detManuChannelId].fRealZ = lookUpTableData[i].fRealZ ;
154     fLookUpTableData[detManuChannelId].fPcbZone = lookUpTableData[i].fPcbZone ;
155     fLookUpTableData[detManuChannelId].fPlane = lookUpTableData[i].fPlane ;
156   }
157   return true;
158 }
159
160
161 bool AliHLTMUONHitReconstructor::SetBusToDetMap(BusToDetElem busToDetElem)
162 {
163
164   // function that loads BusPatch To Detection Element (SlatId) map
165
166   if(busToDetElem.size()==0)
167     return false;
168   else
169     fBusToDetElem = busToDetElem;
170   
171   return true;
172 }
173
174
175 bool AliHLTMUONHitReconstructor::SetBusToDDLMap(BusToDDL busToDDL)
176 {
177
178   // function that loads BusPatch To DDL Element (DDL) map
179
180   if(busToDDL.size()==0)
181     return false;
182   else
183     fBusToDDL = busToDDL;
184   
185   return true;
186 }
187
188
189 bool AliHLTMUONHitReconstructor::Run(
190                 const AliHLTUInt32_t* rawData,
191                 AliHLTUInt32_t rawDataSize,
192                 AliHLTMUONRecHitStruct* recHit,
193                 AliHLTUInt32_t& nofHit
194         ) 
195 {
196   // main function called by HLTReconstructor to perform DHLT Hitreconstruction 
197
198   fRecPoints = recHit;
199   fMaxRecPointsCount = nofHit;
200   fRecPointsCount = &nofHit;
201   *fRecPointsCount = 0;
202
203   fPadData[0].fDetElemId = 0;
204   fPadData[0].fBuspatchId = 0;
205   fPadData[0].fIdManuChannel = 0;
206   fPadData[0].fIX = 0 ;
207   fPadData[0].fIY = 0 ;
208   fPadData[0].fRealX = 0.0 ;
209   fPadData[0].fRealY = 0.0 ;
210   fPadData[0].fRealZ = 0.0 ;
211   fPadData[0].fPlane = -1 ;
212   fPadData[0].fPcbZone = -1 ;
213   fPadData[0].fCharge = 0 ;
214
215
216   if(!ReadDDL(rawData, rawDataSize)){
217     HLTError("Failed to read the complete DDL file");
218     return false;
219   }
220
221   if(!FindRecHits()){
222     HLTError("Failed to generate RecHits");
223     return false;
224   }
225     
226   return true;
227 }
228
229
230 bool AliHLTMUONHitReconstructor::ReadDDL(
231                 const AliHLTUInt32_t* rawData,
232                 AliHLTUInt32_t rawDataSize
233         )
234 {
235   //function to read Raw Data files
236
237   const int* buffer = reinterpret_cast<const int*>(rawData);
238
239   fIdOffSet= fgkMinIdManuChannel[(fDDLId%2)];
240   fDetManuChannelIdList = new int[rawDataSize];
241
242   int index = 0;
243   int dataCount = 0;
244   fNofFiredDetElem = 0;
245   int detElemId = 0 ;
246   int buspatchId = 0;
247   int prevDetElemId = 0 ;
248   int totalBlockSize,blockRawDataSize;
249   int totalDspSize,dspRawDataSize;
250   int totalBuspatchSize,buspatchRawDataSize;
251   int indexDsp,indexBuspatch,indexRawData;
252   unsigned int dataWord;
253   int charge;
254   int idManuChannel;
255   
256   for(int iBlock = 0; iBlock < 2 ;iBlock++){  // loop over 2 blocks
257     totalBlockSize = buffer[index + 1];
258     blockRawDataSize = buffer[index + 2];
259     indexDsp = index + fkBlockHeaderSize;
260     while(blockRawDataSize > 0){
261       totalDspSize = buffer[indexDsp + 1];
262       dspRawDataSize = buffer[indexDsp + 2];
263       //if(buffer[indexDsp+1] == 1)
264       dspRawDataSize --;                              // temporary solution to read buspatches 
265       indexBuspatch = indexDsp + fkDspHeaderSize + 2; // this extra 2 word comes from the faulty defination of Dsp header size
266       while(dspRawDataSize > 0){
267         totalBuspatchSize = buffer[indexBuspatch + 1];
268         buspatchRawDataSize = buffer[indexBuspatch + 2];
269         buspatchId = buffer[indexBuspatch + 3];
270         if((detElemId = fBusToDetElem[buspatchId])==0){
271           HLTError("No Detection element found for buspatch : %d",buspatchId);
272           return false;
273         }
274         indexRawData = indexBuspatch + fkBuspatchHeaderSize;
275         while(buspatchRawDataSize > 0){
276           dataWord = buffer[indexRawData];
277           charge = (unsigned short)(dataWord & 0xFFF);
278           
279           idManuChannel = 0x0;
280           idManuChannel = (idManuChannel|(detElemId%100))<<17;
281           idManuChannel |= (dataWord >> 12) & 0x1FFFF;
282           idManuChannel -= fIdOffSet ;
283           
284           if(charge > fDCCut && charge > 5){  // (charge > 4) is due cut out the noise level                    
285             fPadData[idManuChannel].fBuspatchId = buspatchId;
286             fPadData[idManuChannel].fDetElemId = detElemId;
287             fPadData[idManuChannel].fIdManuChannel = idManuChannel;
288             fPadData[idManuChannel].fIX = fLookUpTableData[idManuChannel+1].fIX;
289             fPadData[idManuChannel].fIY = fLookUpTableData[idManuChannel+1].fIY;
290             fPadData[idManuChannel].fRealX = fLookUpTableData[idManuChannel+1].fRealX;
291             fPadData[idManuChannel].fRealY = fLookUpTableData[idManuChannel+1].fRealY;
292             fPadData[idManuChannel].fRealZ = fLookUpTableData[idManuChannel+1].fRealZ;
293             fPadData[idManuChannel].fPcbZone = fLookUpTableData[idManuChannel+1].fPcbZone;
294             fPadData[idManuChannel].fPlane = fLookUpTableData[idManuChannel+1].fPlane;
295             fPadData[idManuChannel].fCharge = charge;
296             
297             fDetManuChannelIdList[dataCount] = idManuChannel;
298             if(detElemId != prevDetElemId){
299               if(fNofFiredDetElem>0){
300                 fMaxFiredPerDetElem[fNofFiredDetElem-1] = dataCount;
301               }
302               fNofFiredDetElem++;
303               prevDetElemId = detElemId ;
304             }
305             
306             HLTDebug("buspatch : %d, detele : %d, id : %d, manu : %d, channel : %d, X : %f, Y: %f",
307                     fPadData[idManuChannel].fBuspatchId,fPadData[idManuChannel].fDetElemId,
308                     idManuChannel,((dataWord >> 12) & 0x7FF),((dataWord >> 23) & 0x3F),
309                     fPadData[idManuChannel].fRealX,fPadData[idManuChannel].fRealY);
310
311             dataCount ++;
312           }
313           
314           
315           indexRawData++;
316           buspatchRawDataSize --;
317         }
318         indexBuspatch += totalBuspatchSize;
319         dspRawDataSize -= totalBuspatchSize;
320       }// buspatch loop
321       indexDsp += totalDspSize;
322       blockRawDataSize -= totalDspSize;
323     }// DSP loop
324     index = totalBlockSize;
325   }// Block loop
326   
327   //delete[] buffer;
328   
329   fDigitPerDDL = dataCount;
330   fMaxFiredPerDetElem[fNofFiredDetElem-1] = dataCount;
331     
332   return true;
333 }
334
335
336 bool AliHLTMUONHitReconstructor::FindRecHits() 
337 {
338   // fuction that calls hit reconstruction detector element-wise   
339
340   for(int iDet=0; iDet<fNofFiredDetElem ; iDet++){
341     
342     fCentralCountB = 0 ;
343     fCentralCountNB = 0 ;
344     fCentralChargeB = new int[fMaxFiredPerDetElem[iDet]];
345     fCentralChargeNB = new int[fMaxFiredPerDetElem[iDet]];
346     
347     if(iDet>0)
348       FindCentralHits(fMaxFiredPerDetElem[iDet-1],fMaxFiredPerDetElem[iDet]);
349     else
350       FindCentralHits(0,fMaxFiredPerDetElem[iDet]);
351     
352     RecXRecY();
353     if(!MergeRecHits()){
354       HLTError("Failed to merge hits\n");
355       return false;
356     }
357     
358     if(iDet==0)
359       for(int i=0;i<fMaxFiredPerDetElem[iDet];i++)
360         fGetIdTotalData[fPadData[fDetManuChannelIdList[i]].fIX][fPadData[fDetManuChannelIdList[i]].fIY][fPadData[fDetManuChannelIdList[i]].fPlane] = 0;
361     else
362       for(int i=fMaxFiredPerDetElem[iDet-1];i<fMaxFiredPerDetElem[iDet];i++)
363         fGetIdTotalData[fPadData[fDetManuChannelIdList[i]].fIX][fPadData[fDetManuChannelIdList[i]].fIY][fPadData[fDetManuChannelIdList[i]].fPlane] = 0;
364
365     //fDHLTTree->Fill();
366
367     delete []fCentralChargeB;
368     delete []fCentralChargeNB;
369
370   }
371     
372   //for(int iPad=fDataPerDetElem[i];iPad<fDataPerDetElem[i+1];iPad++){
373   for(int iPad=0;iPad<fDigitPerDDL;iPad++){
374     fGetIdTotalData[fPadData[fDetManuChannelIdList[iPad]].fIX][fPadData[fDetManuChannelIdList[iPad]].fIY][fPadData[fDetManuChannelIdList[iPad]].fPlane] = 0;
375     fPadData[fDetManuChannelIdList[iPad]].fDetElemId = 0;
376     fPadData[fDetManuChannelIdList[iPad]].fBuspatchId = 0;
377     fPadData[fDetManuChannelIdList[iPad]].fIdManuChannel = 0;
378     fPadData[fDetManuChannelIdList[iPad]].fIX = 0 ;
379     fPadData[fDetManuChannelIdList[iPad]].fIY = 0 ;
380     fPadData[fDetManuChannelIdList[iPad]].fRealX = 0.0 ;
381     fPadData[fDetManuChannelIdList[iPad]].fRealY = 0.0 ;
382     fPadData[fDetManuChannelIdList[iPad]].fRealZ = 0.0 ;
383     fPadData[fDetManuChannelIdList[iPad]].fPlane = -1 ;
384     fPadData[fDetManuChannelIdList[iPad]].fPcbZone = -1 ;
385     fPadData[fDetManuChannelIdList[iPad]].fCharge = 0 ;
386   }  
387   
388   for(int i=0;i<13;i++)
389     fMaxFiredPerDetElem[i] = 0;
390   delete []fDetManuChannelIdList;
391
392   return true;
393 }
394
395
396 void AliHLTMUONHitReconstructor::FindCentralHits(int minPadId, int maxPadId)
397 {
398   // to find central hit associated with each cluster
399
400   int b,nb;
401   int idManuChannelCentral;
402   bool hasFind;
403   int idManuChannel;
404   
405   for(int iPad=minPadId;iPad<maxPadId;iPad++){
406     idManuChannel   = fDetManuChannelIdList[iPad];
407     
408     
409     fGetIdTotalData[fPadData[idManuChannel].fIX]
410       [fPadData[idManuChannel].fIY]
411       [fPadData[idManuChannel].fPlane] = idManuChannel;
412     
413     if(fPadData[idManuChannel].fPlane == 0 ){//&& fPadData[idManuChannel].fIY > (0+1) && fPadData[idManuChannel].fIY < (79 - 1)){
414       //if(fPadData[idManuChannel].fIY > 0){
415       if(fCentralCountB>0){
416         hasFind = false;
417         for(b = 0;b<fCentralCountB;b++){
418           idManuChannelCentral = fCentralChargeB[b];
419           if(fPadData[idManuChannel].fIX == fPadData[idManuChannelCentral].fIX
420              &&
421              (fPadData[idManuChannel].fIY 
422               == fPadData[idManuChannelCentral].fIY + 1 
423               ||
424               fPadData[idManuChannel].fIY 
425               == fPadData[idManuChannelCentral].fIY + 2 
426               ||
427               fPadData[idManuChannel].fIY 
428               == fPadData[idManuChannelCentral].fIY - 2 
429               ||
430               fPadData[idManuChannel].fIY 
431               == fPadData[idManuChannelCentral].fIY - 1)){
432             
433             hasFind = true;
434             if(fPadData[idManuChannel].fCharge > fPadData[idManuChannelCentral].fCharge){
435               fCentralChargeB[b] = idManuChannel;
436             }// if condn on pad charge
437           }// if condon on pad position
438         }// for loop over b
439         if(!hasFind){
440           fCentralChargeB[fCentralCountB] = idManuChannel;
441           fCentralCountB++;
442         }
443       }
444       else{
445         fCentralChargeB[fCentralCountB] = idManuChannel;
446         fCentralCountB++;
447       }// check the size of centralHitB
448       for(b = 0;b<fCentralCountB;b++){
449         idManuChannelCentral = fCentralChargeB[b];
450       }
451       //}// if cond on iY > 2 (to avoid edge value pb)
452     }// B/Nb checking
453     else{
454       if(fCentralCountNB>0){
455         hasFind = false;
456         for(nb = 0;nb<fCentralCountNB;nb++){
457           idManuChannelCentral = fCentralChargeNB[nb];
458           if(fPadData[idManuChannel].fIY == fPadData[idManuChannelCentral].fIY
459              &&
460              (fPadData[idManuChannel].fIX 
461               == fPadData[idManuChannelCentral].fIX + 1 
462               ||
463               fPadData[idManuChannel].fIX
464               == fPadData[idManuChannelCentral].fIX + 2
465               ||
466               fPadData[idManuChannel].fIX
467               == fPadData[idManuChannelCentral].fIX - 2
468               ||
469               fPadData[idManuChannel].fIX
470               == fPadData[idManuChannelCentral].fIX - 1)){
471             
472             hasFind = true;       
473             if(fPadData[idManuChannel].fCharge > fPadData[idManuChannelCentral].fCharge){
474               fCentralChargeNB[nb] = idManuChannel;
475             }// if condn over to find higher charge
476           }// if condn over to find position
477         }// for loop over presently all nb values
478         if(!hasFind){
479           fCentralChargeNB[fCentralCountNB] = idManuChannel;
480           fCentralCountNB++;
481         }
482       }// centralHitNB size test
483       else{
484         fCentralChargeNB[fCentralCountNB] = idManuChannel;
485         fCentralCountNB++;
486       }// centralHitNB size test
487       
488     }// fill for bending and nonbending hit
489   }// detElemId loop
490 }
491
492
493 void AliHLTMUONHitReconstructor::RecXRecY()
494 {
495   // find reconstructed X and Y for each plane separately
496   int b,nb;
497   int idCentral;
498   int idLower = 0;
499   int idUpper = 0;
500   int idRight = 0;
501   int idLeft = 0;
502   fRecY = new float[fCentralCountB];
503   fRecX = new float[fCentralCountNB];
504   
505   fAvgChargeY = new float[fCentralCountB];
506   fAvgChargeX = new float[fCentralCountNB];
507
508   for(b=0;b<fCentralCountB;b++){
509     idCentral = fCentralChargeB[b];
510     
511     if(fPadData[idCentral].fIY==0)
512       idLower = 0;
513     else
514       idLower = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY-1][0];
515     
516     if(fPadData[idCentral].fIY==79)
517       idUpper = 0;
518     else
519       idUpper = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY+1][0];
520
521     fRecY[b] = (fPadData[idCentral].fRealY*fPadData[idCentral].fCharge
522                +
523                fPadData[idUpper].fRealY*fPadData[idUpper].fCharge
524                +
525                fPadData[idLower].fRealY*fPadData[idLower].fCharge
526                )/(fPadData[idCentral].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge) ;
527
528     fAvgChargeY[b] = fPadData[idCentral].fCharge;
529   
530
531     fRecY[b] += 0.025*sin(12.56637*(0.25-(fRecY[b] - fPadData[idCentral].fRealY))) ;
532   }
533       
534   for(nb=0;nb<fCentralCountNB;nb++){
535     idCentral = fCentralChargeNB[nb];
536
537     if(fPadData[idCentral].fIX==0)
538       idLeft = 0;
539     else
540       idLeft = fGetIdTotalData[fPadData[idCentral].fIX-1][fPadData[idCentral].fIY][1];
541     
542     if(fPadData[idCentral].fIX==335)
543       idRight = 0 ;
544     else
545       idRight = fGetIdTotalData[fPadData[idCentral].fIX+1][fPadData[idCentral].fIY][1];
546
547     fRecX[nb] = (fPadData[idCentral].fRealX*fPadData[idCentral].fCharge
548                  +
549                  fPadData[idRight].fRealX*fPadData[idRight].fCharge
550                  +
551                  fPadData[idLeft].fRealX*fPadData[idLeft].fCharge
552                  )/(fPadData[idCentral].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
553     
554
555     fAvgChargeX[nb] = fPadData[idCentral].fCharge;
556     
557   }
558 }
559
560
561 bool AliHLTMUONHitReconstructor::MergeRecHits()
562 {
563   // Merge reconstructed hits first over same plane then bending plane with non-bending plane
564
565   int idCentralB,idCentralNB ;
566   float padCenterXB;
567   float padCenterYNB;
568   float diffX,diffY;
569   float halfPadLengthX,halfPadLengthY;
570
571   // MERGE Bending Plane hits, which are placed side by side
572   for(int i=0;i<fCentralCountB-1;i++){
573     if(fRecY[i] != 0.0){
574       for(int j=i+1;j<fCentralCountB;j++){
575                  
576         if(fCentralChargeB[i]==fCentralChargeB[j]){
577           fRecY[j] = 0.0;
578           continue;
579         }
580         else if(
581            (
582             fPadData[fCentralChargeB[i]].fIY == fPadData[fCentralChargeB[j]].fIY
583             )
584            &&
585            (
586             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX + 1
587             ||
588             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX - 1
589             )
590            &&
591            fRecY[j] != 0.0
592            &&
593            fRecY[i] != 0.0
594            ){
595
596           if(fAvgChargeY[i] > fAvgChargeY[j]){
597             fRecY[i] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
598                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
599             fRecY[j] = 0.0;
600           }
601           else{
602             fRecY[j] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
603                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
604             fRecY[i] = 0.0;
605
606           }// search for higher charge
607         }//pad position
608       }//j for loop
609     }//if fRecY[i] != 0.0
610   }// i for loop
611   
612   // MERGE Non Bending Plane hits, which are place side by side
613   for(int i=0;i<fCentralCountNB-1;i++){
614     if(fRecX[i] != 0.0){
615       for(int j=i+1;j<fCentralCountNB;j++){
616
617         if(fCentralChargeNB[i]==fCentralChargeNB[j]){
618           fRecX[j] = 0.0;
619           continue;
620         }
621         else if(
622            (
623             fPadData[fCentralChargeNB[i]].fIX == fPadData[fCentralChargeNB[j]].fIX
624             )
625            &&
626            (
627             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY + 1
628             ||
629             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY - 1
630             )
631            &&
632            fRecX[j] != 0.0
633            &&
634            fRecX[i] != 0.0
635            ){
636
637           if(fAvgChargeX[i] > fAvgChargeX[j]){
638             fRecX[i] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
639                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
640             fRecX[j] = 0.0;
641           }
642           else{
643             fRecX[j] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
644                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
645             fRecX[i] = 0.0;
646           }// search for higher charge
647         }//pad position
648       }//j for loop
649     }//if fRecX[i] != 0.0
650   }// i for loop
651
652   // Merge bending Plane hits with Non Bending
653   for(int b=0;b<fCentralCountB;b++){
654     if(fRecY[b]!=0.0){
655       idCentralB = fCentralChargeB[b];
656       padCenterXB = fPadData[idCentralB].fRealX; 
657       
658       halfPadLengthX = fgkHalfPadSize[fPadData[idCentralB].fPcbZone] ;
659
660       for(int nb=0;nb<fCentralCountNB;nb++){
661         if(fRecX[nb]!=0.0){
662           idCentralNB = fCentralChargeNB[nb];
663
664           padCenterYNB = fPadData[idCentralNB].fRealY;
665
666           halfPadLengthY = fgkHalfPadSize[fPadData[idCentralNB].fPcbZone] ;
667
668           if(fabsf(fRecX[nb]) > fabsf(padCenterXB))
669             diffX = fabsf(fRecX[nb]) -  fabsf(padCenterXB);
670           else
671             diffX = fabsf(padCenterXB) -  fabsf(fRecX[nb]);
672           
673           if(fabsf(padCenterYNB)>fabsf(fRecY[b]))
674             diffY = fabsf(padCenterYNB) - fabsf(fRecY[b]);
675           else
676             diffY =  fabsf(fRecY[b]) - fabsf(padCenterYNB);
677
678           if(diffX < halfPadLengthX && diffY < halfPadLengthY ){//&& fPadData[idCentralB].fIY != 0){
679
680             // First check that we have not overflowed the buffer.
681             if((*fRecPointsCount) == fMaxRecPointsCount){
682               HLTError("Nof RecHit (i.e. %d) exceeds the max nof RecHit limit %d\n",(*fRecPointsCount),fMaxRecPointsCount);
683               return false;
684             }
685             
686             //fRecPoints[(*fRecPointsCount)].fId = idCentralB;
687             fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
688             fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
689             fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
690             //fRecPoints[(*fRecPointsCount)].fDetElemId = (AliHLTUInt32_t)fPadData[idCentralB].fDetElemId;
691             (*fRecPointsCount)++;
692           }//if lies wihtin 5.0 mm
693         }// condn over fRecX ! = 0.0
694       }// loop over NB side
695     }// condn on fRecY[b] !=  0.0
696   }// loop over B side;
697
698   delete []fRecX;
699   delete []fRecY;
700   
701   delete []fAvgChargeX;
702   delete []fAvgChargeY;
703
704   return true;
705 }