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