]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/OnlineAnalysis/AliHLTMUONHitReconstructor.cxx
Applying fixes and updates (Indra)
[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(int* rawData, int *rawDataSize, AliHLTMUONRecHitStruct recHit[], int *nofHit) 
190 {  
191   // main function called by HLTReconstructor to perform DHLT Hitreconstruction 
192
193   fRecPoints = &recHit[0];
194   fMaxRecPointsCount = *nofHit;
195   fRecPointsCount = nofHit;
196   *fRecPointsCount = 0;
197
198   fPadData[0].fDetElemId = 0;
199   fPadData[0].fBuspatchId = 0;
200   fPadData[0].fIdManuChannel = 0;
201   fPadData[0].fIX = 0 ;
202   fPadData[0].fIY = 0 ;
203   fPadData[0].fRealX = 0.0 ;
204   fPadData[0].fRealY = 0.0 ;
205   fPadData[0].fRealZ = 0.0 ;
206   fPadData[0].fPlane = -1 ;
207   fPadData[0].fPcbZone = -1 ;
208   fPadData[0].fCharge = 0 ;
209
210
211   if(!ReadDDL(rawData,rawDataSize)){
212     HLTError("Failed to read the complete DDL file");
213     return false;
214   }
215
216   if(!FindRecHits()){
217     HLTError("Failed to generate RecHits");
218     return false;
219   }
220     
221   return true;
222 }
223
224
225 bool AliHLTMUONHitReconstructor::ReadDDL(int *rawData, int *rawDataSize)
226 {
227   //function to read Raw Data files
228
229   int ddlRawDataSize;
230   ddlRawDataSize = *rawDataSize;
231
232   int *buffer = rawData ;
233   //new int[ddlRawDataSize]; 
234   //buffer = (int *)rawData; 
235
236   fIdOffSet= fgkMinIdManuChannel[(fDDLId%2)];
237   fDetManuChannelIdList = new int[ddlRawDataSize];
238
239   int index = 0;
240   int dataCount = 0;
241   fNofFiredDetElem = 0;
242   int detElemId = 0 ;
243   int buspatchId = 0;
244   int prevDetElemId = 0 ;
245   int totalBlockSize,blockRawDataSize;
246   int totalDspSize,dspRawDataSize;
247   int totalBuspatchSize,buspatchRawDataSize;
248   int indexDsp,indexBuspatch,indexRawData;
249   unsigned int dataWord;
250   int charge;
251   int idManuChannel;
252   
253   for(int iBlock = 0; iBlock < 2 ;iBlock++){  // loop over 2 blocks
254     totalBlockSize = buffer[index + 1];
255     blockRawDataSize = buffer[index + 2];
256     indexDsp = index + fkBlockHeaderSize;
257     while(blockRawDataSize > 0){
258       totalDspSize = buffer[indexDsp + 1];
259       dspRawDataSize = buffer[indexDsp + 2];
260       //if(buffer[indexDsp+1] == 1)
261       dspRawDataSize --;                              // temporary solution to read buspatches 
262       indexBuspatch = indexDsp + fkDspHeaderSize + 2; // this extra 2 word comes from the faulty defination of Dsp header size
263       while(dspRawDataSize > 0){
264         totalBuspatchSize = buffer[indexBuspatch + 1];
265         buspatchRawDataSize = buffer[indexBuspatch + 2];
266         buspatchId = buffer[indexBuspatch + 3];
267         if((detElemId = fBusToDetElem[buspatchId])==0){
268           HLTError("No Detection element found for buspatch : %d",buspatchId);
269           return false;
270         }
271         indexRawData = indexBuspatch + fkBuspatchHeaderSize;
272         while(buspatchRawDataSize > 0){
273           dataWord = buffer[indexRawData];
274           charge = (unsigned short)(dataWord & 0xFFF);
275           
276           idManuChannel = 0x0;
277           idManuChannel = (idManuChannel|(detElemId%100))<<17;
278           idManuChannel |= (dataWord >> 12) & 0x1FFFF;
279           idManuChannel -= fIdOffSet ;
280           
281           if(charge > fDCCut && charge > 5){  // (charge > 4) is due cut out the noise level                    
282             fPadData[idManuChannel].fBuspatchId = buspatchId;
283             fPadData[idManuChannel].fDetElemId = detElemId;
284             fPadData[idManuChannel].fIdManuChannel = idManuChannel;
285             fPadData[idManuChannel].fIX = fLookUpTableData[idManuChannel+1].fIX;
286             fPadData[idManuChannel].fIY = fLookUpTableData[idManuChannel+1].fIY;
287             fPadData[idManuChannel].fRealX = fLookUpTableData[idManuChannel+1].fRealX;
288             fPadData[idManuChannel].fRealY = fLookUpTableData[idManuChannel+1].fRealY;
289             fPadData[idManuChannel].fRealZ = fLookUpTableData[idManuChannel+1].fRealZ;
290             fPadData[idManuChannel].fPcbZone = fLookUpTableData[idManuChannel+1].fPcbZone;
291             fPadData[idManuChannel].fPlane = fLookUpTableData[idManuChannel+1].fPlane;
292             fPadData[idManuChannel].fCharge = charge;
293             
294             fDetManuChannelIdList[dataCount] = idManuChannel;
295             if(detElemId != prevDetElemId){
296               if(fNofFiredDetElem>0){
297                 fMaxFiredPerDetElem[fNofFiredDetElem-1] = dataCount;
298               }
299               fNofFiredDetElem++;
300               prevDetElemId = detElemId ;
301             }
302             
303             HLTDebug("buspatch : %d, detele : %d, id : %d, manu : %d, channel : %d, X : %f, Y: %f",
304                     fPadData[idManuChannel].fBuspatchId,fPadData[idManuChannel].fDetElemId,
305                     idManuChannel,((dataWord >> 12) & 0x7FF),((dataWord >> 23) & 0x3F),
306                     fPadData[idManuChannel].fRealX,fPadData[idManuChannel].fRealY);
307
308             dataCount ++;
309           }
310           
311           
312           indexRawData++;
313           buspatchRawDataSize --;
314         }
315         indexBuspatch += totalBuspatchSize;
316         dspRawDataSize -= totalBuspatchSize;
317       }// buspatch loop
318       indexDsp += totalDspSize;
319       blockRawDataSize -= totalDspSize;
320     }// DSP loop
321     index = totalBlockSize;
322   }// Block loop
323   
324   //delete[] buffer;
325   
326   fDigitPerDDL = dataCount;
327   fMaxFiredPerDetElem[fNofFiredDetElem-1] = dataCount;
328     
329   return true;
330 }
331
332
333 bool AliHLTMUONHitReconstructor::FindRecHits() 
334 {
335   // fuction that calls hit reconstruction detector element-wise   
336
337   for(int iDet=0; iDet<fNofFiredDetElem ; iDet++){
338     
339     fCentralCountB = 0 ;
340     fCentralCountNB = 0 ;
341     fCentralChargeB = new int[fMaxFiredPerDetElem[iDet]];
342     fCentralChargeNB = new int[fMaxFiredPerDetElem[iDet]];
343     
344     if(iDet>0)
345       FindCentralHits(fMaxFiredPerDetElem[iDet-1],fMaxFiredPerDetElem[iDet]);
346     else
347       FindCentralHits(0,fMaxFiredPerDetElem[iDet]);
348     
349     RecXRecY();
350     if(!MergeRecHits()){
351       HLTError("Failed to merge hits\n");
352       return false;
353     }
354     
355     if(iDet==0)
356       for(int i=0;i<fMaxFiredPerDetElem[iDet];i++)
357         fGetIdTotalData[fPadData[fDetManuChannelIdList[i]].fIX][fPadData[fDetManuChannelIdList[i]].fIY][fPadData[fDetManuChannelIdList[i]].fPlane] = 0;
358     else
359       for(int i=fMaxFiredPerDetElem[iDet-1];i<fMaxFiredPerDetElem[iDet];i++)
360         fGetIdTotalData[fPadData[fDetManuChannelIdList[i]].fIX][fPadData[fDetManuChannelIdList[i]].fIY][fPadData[fDetManuChannelIdList[i]].fPlane] = 0;
361
362     //fDHLTTree->Fill();
363
364     delete []fCentralChargeB;
365     delete []fCentralChargeNB;
366
367   }
368     
369   //for(int iPad=fDataPerDetElem[i];iPad<fDataPerDetElem[i+1];iPad++){
370   for(int iPad=0;iPad<fDigitPerDDL;iPad++){
371     fGetIdTotalData[fPadData[fDetManuChannelIdList[iPad]].fIX][fPadData[fDetManuChannelIdList[iPad]].fIY][fPadData[fDetManuChannelIdList[iPad]].fPlane] = 0;
372     fPadData[fDetManuChannelIdList[iPad]].fDetElemId = 0;
373     fPadData[fDetManuChannelIdList[iPad]].fBuspatchId = 0;
374     fPadData[fDetManuChannelIdList[iPad]].fIdManuChannel = 0;
375     fPadData[fDetManuChannelIdList[iPad]].fIX = 0 ;
376     fPadData[fDetManuChannelIdList[iPad]].fIY = 0 ;
377     fPadData[fDetManuChannelIdList[iPad]].fRealX = 0.0 ;
378     fPadData[fDetManuChannelIdList[iPad]].fRealY = 0.0 ;
379     fPadData[fDetManuChannelIdList[iPad]].fRealZ = 0.0 ;
380     fPadData[fDetManuChannelIdList[iPad]].fPlane = -1 ;
381     fPadData[fDetManuChannelIdList[iPad]].fPcbZone = -1 ;
382     fPadData[fDetManuChannelIdList[iPad]].fCharge = 0 ;
383   }  
384   
385   for(int i=0;i<13;i++)
386     fMaxFiredPerDetElem[i] = 0;
387   delete []fDetManuChannelIdList;
388
389   return true;
390 }
391
392
393 void AliHLTMUONHitReconstructor::FindCentralHits(int minPadId, int maxPadId)
394 {
395   // to find central hit associated with each cluster
396
397   int b,nb;
398   int idManuChannelCentral;
399   bool hasFind;
400   int idManuChannel;
401   
402   for(int iPad=minPadId;iPad<maxPadId;iPad++){
403     idManuChannel   = fDetManuChannelIdList[iPad];
404     
405     
406     fGetIdTotalData[fPadData[idManuChannel].fIX]
407       [fPadData[idManuChannel].fIY]
408       [fPadData[idManuChannel].fPlane] = idManuChannel;
409     
410     if(fPadData[idManuChannel].fPlane == 0 ){//&& fPadData[idManuChannel].fIY > (0+1) && fPadData[idManuChannel].fIY < (79 - 1)){
411       //if(fPadData[idManuChannel].fIY > 0){
412       if(fCentralCountB>0){
413         hasFind = false;
414         for(b = 0;b<fCentralCountB;b++){
415           idManuChannelCentral = fCentralChargeB[b];
416           if(fPadData[idManuChannel].fIX == fPadData[idManuChannelCentral].fIX
417              &&
418              (fPadData[idManuChannel].fIY 
419               == fPadData[idManuChannelCentral].fIY + 1 
420               ||
421               fPadData[idManuChannel].fIY 
422               == fPadData[idManuChannelCentral].fIY + 2 
423               ||
424               fPadData[idManuChannel].fIY 
425               == fPadData[idManuChannelCentral].fIY - 2 
426               ||
427               fPadData[idManuChannel].fIY 
428               == fPadData[idManuChannelCentral].fIY - 1)){
429             
430             hasFind = true;
431             if(fPadData[idManuChannel].fCharge > fPadData[idManuChannelCentral].fCharge){
432               fCentralChargeB[b] = idManuChannel;
433             }// if condn on pad charge
434           }// if condon on pad position
435         }// for loop over b
436         if(!hasFind){
437           fCentralChargeB[fCentralCountB] = idManuChannel;
438           fCentralCountB++;
439         }
440       }
441       else{
442         fCentralChargeB[fCentralCountB] = idManuChannel;
443         fCentralCountB++;
444       }// check the size of centralHitB
445       for(b = 0;b<fCentralCountB;b++){
446         idManuChannelCentral = fCentralChargeB[b];
447       }
448       //}// if cond on iY > 2 (to avoid edge value pb)
449     }// B/Nb checking
450     else{
451       if(fCentralCountNB>0){
452         hasFind = false;
453         for(nb = 0;nb<fCentralCountNB;nb++){
454           idManuChannelCentral = fCentralChargeNB[nb];
455           if(fPadData[idManuChannel].fIY == fPadData[idManuChannelCentral].fIY
456              &&
457              (fPadData[idManuChannel].fIX 
458               == fPadData[idManuChannelCentral].fIX + 1 
459               ||
460               fPadData[idManuChannel].fIX
461               == fPadData[idManuChannelCentral].fIX + 2
462               ||
463               fPadData[idManuChannel].fIX
464               == fPadData[idManuChannelCentral].fIX - 2
465               ||
466               fPadData[idManuChannel].fIX
467               == fPadData[idManuChannelCentral].fIX - 1)){
468             
469             hasFind = true;       
470             if(fPadData[idManuChannel].fCharge > fPadData[idManuChannelCentral].fCharge){
471               fCentralChargeNB[nb] = idManuChannel;
472             }// if condn over to find higher charge
473           }// if condn over to find position
474         }// for loop over presently all nb values
475         if(!hasFind){
476           fCentralChargeNB[fCentralCountNB] = idManuChannel;
477           fCentralCountNB++;
478         }
479       }// centralHitNB size test
480       else{
481         fCentralChargeNB[fCentralCountNB] = idManuChannel;
482         fCentralCountNB++;
483       }// centralHitNB size test
484       
485     }// fill for bending and nonbending hit
486   }// detElemId loop
487 }
488
489
490 void AliHLTMUONHitReconstructor::RecXRecY()
491 {
492   // find reconstructed X and Y for each plane separately
493   int b,nb;
494   int idCentral;
495   int idLower = 0;
496   int idUpper = 0;
497   int idRight = 0;
498   int idLeft = 0;
499   fRecY = new float[fCentralCountB];
500   fRecX = new float[fCentralCountNB];
501   
502   fAvgChargeY = new float[fCentralCountB];
503   fAvgChargeX = new float[fCentralCountNB];
504
505   for(b=0;b<fCentralCountB;b++){
506     idCentral = fCentralChargeB[b];
507     
508     if(fPadData[idCentral].fIY==0)
509       idLower = 0;
510     else
511       idLower = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY-1][0];
512     
513     if(fPadData[idCentral].fIY==79)
514       idUpper = 0;
515     else
516       idUpper = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY+1][0];
517
518     fRecY[b] = (fPadData[idCentral].fRealY*fPadData[idCentral].fCharge
519                +
520                fPadData[idUpper].fRealY*fPadData[idUpper].fCharge
521                +
522                fPadData[idLower].fRealY*fPadData[idLower].fCharge
523                )/(fPadData[idCentral].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge) ;
524
525     fAvgChargeY[b] = fPadData[idCentral].fCharge;
526   
527
528     fRecY[b] += 0.025*sin(12.56637*(0.25-(fRecY[b] - fPadData[idCentral].fRealY))) ;
529   }
530       
531   for(nb=0;nb<fCentralCountNB;nb++){
532     idCentral = fCentralChargeNB[nb];
533
534     if(fPadData[idCentral].fIX==0)
535       idLeft = 0;
536     else
537       idLeft = fGetIdTotalData[fPadData[idCentral].fIX-1][fPadData[idCentral].fIY][1];
538     
539     if(fPadData[idCentral].fIX==335)
540       idRight = 0 ;
541     else
542       idRight = fGetIdTotalData[fPadData[idCentral].fIX+1][fPadData[idCentral].fIY][1];
543
544     fRecX[nb] = (fPadData[idCentral].fRealX*fPadData[idCentral].fCharge
545                  +
546                  fPadData[idRight].fRealX*fPadData[idRight].fCharge
547                  +
548                  fPadData[idLeft].fRealX*fPadData[idLeft].fCharge
549                  )/(fPadData[idCentral].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
550     
551
552     fAvgChargeX[nb] = fPadData[idCentral].fCharge;
553     
554   }
555 }
556
557
558 bool AliHLTMUONHitReconstructor::MergeRecHits()
559 {
560   // Merge reconstructed hits first over same plane then bending plane with non-bending plane
561
562   int idCentralB,idCentralNB ;
563   float padCenterXB;
564   float padCenterYNB;
565   float diffX,diffY;
566   float halfPadLengthX,halfPadLengthY;
567
568   // MERGE Bending Plane hits, which are placed side by side
569   for(int i=0;i<fCentralCountB-1;i++){
570     if(fRecY[i] != 0.0){
571       for(int j=i+1;j<fCentralCountB;j++){
572                  
573         if(fCentralChargeB[i]==fCentralChargeB[j]){
574           fRecY[j] = 0.0;
575           continue;
576         }
577         else if(
578            (
579             fPadData[fCentralChargeB[i]].fIY == fPadData[fCentralChargeB[j]].fIY
580             )
581            &&
582            (
583             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX + 1
584             ||
585             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX - 1
586             )
587            &&
588            fRecY[j] != 0.0
589            &&
590            fRecY[i] != 0.0
591            ){
592
593           if(fAvgChargeY[i] > fAvgChargeY[j]){
594             fRecY[i] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
595                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
596             fRecY[j] = 0.0;
597           }
598           else{
599             fRecY[j] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
600                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
601             fRecY[i] = 0.0;
602
603           }// search for higher charge
604         }//pad position
605       }//j for loop
606     }//if fRecY[i] != 0.0
607   }// i for loop
608   
609   // MERGE Non Bending Plane hits, which are place side by side
610   for(int i=0;i<fCentralCountNB-1;i++){
611     if(fRecX[i] != 0.0){
612       for(int j=i+1;j<fCentralCountNB;j++){
613
614         if(fCentralChargeNB[i]==fCentralChargeNB[j]){
615           fRecX[j] = 0.0;
616           continue;
617         }
618         else if(
619            (
620             fPadData[fCentralChargeNB[i]].fIX == fPadData[fCentralChargeNB[j]].fIX
621             )
622            &&
623            (
624             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY + 1
625             ||
626             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY - 1
627             )
628            &&
629            fRecX[j] != 0.0
630            &&
631            fRecX[i] != 0.0
632            ){
633
634           if(fAvgChargeX[i] > fAvgChargeX[j]){
635             fRecX[i] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
636                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
637             fRecX[j] = 0.0;
638           }
639           else{
640             fRecX[j] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
641                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
642             fRecX[i] = 0.0;
643           }// search for higher charge
644         }//pad position
645       }//j for loop
646     }//if fRecX[i] != 0.0
647   }// i for loop
648
649   // Merge bending Plane hits with Non Bending
650   for(int b=0;b<fCentralCountB;b++){
651     if(fRecY[b]!=0.0){
652       idCentralB = fCentralChargeB[b];
653       padCenterXB = fPadData[idCentralB].fRealX; 
654       
655       halfPadLengthX = fgkHalfPadSize[fPadData[idCentralB].fPcbZone] ;
656
657       for(int nb=0;nb<fCentralCountNB;nb++){
658         if(fRecX[nb]!=0.0){
659           idCentralNB = fCentralChargeNB[nb];
660
661           padCenterYNB = fPadData[idCentralNB].fRealY;
662
663           halfPadLengthY = fgkHalfPadSize[fPadData[idCentralNB].fPcbZone] ;
664
665           if(fabsf(fRecX[nb]) > fabsf(padCenterXB))
666             diffX = fabsf(fRecX[nb]) -  fabsf(padCenterXB);
667           else
668             diffX = fabsf(padCenterXB) -  fabsf(fRecX[nb]);
669           
670           if(fabsf(padCenterYNB)>fabsf(fRecY[b]))
671             diffY = fabsf(padCenterYNB) - fabsf(fRecY[b]);
672           else
673             diffY =  fabsf(fRecY[b]) - fabsf(padCenterYNB);
674
675           if(diffX < halfPadLengthX && diffY < halfPadLengthY ){//&& fPadData[idCentralB].fIY != 0){
676
677             //fRecPoints[(*fRecPointsCount)].fId = idCentralB;
678             fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
679             fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
680             fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
681             //fRecPoints[(*fRecPointsCount)].fDetElemId = (AliHLTUInt32_t)fPadData[idCentralB].fDetElemId;
682             (*fRecPointsCount)++;
683             if((*fRecPointsCount) == fMaxRecPointsCount){
684               HLTError("Nof RecHit (i.e. %d) exceeds the max nof RecHit limit %d\n",(*fRecPointsCount),fMaxRecPointsCount);
685               return false;
686             }
687           }//if lies wihtin 5.0 mm
688         }// condn over fRecX ! = 0.0
689       }// loop over NB side
690     }// condn on fRecY[b] !=  0.0
691   }// loop over B side;
692
693   delete []fRecX;
694   delete []fRecY;
695   
696   delete []fAvgChargeX;
697   delete []fAvgChargeY;
698
699   return true;
700 }