]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/OnlineAnalysis/AliHLTMUONHitReconstructor.cxx
74bcfdc3a8a316f4f74a2d02a703bfbf52758e29
[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 "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         AliHLTLogging(),
64         fHLTMUONDecoder(),
65         fkBlockHeaderSize(8),
66         fkDspHeaderSize(8),
67         fkBuspatchHeaderSize(4),
68         fDCCut(-1),
69         fPadData(NULL),
70         fkLookUpTableData(NULL),
71         fRecPoints(NULL),
72         fRecPointsCount(NULL),
73         fMaxRecPointsCount(0),
74         fClusters(NULL),
75         fClusterCount(0),
76         fMaxClusters(0),
77         fGenerateClusterInfo(false),
78         fNewClusterId(0),
79         fDDL(-1),
80         fChannels(NULL),
81         fChannelCount(0),
82         fMaxChannels(0),
83         fGenerateChannelInfo(false),
84         fMaxChannelMult(6),
85         fCentralCountB(0),
86         fCentralCountNB(0),
87         fDigitPerDDL(0),
88         fDataCountListPerDetElem(NULL),
89         fNofDataInDetElem(NULL),
90         fCentralChargeB(NULL),
91         fCentralChargeNB(NULL),
92         fRecX(NULL),
93         fRecY(NULL),
94         fAvgChargeX(NULL),
95         fAvgChargeY(NULL),
96         fTotChargeX(NULL),
97         fTotChargeY(NULL),
98         fNofBChannel(NULL),
99         fNofNBChannel(NULL),
100         fNofYNeighbour(NULL),
101         fkIdToEntry(),
102         fkMaxEntryPerBusPatch(0),
103         fRecoveryMode(kDontTryRecover)
104 {
105         /// Default constructor
106         
107         fkBlockHeaderSize    = 8;
108         fkDspHeaderSize      = 8;
109         fkBuspatchHeaderSize = 4;
110         
111         try
112         {
113                 fPadData = new AliHLTMUONPad[fgkLutLine];
114         }
115         catch (const std::bad_alloc&)
116         {
117                 HLTError("Dynamic memory allocation failed for fPadData in constructor.");
118                 throw;
119         }
120         
121         fPadData[0].fDetElemId = 0;
122         fPadData[0].fIX = 0 ;
123         fPadData[0].fIY = 0 ;
124         fPadData[0].fRealX = 0.0 ;
125         fPadData[0].fRealY = 0.0 ;
126         fPadData[0].fRealZ = 0.0 ;
127         fPadData[0].fHalfPadSize = 0.0 ;
128         fPadData[0].fPlane = 0 ;
129         fPadData[0].fCharge = 0 ;
130         fPadData[0].fBusPatch = -1;
131         fPadData[0].fRawData = 0 ;
132         
133         bzero(fGetIdTotalData, 336*237*2*sizeof(int));
134 }
135
136
137 AliHLTMUONHitReconstructor::~AliHLTMUONHitReconstructor()
138 {
139         /// Default destructor
140         
141         if (fPadData)
142         {
143                 delete [] fPadData;
144                 fPadData = NULL;
145         }
146         
147         if (fClusters != NULL)
148         {
149                 delete [] fClusters;
150         }
151         if (fChannels != NULL)
152         {
153                 delete [] fChannels;
154         }
155 }
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         assert( lookupTable != NULL );
169         assert( idToEntry != NULL );
170         assert( maxEntryPerBP != NULL );
171         
172         fkLookUpTableData = lookupTable;
173         fkIdToEntry = idToEntry;
174         fkMaxEntryPerBusPatch = maxEntryPerBP;
175 }
176
177 bool AliHLTMUONHitReconstructor::DeInitDetElemInDDLArray()
178 {
179   /// Deinitialisation
180
181         if (fDataCountListPerDetElem)
182         {
183                 delete [] fDataCountListPerDetElem;
184                 fDataCountListPerDetElem = NULL;
185         }
186
187         if (fNofDataInDetElem)
188         {
189                 delete [] fNofDataInDetElem;
190                 fNofDataInDetElem = NULL;
191         }
192
193   return true;
194 }
195
196 bool AliHLTMUONHitReconstructor::InitDetElemInDDLArray()
197 {
198
199   ///Initialisation
200
201   if(GetkNofDetElemInDDL(fDDL)==-1){
202     HLTError("Check if the DDLNumber(AliHLTInt32_t value) is Set before this method");
203     return false;
204   }
205   
206   try{
207     fDataCountListPerDetElem = new AliHLTUInt16_t*[GetkNofDetElemInDDL(fDDL)];
208   }catch (const std::bad_alloc&){
209     HLTError("Dynamic memory allocation failed in constructor : fDataCountListPerDetElem");
210     throw;
211   }
212
213   for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
214     try{
215       fDataCountListPerDetElem[idet] = new AliHLTUInt16_t[fgkMaxNofDataPerDetElem];
216     }catch (const std::bad_alloc&){
217       HLTError("Dynamic memory allocation failed in constructor : fDataCountListPerDetElem[%d]",idet);
218       throw;
219     }
220   
221   try{
222     fNofDataInDetElem = new AliHLTUInt16_t[GetkNofDetElemInDDL(fDDL)];
223   }catch (const std::bad_alloc&){
224     HLTError("Dynamic memory allocation failed in constructor : fDataCountListPerDetElem");
225     throw;
226   }
227
228   for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
229     fNofDataInDetElem[idet] = 0;
230   
231   return true;
232 }
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         fRecoveryMode = mode;
241         switch (mode)
242         {
243         case kRecoverFull:
244                 fHLTMUONDecoder.TryRecover(true);
245                 fHLTMUONDecoder.ExitOnError(false);
246                 fHLTMUONDecoder.GetHandler().WarnOnly(true);
247                 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
248                 break;
249         case kRecoverJustSkip:
250                 fHLTMUONDecoder.TryRecover(false);
251                 fHLTMUONDecoder.ExitOnError(false);
252                 fHLTMUONDecoder.GetHandler().WarnOnly(true);
253                 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
254                 break;
255         case kRecoverFromParityErrorsOnly:
256                 fHLTMUONDecoder.TryRecover(false);
257                 fHLTMUONDecoder.ExitOnError(false);
258                 fHLTMUONDecoder.GetHandler().WarnOnly(false);
259                 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
260                 break;
261         default:
262                 fRecoveryMode = kDontTryRecover;
263                 fHLTMUONDecoder.TryRecover(false);
264                 fHLTMUONDecoder.ExitOnError(true);
265                 fHLTMUONDecoder.GetHandler().WarnOnly(false);
266                 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(false);
267                 break;
268         }
269 }
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   fRecPoints = recHit;
282   fMaxRecPointsCount = nofHit;
283   fRecPointsCount = &nofHit;
284   *fRecPointsCount = 0;
285   fDigitPerDDL = 0;
286   fClusterCount = 0;
287   fChannelCount = 0;
288   HLTDebug("Decoding for DDL : %d",fDDL);
289   if(GetkMinDetElemIdInDDL(fDDL) == -1 or GetkNofDetElemInDDL(fDDL)==-1){
290     HLTError("DDL value fDDL : %d, out of range",fDDL);
291   }
292   if (not DecodeDDL(rawData, rawDataSize)) {
293     // Dont need to log any message again. Already done so in DecodeDDL.
294     return false;
295   }
296
297   if (fDigitPerDDL == 1)
298   {
299     // There are no digits to process so stop here.
300     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     if (fGenerateClusterInfo and fMaxClusters < fMaxRecPointsCount)
308     {
309       if (fClusters != NULL)
310       {
311         delete [] fClusters;
312         fMaxClusters = 0;
313       }
314       fClusters = new AliHLTMUONClusterStruct[fMaxRecPointsCount];
315       fMaxClusters = fMaxRecPointsCount;
316     }
317     if (fGenerateChannelInfo and fMaxChannels < fMaxRecPointsCount*fMaxChannelMult)
318     {
319       if (fChannels != NULL)
320       {
321         delete [] fChannels;
322         fMaxChannels = 0;
323       }
324       fChannels = new AliHLTMUONChannelStruct[fMaxRecPointsCount*fMaxChannelMult];
325       fMaxChannels = fMaxRecPointsCount*fMaxChannelMult;
326     }
327   }
328   catch(const std::bad_alloc&)
329   {
330     HLTError("Could not allocate memory for the extra cluster and channel information.");
331     return false;
332   }
333
334   if (not FindRecHits()) {
335     HLTError("Failed to generate RecHits");
336     return false;
337   }
338
339   return true;
340 }
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         bool sizeOk = fClusterCount <= nofClusters;
350         AliHLTUInt32_t n = sizeOk ? fClusterCount : nofClusters;
351         memcpy(clusters, fClusters, sizeof(AliHLTMUONClusterStruct)*n);
352         nofClusters = n;
353         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         bool sizeOk = fChannelCount <= nofChannels;
364         AliHLTUInt32_t n = sizeOk ? fChannelCount : nofChannels;
365         memcpy(channels, fChannels, sizeof(AliHLTMUONChannelStruct)*n);
366         nofChannels = n;
367         return sizeOk;
368 }
369
370
371 bool AliHLTMUONHitReconstructor::DecodeDDL(AliHLTUInt32_t* rawData,AliHLTUInt32_t rawDataSize)
372 {
373   //function to decode Raw Data 
374
375   AliHLTMUONRawDecoder& handler = reinterpret_cast<AliHLTMUONRawDecoder&>(fHLTMUONDecoder.GetHandler());
376   UInt_t bufferSize = UInt_t(rawDataSize*sizeof(AliHLTUInt32_t));
377
378   handler.SetDCCut(fDCCut);
379   handler.SetPadData(fPadData);
380   handler.SetLookUpTable(fkLookUpTableData);
381   handler.SetIdManuChannelToEntry(fkIdToEntry);
382   handler.DDLNumber(fDDL);
383   handler.SetNofFiredDetElemId(fNofDataInDetElem);
384   handler.SetMaxFiredPerDetElem(fDataCountListPerDetElem);
385   handler.SetMaxEntryPerBusPatch(fkMaxEntryPerBusPatch);
386  
387   if (not fHLTMUONDecoder.Decode(rawData,bufferSize))
388   {
389         switch (TryRecover())
390         {
391         case kRecoverFull:
392                 // Do not print the following warning for option "-dontprintparityerrors" if there
393                 // were only parity errors.
394                 if (fHLTMUONDecoder.GetHandler().NonParityErrorFound() or
395                     (fHLTMUONDecoder.GetHandler().ParityErrorFound() and not fHLTMUONDecoder.GetHandler().DontPrintParityErrors())
396                    )
397                 {
398                         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                 if (fHLTMUONDecoder.GetHandler().NonParityErrorFound() or
406                     (fHLTMUONDecoder.GetHandler().ParityErrorFound() and not fHLTMUONDecoder.GetHandler().DontPrintParityErrors())
407                    )
408                 {
409                         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                 if (fHLTMUONDecoder.GetHandler().NonParityErrorFound())
417                 {
418                         HLTError("Failed to decode the tracker DDL raw data.");
419                         return false;
420                 }
421                 if (not fHLTMUONDecoder.GetHandler().DontPrintParityErrors())
422                 {
423                         assert( fHLTMUONDecoder.GetHandler().ParityErrorFound() );
424                         HLTWarning("Found parity errors in the raw data,"
425                                 " but will continue processing."
426                         );
427                 }
428                 break;
429         default:
430                 HLTError("Failed to decode the tracker DDL raw data.");
431                 return false;
432         }
433   }
434
435   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   return true;
455 }
456
457
458 bool AliHLTMUONHitReconstructor::FindRecHits()
459 {
460   // fuction that calls hit reconstruction detector element-wise.
461
462   assert( fCentralChargeB == NULL );
463   assert( fCentralChargeNB == NULL );
464   assert( fRecX == NULL );
465   assert( fRecY == NULL );
466   assert( fAvgChargeX == NULL );
467   assert( fAvgChargeY == NULL );
468   assert( fTotChargeX == NULL );
469   assert( fTotChargeY == NULL );
470   assert( fNofBChannel == NULL );
471   assert( fNofNBChannel == NULL );
472   assert( fNofYNeighbour == NULL );
473   
474   bool resultOk = false;
475   
476
477
478   for(int iDet=0; iDet< GetkNofDetElemInDDL(fDDL) ; iDet++)
479   {
480     fCentralCountB = 0;
481     fCentralCountNB = 0;
482
483     try
484     {
485       fCentralChargeB = new int[fNofDataInDetElem[iDet]];
486       HLTDebug("Allocated fCentralChargeB with %d elements.", fNofDataInDetElem[iDet]);
487       fCentralChargeNB = new int[fNofDataInDetElem[iDet]];
488       HLTDebug("Allocated fCentralChargeNB with %d elements.", fNofDataInDetElem[iDet]);
489       resultOk = true;
490     }
491     catch(const std::bad_alloc&)
492     {
493       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     }
497
498     // Continue processing, but check if everything is OK as we do, otherwise
499     // do not execute the next steps.
500     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       FindCentralHits(iDet);
505       
506       HLTDebug("For iDet : %d, Found fCentralCountB : %d, fCentralCountNB : %d",iDet,fCentralCountB,fCentralCountNB);
507       if(fCentralCountB==0 or fCentralCountNB==0)
508       {
509         HLTDebug("There is no fired pad in bending/nonbending plane...skipping this detection element");
510         if (fCentralChargeB != NULL)
511         {
512           delete [] fCentralChargeB;
513           HLTDebug("Released fCentralChargeB array.");
514           fCentralChargeB = NULL;
515         }
516         if (fCentralChargeNB != NULL)
517         {
518           delete [] fCentralChargeNB;
519           HLTDebug("Released fCentralChargeNB array.");
520           fCentralChargeNB = NULL;
521         }
522         continue;
523       }
524     }
525
526     if (resultOk)
527     {
528       try
529       {
530         fRecY = new float[fCentralCountB];
531         HLTDebug("Allocated fRecY with %d elements.", fCentralCountB);
532         fRecX = new float[fCentralCountNB];
533         HLTDebug("Allocated fRecX with %d elements.", fCentralCountNB);
534         fAvgChargeY = new float[fCentralCountB];
535         HLTDebug("Allocated fAvgChargeY with %d elements.", fCentralCountB);
536         fAvgChargeX = new float[fCentralCountNB];
537         HLTDebug("Allocated fAvgChargeX with %d elements.", fCentralCountNB);
538         fTotChargeY = new float[fCentralCountB];
539         HLTDebug("Allocated fTotChargeY with %d elements.", fCentralCountB);
540         fTotChargeX = new float[fCentralCountNB];
541         HLTDebug("Allocated fTotChargeX with %d elements.", fCentralCountNB);
542         fNofBChannel = new int[fCentralCountB];
543         HLTDebug("Allocated fNofBChannel with %d elements.", fCentralCountB);
544         fNofNBChannel = new int[fCentralCountNB];
545         HLTDebug("Allocated fNofNBChannel with %d elements.", fCentralCountNB);
546         fNofYNeighbour = new int[fCentralCountB];
547         HLTDebug("Allocated fNofBChannel with %d elements.", fCentralCountB);
548         resultOk = true;
549       }
550       catch(const std::bad_alloc&){
551         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       }
555     }
556
557     if (resultOk) RecXRecY();
558     
559     if (resultOk)
560     {
561       if(fDDL<8)
562         resultOk = MergeQuadRecHits();
563       else
564         resultOk = MergeSlatRecHits();
565     }
566     
567     // minimum value in loop is 1 because dataCount in ReadDDL starts from 1 instead of 0;
568     for(int i=0;i<fNofDataInDetElem[iDet];i++)
569       fGetIdTotalData[fPadData[fDataCountListPerDetElem[iDet][i]].fIX]
570         [fPadData[fDataCountListPerDetElem[iDet][i]].fIY]
571         [fPadData[fDataCountListPerDetElem[iDet][i]].fPlane] = 0;
572
573     // Make sure to release any memory that was allocated.
574     if (fCentralChargeB != NULL)
575     {
576       delete [] fCentralChargeB;
577       HLTDebug("Released fCentralChargeB array.");
578       fCentralChargeB = NULL;
579     }
580     if (fCentralChargeNB != NULL)
581     {
582       delete [] fCentralChargeNB;
583       HLTDebug("Released fCentralChargeNB array.");
584       fCentralChargeNB = NULL;
585     }
586     if (fRecX != NULL)
587     {
588       delete [] fRecX;
589       HLTDebug("Released fRecX array.");
590       fRecX = NULL;
591     }
592     if (fRecY != NULL)
593     {
594       delete [] fRecY;
595       HLTDebug("Released fRecY array.");
596       fRecY = NULL;
597     }
598     if (fAvgChargeX != NULL)
599     {
600       delete [] fAvgChargeX;
601       HLTDebug("Released fAvgChargeX array.");
602       fAvgChargeX = NULL;
603     }
604     if (fAvgChargeY != NULL)
605     {
606       delete [] fAvgChargeY;
607       HLTDebug("Released fAvgChargeY array.");
608       fAvgChargeY = NULL;
609     }
610     if (fTotChargeX != NULL)
611     {
612       delete [] fTotChargeX;
613       HLTDebug("Released fTotChargeX array.");
614       fTotChargeX = NULL;
615     }
616     if (fTotChargeY != NULL)
617     {
618       delete [] fTotChargeY;
619       HLTDebug("Released fTotChargeY array.");
620       fTotChargeY = NULL;
621     }
622     if (fNofBChannel != NULL)
623     {
624       delete [] fNofBChannel;
625       HLTDebug("Released fNofBChannel array.");
626       fNofBChannel = NULL;
627     }
628     if (fNofNBChannel != NULL)
629     {
630       delete [] fNofNBChannel;
631       HLTDebug("Released fNofNBChannel array.");
632       fNofNBChannel = NULL;
633     }
634     if (fNofYNeighbour != NULL)
635     {
636       delete [] fNofYNeighbour;
637       HLTDebug("Released fNofYNeighbour array.");
638       fNofYNeighbour = NULL;
639     }
640   }
641
642   Clear();  // clear internal arrays.
643
644   return resultOk;
645 }
646
647
648 void AliHLTMUONHitReconstructor::FindCentralHits(int iDet)
649 {
650   // to find central hit associated with each cluster
651
652   assert( fCentralChargeB != NULL );
653   assert( fCentralChargeNB != NULL );
654
655   int b,nb;
656   int idManuChannelCentral;
657   bool hasFind;
658   int iPad = 0;
659
660   for(int iEntry=0;iEntry<fNofDataInDetElem[iDet];iEntry++){
661
662     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     fGetIdTotalData[fPadData[iPad].fIX]
668       [fPadData[iPad].fIY]
669       [fPadData[iPad].fPlane] = iPad ;
670
671     if(fPadData[iPad].fCharge <= fDCCut ) continue;
672     
673     if(fPadData[iPad].fPlane == 0 ){//&& fPadData[iPad].fIY > (0+1) && fPadData[iPad].fIY < (79 - 1)){
674       //if(fPadData[iPad].fIY > 0){
675       if(fCentralCountB>0){
676         hasFind = false;
677         for(b = 0;b<fCentralCountB;b++){
678           idManuChannelCentral = fCentralChargeB[b];
679           if(fPadData[iPad].fIX == fPadData[idManuChannelCentral].fIX
680              &&
681              (fPadData[iPad].fIY 
682               == fPadData[idManuChannelCentral].fIY + 1 
683               ||
684               fPadData[iPad].fIY 
685               == fPadData[idManuChannelCentral].fIY + 2 
686               ||
687               fPadData[iPad].fIY 
688               == fPadData[idManuChannelCentral].fIY - 2 
689               ||
690               fPadData[iPad].fIY 
691               == fPadData[idManuChannelCentral].fIY - 1)){
692             
693             hasFind = true;
694             if(fPadData[iPad].fCharge > fPadData[idManuChannelCentral].fCharge){
695               fCentralChargeB[b] = iPad;
696             }// if condn on pad charge
697           }// if condon on pad position
698         }// for loop over b
699         if(!hasFind){
700           fCentralChargeB[fCentralCountB] = iPad;
701           fCentralCountB++;
702         }
703       }
704       else{
705         fCentralChargeB[fCentralCountB] = iPad;
706         fCentralCountB++;
707       }// check the size of centralHitB
708       for(b = 0;b<fCentralCountB;b++){
709         idManuChannelCentral = fCentralChargeB[b];
710       }
711       //}// if cond on iY > 2 (to avoid edge value pb)
712     }// B/Nb checking
713     else{
714       if(fCentralCountNB>0){
715         hasFind = false;
716         for(nb = 0;nb<fCentralCountNB;nb++){
717           idManuChannelCentral = fCentralChargeNB[nb];
718           if(fPadData[iPad].fIY == fPadData[idManuChannelCentral].fIY
719              &&
720              (fPadData[iPad].fIX 
721               == fPadData[idManuChannelCentral].fIX + 1 
722               ||
723               fPadData[iPad].fIX
724               == fPadData[idManuChannelCentral].fIX + 2
725               ||
726               fPadData[iPad].fIX
727               == fPadData[idManuChannelCentral].fIX - 2
728               ||
729               fPadData[iPad].fIX
730               == fPadData[idManuChannelCentral].fIX - 1)){
731             
732             hasFind = true;       
733             if(fPadData[iPad].fCharge > fPadData[idManuChannelCentral].fCharge){
734               fCentralChargeNB[nb] = iPad;
735             }// if condn over to find higher charge
736           }// if condn over to find position
737         }// for loop over presently all nb values
738         if(!hasFind){
739           fCentralChargeNB[fCentralCountNB] = iPad;
740           fCentralCountNB++;
741         }
742       }// centralHitNB size test
743       else{
744         fCentralChargeNB[fCentralCountNB] = iPad;
745         fCentralCountNB++;
746       }// centralHitNB size test
747       
748     }// fill for bending and nonbending hit
749   }// detElemId loop
750
751 }
752
753 void AliHLTMUONHitReconstructor::RecXRecY()
754 {
755   // find reconstructed X and Y for each plane separately
756
757   assert( fRecX != NULL );
758   assert( fRecY != NULL );
759   assert( fAvgChargeX != NULL );
760   assert( fAvgChargeY != NULL );
761   assert( fTotChargeX != NULL );
762   assert( fTotChargeY != NULL );
763   assert( fNofBChannel != NULL );
764   assert( fNofNBChannel != NULL );
765   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   for(b=0;b<fCentralCountB;b++){
775     idCentral = fCentralChargeB[b];
776
777     if(fPadData[idCentral].fIY==0)
778       idLower = 0;
779     else
780       idLower = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY-1][0];
781     
782     if(fPadData[idCentral].fIY==236)
783       idUpper = 0;
784     else
785       idUpper = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY+1][0];
786
787     
788     fTotChargeY[b] = (fPadData[idCentral].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge);
789     if(fTotChargeY[b]==0.0) continue;
790     fAvgChargeY[b] = fTotChargeY[b]/3.0 ;
791
792     fRecY[b] = (fPadData[idCentral].fRealY*fPadData[idCentral].fCharge
793                +
794                 fPadData[idUpper].fRealY*fPadData[idUpper].fCharge
795                +
796                 fPadData[idLower].fRealY*fPadData[idLower].fCharge
797                 )/fTotChargeY[b];//(fPadData[idCentral].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge) ;
798     
799     fNofBChannel[b] = 0;
800     fNofYNeighbour[b] = 0;
801     if(fPadData[idLower].fCharge>0.0){
802       fNofBChannel[b]++ ;
803       fNofYNeighbour[b]++;
804     }
805     if(fPadData[idCentral].fCharge>0.0)
806       fNofBChannel[b]++ ;
807     if(fPadData[idUpper].fCharge>0.0){
808       fNofBChannel[b]++ ;
809       fNofYNeighbour[b]++;
810     }
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     if((fPadData[idCentral].fIX-1)>=0){
817       
818       idLeft = fGetIdTotalData[fPadData[idCentral].fIX-1][fPadData[idCentral].fIY][0];
819       
820       if(fPadData[idLeft].fIY==0)
821         idLower = 0;
822       else
823         idLower = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY-1][0];
824       
825       if(fPadData[idLeft].fIY==236)
826         idUpper = 0;
827       else
828         idUpper = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY+1][0];
829
830       fTotChargeY[b] += (fPadData[idLeft].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge);
831
832       if(fPadData[idLower].fCharge>0.0)
833         fNofBChannel[b]++ ;
834       if(fPadData[idLeft].fCharge>0.0)
835         fNofBChannel[b]++ ;
836       if(fPadData[idUpper].fCharge>0.0)
837         fNofBChannel[b]++ ;
838
839     }
840     ////////////////////////////////////////////////////
841
842     //collect right coloumn
843     if((fPadData[idCentral].fIX+1)<=335){
844
845       idRight = fGetIdTotalData[fPadData[idCentral].fIX+1][fPadData[idCentral].fIY][0];
846     
847       if(fPadData[idRight].fIY==0)
848         idLower = 0;
849       else
850         idLower = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY-1][0];
851       
852       if(fPadData[idRight].fIY==236)
853         idUpper = 0;
854       else
855         idUpper = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY+1][0];
856   
857       fTotChargeY[b] += (fPadData[idRight].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge);
858
859       if(fPadData[idLower].fCharge>0.0)
860         fNofBChannel[b]++ ;
861       if(fPadData[idRight].fCharge>0.0)
862         fNofBChannel[b]++ ;
863       if(fPadData[idUpper].fCharge>0.0)
864         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   for(nb=0;nb<fCentralCountNB;nb++){
873     idCentral = fCentralChargeNB[nb];
874
875     if(fPadData[idCentral].fIX==0)
876       idLeft = 0;
877     else
878       idLeft = fGetIdTotalData[fPadData[idCentral].fIX-1][fPadData[idCentral].fIY][1];
879     
880     if(fPadData[idCentral].fIX==335)
881       idRight = 0 ;
882     else
883       idRight = fGetIdTotalData[fPadData[idCentral].fIX+1][fPadData[idCentral].fIY][1];
884
885     fTotChargeX[nb] = (fPadData[idCentral].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
886     if(fTotChargeX[nb]==0.0) continue;
887     fAvgChargeX[nb] = fTotChargeX[nb]/3.0 ;
888     
889     fRecX[nb] = (fPadData[idCentral].fRealX*fPadData[idCentral].fCharge
890                  +
891                  fPadData[idRight].fRealX*fPadData[idRight].fCharge
892                  +
893                  fPadData[idLeft].fRealX*fPadData[idLeft].fCharge
894                  )/fTotChargeX[nb];//(fPadData[idCentral].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
895     
896
897     fNofNBChannel[nb] = 0;
898     if(fPadData[idLeft].fCharge>0.0)
899       fNofNBChannel[nb]++ ;
900     if(fPadData[idCentral].fCharge>0.0)
901       fNofNBChannel[nb]++ ;
902     if(fPadData[idRight].fCharge>0.0)
903       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     if((fPadData[idCentral].fIY-1)>=0){
911
912       idLower = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY-1][1];
913       
914       if(fPadData[idLower].fIX==0)
915         idLeft = 0;
916       else
917         idLeft = fGetIdTotalData[fPadData[idLower].fIX-1][fPadData[idLower].fIY][1];
918     
919       if(fPadData[idLower].fIX==335)
920         idRight = 0 ;
921       else
922         idRight = fGetIdTotalData[fPadData[idLower].fIX+1][fPadData[idLower].fIY][1];
923
924       fTotChargeX[nb] += (fPadData[idLower].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
925
926       if(fPadData[idLeft].fCharge>0.0)
927         fNofNBChannel[nb]++ ;
928       if(fPadData[idLower].fCharge>0.0)
929         fNofNBChannel[nb]++ ;
930       if(fPadData[idRight].fCharge>0.0)
931         fNofNBChannel[nb]++ ;
932
933     }
934     ////////////////////////////////////////////////////////////
935
936     // Upper row
937     if((fPadData[idCentral].fIY+1)<=236){
938
939       idUpper = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY+1][1];
940
941       if(fPadData[idUpper].fIX==0)
942         idLeft = 0;
943       else
944         idLeft = fGetIdTotalData[fPadData[idUpper].fIX-1][fPadData[idUpper].fIY][1];
945       
946       if(fPadData[idUpper].fIX==335)
947         idRight = 0 ;
948       else
949         idRight = fGetIdTotalData[fPadData[idUpper].fIX+1][fPadData[idUpper].fIY][1];
950       
951       fTotChargeX[nb] += (fPadData[idUpper].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
952       
953       if(fPadData[idLeft].fCharge>0.0)
954         fNofNBChannel[nb]++ ;
955       if(fPadData[idRight].fCharge>0.0)
956         fNofNBChannel[nb]++ ;
957       if(fPadData[idRight].fCharge>0.0)
958         fNofNBChannel[nb]++ ;
959
960     }
961     ////////////////////////////////////////////////////////////
962
963     HLTDebug("RecX[%d] : %f, nofChannel : %d",nb,fRecX[nb],fNofNBChannel[nb]);
964
965    
966
967   }
968 }
969
970
971 bool AliHLTMUONHitReconstructor::MergeQuadRecHits()
972 {
973   // Merge reconstructed hits first over same plane then bending plane with non-bending plane
974
975   assert( fRecX != NULL );
976   assert( fRecY != NULL );
977   assert( fAvgChargeX != NULL );
978   assert( fAvgChargeY != NULL );
979   assert( fTotChargeX != NULL );
980   assert( fTotChargeY != NULL );
981   assert( fNofBChannel != NULL );
982   assert( fNofNBChannel != NULL );
983   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   bool *isMergedY = new bool[fCentralCountB];
992   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   for(int i=0;i<fCentralCountB-1;i++){
997     isMergedY[i] = false;
998     if(fRecY[i] != outsideSpacePoint){
999       for(int j=i+1;j<fCentralCountB;j++){
1000                  
1001         if(fCentralChargeB[i]==fCentralChargeB[j]){
1002           fRecY[j] = outsideSpacePoint;
1003           continue;
1004         }
1005         else if(
1006            (
1007             fPadData[fCentralChargeB[i]].fIY == fPadData[fCentralChargeB[j]].fIY
1008             )
1009            &&
1010            (
1011             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX + 1
1012             ||
1013             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX - 1
1014             )
1015            &&
1016            fRecY[j] != outsideSpacePoint
1017            &&
1018            fRecY[i] != outsideSpacePoint
1019            ){
1020
1021           if(fAvgChargeY[i] > fAvgChargeY[j]){
1022             fRecY[i] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
1023                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
1024             fRecY[j] = outsideSpacePoint;
1025           }
1026           else{
1027             fRecY[j] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
1028                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
1029             fRecY[i] = outsideSpacePoint;
1030
1031           }// search for higher charge
1032         }//pad position
1033       }//j for loop
1034     }//if fRecY[i] != outsideSpacePoint
1035   }// i for loop
1036   isMergedY[fCentralCountB-1] = false;
1037   
1038   // MERGE Non Bending Plane hits, which are placed side by side
1039   for(int i=0;i<fCentralCountNB-1;i++){
1040     isMergedX[i] = false;
1041     if(fRecX[i] != outsideSpacePoint){
1042       for(int j=i+1;j<fCentralCountNB;j++){
1043
1044         if(fCentralChargeNB[i]==fCentralChargeNB[j]){
1045           fRecX[j] = outsideSpacePoint;
1046           continue;
1047         }
1048         else if(
1049            (
1050             fPadData[fCentralChargeNB[i]].fIX == fPadData[fCentralChargeNB[j]].fIX
1051             )
1052            &&
1053            (
1054             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY + 1
1055             ||
1056             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY - 1
1057             )
1058            &&
1059            fRecX[j] != outsideSpacePoint
1060            &&
1061            fRecX[i] != outsideSpacePoint
1062            ){
1063
1064           if(fAvgChargeX[i] > fAvgChargeX[j]){
1065             fRecX[i] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
1066                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
1067             fRecX[j] = outsideSpacePoint;
1068           }
1069           else{
1070             fRecX[j] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
1071                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
1072             fRecX[i] = outsideSpacePoint;
1073           }// search for higher charge
1074         }//pad position
1075       }//j for loop
1076     }//if fRecX[i] != outsideSpacePoint
1077   }// i for loop
1078   isMergedX[fCentralCountNB-1] = false;
1079   
1080   // Merge bending Plane hits with Non Bending
1081   for(int b=0;b<fCentralCountB;b++){
1082     if(fRecY[b]!=outsideSpacePoint){
1083       idCentralB = fCentralChargeB[b];
1084       padCenterXB = fPadData[idCentralB].fRealX; 
1085       
1086       halfPadLengthX = fPadData[idCentralB].fHalfPadSize ;
1087
1088       for(int nb=0;nb<fCentralCountNB;nb++){
1089         if(fRecX[nb]!=outsideSpacePoint){
1090           idCentralNB = fCentralChargeNB[nb];
1091
1092           padCenterYNB = fPadData[idCentralNB].fRealY;
1093
1094           halfPadLengthY = fPadData[idCentralNB].fHalfPadSize ;
1095
1096           if(fabsf(fRecX[nb]) > fabsf(padCenterXB))
1097             diffX = fabsf(fRecX[nb]) -  fabsf(padCenterXB);
1098           else
1099             diffX = fabsf(padCenterXB) -  fabsf(fRecX[nb]);
1100           
1101           if(fabsf(padCenterYNB)>fabsf(fRecY[b]))
1102             diffY = fabsf(padCenterYNB) - fabsf(fRecY[b]);
1103           else
1104             diffY =  fabsf(fRecY[b]) - fabsf(padCenterYNB);
1105
1106           if(diffX < halfPadLengthX && diffY < halfPadLengthY ){//&& fPadData[idCentralB].fIY != 0){
1107             
1108             isMergedY[b] = true;
1109             isMergedX[nb] = true;
1110             
1111             if(fNofYNeighbour[b]==2){
1112               if(fPadData[idCentralB].fDetElemId<104)
1113                 fRecY[b] += 0.02*sin(14.5*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1114               else if(fPadData[idCentralB].fDetElemId>=200 && fPadData[idCentralB].fDetElemId<204)
1115                 fRecY[b] += 0.02*sin(14.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1116               else
1117                 fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1118             }
1119             
1120             if(fPadData[idCentralNB].fDetElemId<204)
1121               fRecX[nb] += 0.095*sin(10.5*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
1122             else //if(fPadData[idCentralNB].fDetElemId>=300 && fPadData[idCentralNB].fDetElemId<404)
1123               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             if((*fRecPointsCount) == fMaxRecPointsCount){
1128               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               delete [] isMergedY;
1133               delete [] isMergedX;
1134               return true;
1135             }
1136
1137             AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
1138                  (fPadData[idCentralB].fDetElemId / 100) - 1,
1139                  fPadData[idCentralB].fDetElemId
1140               );
1141             fRecPoints[(*fRecPointsCount)].fFlags = idflags;
1142             fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
1143             fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
1144             fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
1145             
1146             if (fGenerateClusterInfo)
1147             {
1148               if (fClusterCount >= fMaxClusters)
1149               {
1150                 HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
1151                 delete [] isMergedY;
1152                 delete [] isMergedX;
1153                 return false;
1154               }
1155               
1156               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               fNewClusterId = (fNewClusterId + 1) & 0x03FFFFFF;
1162               
1163               fClusters[fClusterCount].fHit = fRecPoints[(*fRecPointsCount)];
1164               fClusters[fClusterCount].fDetElemId = fPadData[idCentralB].fDetElemId;
1165               fClusters[fClusterCount].fNchannelsB = fNofBChannel[b];
1166               fClusters[fClusterCount].fNchannelsNB = fNofNBChannel[nb];
1167               fClusters[fClusterCount].fChargeB = fTotChargeY[b];
1168               fClusters[fClusterCount].fChargeNB = fTotChargeX[nb];
1169               fClusterCount++;
1170             }
1171             
1172             if (fGenerateChannelInfo)
1173             {
1174               // 3 by 3 pad structure around the central pad for the 2 planes.
1175               int pad[2][3][3] = {{
1176                   {0,      0,      0},
1177                   {0, idCentralB,  0},
1178                   {0,      0,      0}
1179                 },{
1180                   {0,      0,      0},
1181                   {0, idCentralNB, 0},
1182                   {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               if (fPadData[idCentralB].fIY > 0)
1188                 pad[0][0][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY-1][0];
1189               if (fPadData[idCentralB].fIY < 236)
1190                 pad[0][2][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY+1][0];
1191               if (fPadData[idCentralB].fIX > 0)
1192               {
1193                 int idLeft = fGetIdTotalData[fPadData[idCentralB].fIX-1][fPadData[idCentralB].fIY][0];
1194                 pad[0][1][0] = idLeft;
1195                 if (fPadData[idLeft].fIY > 0)
1196                   pad[0][0][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY-1][0];
1197                 if (fPadData[idLeft].fIY < 236)
1198                   pad[0][2][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY+1][0];
1199               }
1200               if (fPadData[idCentralB].fIX < 335)
1201               {
1202                 int idRight = fGetIdTotalData[fPadData[idCentralB].fIX+1][fPadData[idCentralB].fIY][0];
1203                 pad[0][1][2] = idRight;
1204                 if (fPadData[idRight].fIY > 0)
1205                   pad[0][0][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY-1][0];
1206                 if (fPadData[idRight].fIY < 236)
1207                   pad[0][2][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY+1][0];
1208               }
1209               
1210               if (fPadData[idCentralNB].fIX > 0)
1211                 pad[1][1][0] = fGetIdTotalData[fPadData[idCentralNB].fIX-1][fPadData[idCentralNB].fIY][1];
1212               if (fPadData[idCentralNB].fIX < 335)
1213                 pad[1][1][2] = fGetIdTotalData[fPadData[idCentralNB].fIX+1][fPadData[idCentralNB].fIY][1];
1214               if (fPadData[idCentralNB].fIY > 0)
1215               {
1216                 int idLower = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY-1][1];
1217                 pad[1][0][1] = idLower;
1218                 if (fPadData[idLower].fIX > 0)
1219                   pad[1][0][0] = fGetIdTotalData[fPadData[idLower].fIX-1][fPadData[idLower].fIY][1];
1220                 if (fPadData[idLower].fIX < 335)
1221                   pad[1][0][2] = fGetIdTotalData[fPadData[idLower].fIX+1][fPadData[idLower].fIY][1];
1222               }
1223               if (fPadData[idCentralNB].fIY < 236)
1224               {
1225                 int idUpper = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY+1][1];
1226                 pad[1][2][1] = idUpper;
1227                 if (fPadData[idUpper].fIX > 0)
1228                   pad[1][2][0] = fGetIdTotalData[fPadData[idUpper].fIX-1][fPadData[idUpper].fIY][1];
1229                 if (fPadData[idUpper].fIX < 335)
1230                   pad[1][2][2] = fGetIdTotalData[fPadData[idUpper].fIX+1][fPadData[idUpper].fIY][1];
1231               }
1232               
1233               AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
1234               
1235               // Now generate the pad structures from all the pad indices found above.
1236               for (int i = 0; i < 2; i++)
1237               for (int j = 0; j < 3; j++)
1238               for (int k = 0; k < 3; k++)
1239               {
1240                 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                 if (p.fCharge <= 0) continue;
1244                 
1245                 UShort_t manuId; UChar_t channelId; UShort_t adc;
1246                 AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
1247                 
1248                 fChannels[fChannelCount].fClusterId = clusterId;
1249                 fChannels[fChannelCount].fBusPatch = p.fBusPatch;
1250                 fChannels[fChannelCount].fManu = manuId;
1251                 fChannels[fChannelCount].fChannelAddress = channelId;
1252                 fChannels[fChannelCount].fSignal = adc;
1253                 fChannels[fChannelCount].fRawDataWord = p.fRawData;
1254                 fChannelCount++;
1255               }
1256             }
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             (*fRecPointsCount)++;
1264           }//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   for(int b=0;b<fCentralCountB;b++){
1272     if(fRecY[b]!=outsideSpacePoint and !isMergedY[b] and fNofBChannel[b]>2){
1273       idCentralB = fCentralChargeB[b];
1274       
1275       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       if(TMath::Abs(400.0*fPadData[idCentralB].fHalfPadSize*fPadData[idCentralB].fPadSizeXY - minPadArea)> 1.0e-5) continue;
1278       
1279       if(fNofYNeighbour[b]==2){
1280         if(fPadData[idCentralB].fDetElemId<104)
1281           fRecY[b] += 0.02*sin(14.5*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1282         else if(fPadData[idCentralB].fDetElemId>=200 && fPadData[idCentralB].fDetElemId<204)
1283           fRecY[b] += 0.02*sin(14.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1284         else
1285           fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1286       }
1287       
1288       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       if((*fRecPointsCount) == fMaxRecPointsCount){
1296         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         delete [] isMergedY;
1301         delete [] isMergedX;
1302         return true;
1303       }
1304       
1305       AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
1306                  (fPadData[idCentralB].fDetElemId / 100) - 1,
1307                  fPadData[idCentralB].fDetElemId
1308               );
1309       fRecPoints[(*fRecPointsCount)].fFlags = idflags;
1310       fRecPoints[(*fRecPointsCount)].fX = padCenterXB;
1311       fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
1312       fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
1313             
1314       if (fGenerateClusterInfo)
1315         {
1316           if (fClusterCount >= fMaxClusters)
1317             {
1318               HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
1319               delete [] isMergedY;
1320               delete [] isMergedX;
1321               return false;
1322             }
1323               
1324           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           fNewClusterId = (fNewClusterId + 1) & 0x03FFFFFF;
1330           
1331           fClusters[fClusterCount].fHit = fRecPoints[(*fRecPointsCount)];
1332           fClusters[fClusterCount].fDetElemId = fPadData[idCentralB].fDetElemId;
1333           fClusters[fClusterCount].fNchannelsB = fNofBChannel[b];
1334           fClusters[fClusterCount].fNchannelsNB = fNofBChannel[b];
1335           fClusters[fClusterCount].fChargeB = fTotChargeY[b];
1336           fClusters[fClusterCount].fChargeNB = fTotChargeY[b];
1337           fClusterCount++;
1338         }
1339       
1340       if (fGenerateChannelInfo)
1341         {
1342           // 3 by 3 pad structure around the central pad for the 2 planes.
1343           int pad[2][3][3] = {{
1344               {0,      0,      0},
1345               {0, idCentralB,  0},
1346               {0,      0,      0}
1347             },{
1348               {0,      0,      0},
1349               {0,      0     , 0},
1350               {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           if (fPadData[idCentralB].fIY > 0)
1356             pad[0][0][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY-1][0];
1357           if (fPadData[idCentralB].fIY < 236)
1358             pad[0][2][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY+1][0];
1359           if (fPadData[idCentralB].fIX > 0)
1360             {
1361               int idLeft = fGetIdTotalData[fPadData[idCentralB].fIX-1][fPadData[idCentralB].fIY][0];
1362               pad[0][1][0] = idLeft;
1363               if (fPadData[idLeft].fIY > 0)
1364                 pad[0][0][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY-1][0];
1365               if (fPadData[idLeft].fIY < 236)
1366                 pad[0][2][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY+1][0];
1367             }
1368           if (fPadData[idCentralB].fIX < 335)
1369             {
1370               int idRight = fGetIdTotalData[fPadData[idCentralB].fIX+1][fPadData[idCentralB].fIY][0];
1371               pad[0][1][2] = idRight;
1372               if (fPadData[idRight].fIY > 0)
1373                 pad[0][0][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY-1][0];
1374               if (fPadData[idRight].fIY < 236)
1375                 pad[0][2][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY+1][0];
1376             }
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           AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
1385           
1386           // Now generate the pad structures from all the pad indices found above.
1387           for (int i = 0; i < 1; i++)
1388             for (int j = 0; j < 3; j++)
1389               for (int k = 0; k < 3; k++)
1390                 {
1391                   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                   if (p.fCharge <= 0) continue;
1395                   
1396                   UShort_t manuId; UChar_t channelId; UShort_t adc;
1397                   AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
1398                   
1399                   fChannels[fChannelCount].fClusterId = clusterId;
1400                   fChannels[fChannelCount].fBusPatch = p.fBusPatch;
1401                   fChannels[fChannelCount].fManu = manuId;
1402                   fChannels[fChannelCount].fChannelAddress = channelId;
1403                   fChannels[fChannelCount].fSignal = adc;
1404                   fChannels[fChannelCount].fRawDataWord = p.fRawData;
1405                   fChannelCount++;
1406                 }
1407         }
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       (*fRecPointsCount)++;
1415
1416     }// 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   for(int nb=0;nb<fCentralCountNB;nb++){
1422
1423     idCentralNB = fCentralChargeNB[nb];
1424     if(fRecX[nb]!=outsideSpacePoint and !isMergedX[nb] and fNofNBChannel[nb]>2){
1425       
1426       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       if(TMath::Abs(400.0*fPadData[idCentralNB].fHalfPadSize*fPadData[idCentralNB].fPadSizeXY - minPadArea)> 1.0e-5) continue;
1429       
1430       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       if(fPadData[idCentralNB].fDetElemId<204)
1442         fRecX[nb] += 0.095*sin(10.5*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
1443       else //if(fPadData[idCentralNB].fDetElemId>=300 && fPadData[idCentralNB].fDetElemId<404)
1444         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       if((*fRecPointsCount) == fMaxRecPointsCount){
1449         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         delete [] isMergedY;
1454         delete [] isMergedX;
1455         return true;
1456       }
1457
1458       AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
1459                  (fPadData[idCentralNB].fDetElemId / 100) - 1,
1460                  fPadData[idCentralNB].fDetElemId
1461               );
1462       fRecPoints[(*fRecPointsCount)].fFlags = idflags;
1463       fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
1464       fRecPoints[(*fRecPointsCount)].fY = padCenterYNB;
1465       fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralNB].fRealZ;
1466       
1467       if (fGenerateClusterInfo)
1468         {
1469           if (fClusterCount >= fMaxClusters)
1470             {
1471               HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
1472               delete [] isMergedY;
1473               delete [] isMergedX;
1474               return false;
1475             }
1476           
1477           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           fNewClusterId = (fNewClusterId + 1) & 0x03FFFFFF;
1483               
1484           fClusters[fClusterCount].fHit = fRecPoints[(*fRecPointsCount)];
1485           fClusters[fClusterCount].fDetElemId = fPadData[idCentralNB].fDetElemId;
1486           fClusters[fClusterCount].fNchannelsB = fNofNBChannel[nb];
1487           fClusters[fClusterCount].fNchannelsNB = fNofNBChannel[nb];
1488           fClusters[fClusterCount].fChargeB = fTotChargeX[nb];
1489           fClusters[fClusterCount].fChargeNB = fTotChargeX[nb];
1490           fClusterCount++;
1491         }
1492       
1493       if (fGenerateChannelInfo)
1494         {
1495           // 3 by 3 pad structure around the central pad for the 2 planes.
1496           int pad[2][3][3] = {{
1497               {0,      0,      0},
1498               {0,      0,      0},
1499               {0,      0,      0}
1500                 },{
1501               {0,      0,      0},
1502               {0, idCentralNB, 0},
1503               {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           if (fPadData[idCentralNB].fIX > 0)
1510             pad[1][1][0] = fGetIdTotalData[fPadData[idCentralNB].fIX-1][fPadData[idCentralNB].fIY][1];
1511           if (fPadData[idCentralNB].fIX < 335)
1512             pad[1][1][2] = fGetIdTotalData[fPadData[idCentralNB].fIX+1][fPadData[idCentralNB].fIY][1];
1513           if (fPadData[idCentralNB].fIY > 0)
1514             {
1515               int idLower = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY-1][1];
1516               pad[1][0][1] = idLower;
1517               if (fPadData[idLower].fIX > 0)
1518                 pad[1][0][0] = fGetIdTotalData[fPadData[idLower].fIX-1][fPadData[idLower].fIY][1];
1519               if (fPadData[idLower].fIX < 335)
1520                 pad[1][0][2] = fGetIdTotalData[fPadData[idLower].fIX+1][fPadData[idLower].fIY][1];
1521             }
1522           if (fPadData[idCentralNB].fIY < 236)
1523             {
1524               int idUpper = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY+1][1];
1525                 pad[1][2][1] = idUpper;
1526                 if (fPadData[idUpper].fIX > 0)
1527                   pad[1][2][0] = fGetIdTotalData[fPadData[idUpper].fIX-1][fPadData[idUpper].fIY][1];
1528                 if (fPadData[idUpper].fIX < 335)
1529                   pad[1][2][2] = fGetIdTotalData[fPadData[idUpper].fIX+1][fPadData[idUpper].fIY][1];
1530             }
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           AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
1539           
1540           // Now generate the pad structures from all the pad indices found above.
1541           for (int i = 1; i < 2; i++)
1542             for (int j = 0; j < 3; j++)
1543               for (int k = 0; k < 3; k++)
1544                 {
1545                   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                   if (p.fCharge <= 0) continue;
1549                   
1550                   UShort_t manuId; UChar_t channelId; UShort_t adc;
1551                   AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
1552                   
1553                   fChannels[fChannelCount].fClusterId = clusterId;
1554                   fChannels[fChannelCount].fBusPatch = p.fBusPatch;
1555                   fChannels[fChannelCount].fManu = manuId;
1556                   fChannels[fChannelCount].fChannelAddress = channelId;
1557                   fChannels[fChannelCount].fSignal = adc;
1558                   fChannels[fChannelCount].fRawDataWord = p.fRawData;
1559                   fChannelCount++;
1560                 }
1561         }
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       (*fRecPointsCount)++;
1570     }//if lies wihtin 5.0 mm
1571   }// condn over fRecX ! = 0.0
1572
1573   delete [] isMergedY;
1574   delete [] isMergedX;
1575   
1576   return true;
1577 }
1578
1579 bool AliHLTMUONHitReconstructor::MergeSlatRecHits()
1580 {
1581   // Merge reconstructed hits first over same plane then bending plane with non-bending plane
1582
1583   assert( fRecX != NULL );
1584   assert( fRecY != NULL );
1585   assert( fAvgChargeX != NULL );
1586   assert( fAvgChargeY != NULL );
1587   assert( fTotChargeX != NULL );
1588   assert( fTotChargeY != NULL );
1589   assert( fNofBChannel != NULL );
1590   assert( fNofNBChannel != NULL );
1591   assert( fNofYNeighbour  != NULL );
1592
1593   int idCentralB,idCentralNB ;
1594   float padCenterXB;
1595   float padCenterYNB;
1596   float diffX,diffY;
1597   float halfPadLengthX,halfPadLengthY;
1598   bool *isMergedY = new bool[fCentralCountB];
1599   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   for(int i=0;i<fCentralCountB-1;i++){
1604     isMergedY[i] = false;
1605     if(fRecY[i] != outsideSpacePoint){
1606       for(int j=i+1;j<fCentralCountB;j++){
1607                  
1608         if(fCentralChargeB[i]==fCentralChargeB[j]){
1609           fRecY[j] = outsideSpacePoint;
1610           continue;
1611         }
1612         else if(
1613            (
1614             fPadData[fCentralChargeB[i]].fIY == fPadData[fCentralChargeB[j]].fIY
1615             )
1616            &&
1617            (
1618             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX + 1
1619             ||
1620             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX - 1
1621             )
1622            &&
1623            fRecY[j] != outsideSpacePoint
1624            &&
1625            fRecY[i] != outsideSpacePoint
1626            ){
1627
1628           if(fAvgChargeY[i] > fAvgChargeY[j]){
1629             fRecY[i] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
1630                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
1631             fRecY[j] = outsideSpacePoint;
1632           }
1633           else{
1634             fRecY[j] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
1635                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
1636             fRecY[i] = outsideSpacePoint;
1637
1638           }// search for higher charge
1639         }//pad position
1640       }//j for loop
1641     }//if fRecY[i] != outsideSpacePoint
1642   }// i for loop
1643   isMergedY[fCentralCountB-1] = false;
1644   
1645   // MERGE Non Bending Plane hits, which are placed side by side
1646   for(int i=0;i<fCentralCountNB-1;i++){
1647     isMergedX[i] = false;
1648     if(fRecX[i] != 0.0){
1649       for(int j=i+1;j<fCentralCountNB;j++){
1650
1651         if(fCentralChargeNB[i]==fCentralChargeNB[j]){
1652           fRecX[j] = outsideSpacePoint;
1653           continue;
1654         }
1655         else if(
1656            (
1657             fPadData[fCentralChargeNB[i]].fIX == fPadData[fCentralChargeNB[j]].fIX
1658             )
1659            &&
1660            (
1661             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY + 1
1662             ||
1663             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY - 1
1664             )
1665            &&
1666            fRecX[j] != outsideSpacePoint
1667            &&
1668            fRecX[i] != outsideSpacePoint
1669            ){
1670
1671           if(fAvgChargeX[i] > fAvgChargeX[j]){
1672             fRecX[i] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
1673                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
1674             fRecX[j] = outsideSpacePoint;
1675           }
1676           else{
1677             fRecX[j] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
1678                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
1679             fRecX[i] = outsideSpacePoint;
1680           }// search for higher charge
1681         }//pad position
1682       }//j for loop
1683     }//if fRecX[i] != outsideSpacePoint
1684   }// i for loop
1685   isMergedX[fCentralCountNB-1] = false;
1686
1687   // Merge bending Plane hits with Non Bending
1688   for(int b=0;b<fCentralCountB;b++){
1689     if(fRecY[b]!=outsideSpacePoint){
1690       idCentralB = fCentralChargeB[b];
1691       padCenterXB = fPadData[idCentralB].fRealX; 
1692       
1693       halfPadLengthX = fPadData[idCentralB].fHalfPadSize ;
1694
1695       for(int nb=0;nb<fCentralCountNB;nb++){
1696         if(fRecX[nb]!=outsideSpacePoint){
1697           idCentralNB = fCentralChargeNB[nb];
1698
1699           padCenterYNB = fPadData[idCentralNB].fRealY;
1700
1701           halfPadLengthY = fPadData[idCentralNB].fHalfPadSize ;
1702
1703           if(fabsf(fRecX[nb]) > fabsf(padCenterXB))
1704             diffX = fabsf(fRecX[nb]) -  fabsf(padCenterXB);
1705           else
1706             diffX = fabsf(padCenterXB) -  fabsf(fRecX[nb]);
1707           
1708           if(fabsf(padCenterYNB)>fabsf(fRecY[b]))
1709             diffY = fabsf(padCenterYNB) - fabsf(fRecY[b]);
1710           else
1711             diffY =  fabsf(fRecY[b]) - fabsf(padCenterYNB);
1712
1713           if(diffX < halfPadLengthX && diffY < halfPadLengthY ){//&& fPadData[idCentralB].fIY != 0){
1714             
1715             isMergedY[b] = true;
1716             isMergedX[nb] = true;
1717             
1718             if(fNofYNeighbour[b]==2){
1719               fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1720             }
1721             
1722             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             if((*fRecPointsCount) == fMaxRecPointsCount){
1727               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               delete [] isMergedY;
1732               delete [] isMergedX;
1733               return true;
1734             }
1735
1736             AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
1737                  (fPadData[idCentralB].fDetElemId / 100) - 1,
1738                  fPadData[idCentralB].fDetElemId
1739               );
1740             fRecPoints[(*fRecPointsCount)].fFlags = idflags;
1741             fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
1742             fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
1743             fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
1744             
1745             if (fGenerateClusterInfo)
1746             {
1747               if (fClusterCount >= fMaxClusters)
1748               {
1749                 HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
1750                 delete [] isMergedY;
1751                 delete [] isMergedX;
1752                 return false;
1753               }
1754               
1755               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               fNewClusterId = (fNewClusterId + 1) & 0x03FFFFFF;
1761               
1762               fClusters[fClusterCount].fHit = fRecPoints[(*fRecPointsCount)];
1763               fClusters[fClusterCount].fDetElemId = fPadData[idCentralB].fDetElemId;
1764               fClusters[fClusterCount].fNchannelsB = fNofBChannel[b];
1765               fClusters[fClusterCount].fNchannelsNB = fNofNBChannel[nb];
1766               fClusters[fClusterCount].fChargeB = fTotChargeY[b];
1767               fClusters[fClusterCount].fChargeNB = fTotChargeX[nb];
1768               fClusterCount++;
1769             }
1770             
1771             if (fGenerateChannelInfo)
1772             {
1773               // 3 by 3 pad structure around the central pad for the 2 planes.
1774               int pad[2][3][3] = {{
1775                   {0,      0,      0},
1776                   {0, idCentralB,  0},
1777                   {0,      0,      0}
1778                 },{
1779                   {0,      0,      0},
1780                   {0, idCentralNB, 0},
1781                   {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               if (fPadData[idCentralB].fIY > 0)
1787                 pad[0][0][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY-1][0];
1788               if (fPadData[idCentralB].fIY < 236)
1789                 pad[0][2][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY+1][0];
1790               if (fPadData[idCentralB].fIX > 0)
1791               {
1792                 int idLeft = fGetIdTotalData[fPadData[idCentralB].fIX-1][fPadData[idCentralB].fIY][0];
1793                 pad[0][1][0] = idLeft;
1794                 if (fPadData[idLeft].fIY > 0)
1795                   pad[0][0][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY-1][0];
1796                 if (fPadData[idLeft].fIY < 236)
1797                   pad[0][2][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY+1][0];
1798               }
1799               if (fPadData[idCentralB].fIX < 335)
1800               {
1801                 int idRight = fGetIdTotalData[fPadData[idCentralB].fIX+1][fPadData[idCentralB].fIY][0];
1802                 pad[0][1][2] = idRight;
1803                 if (fPadData[idRight].fIY > 0)
1804                   pad[0][0][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY-1][0];
1805                 if (fPadData[idRight].fIY < 236)
1806                   pad[0][2][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY+1][0];
1807               }
1808               
1809               if (fPadData[idCentralNB].fIX > 0)
1810                 pad[1][1][0] = fGetIdTotalData[fPadData[idCentralNB].fIX-1][fPadData[idCentralNB].fIY][1];
1811               if (fPadData[idCentralNB].fIX < 335)
1812                 pad[1][1][2] = fGetIdTotalData[fPadData[idCentralNB].fIX+1][fPadData[idCentralNB].fIY][1];
1813               if (fPadData[idCentralNB].fIY > 0)
1814               {
1815                 int idLower = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY-1][1];
1816                 pad[1][0][1] = idLower;
1817                 if (fPadData[idLower].fIX > 0)
1818                   pad[1][0][0] = fGetIdTotalData[fPadData[idLower].fIX-1][fPadData[idLower].fIY][1];
1819                 if (fPadData[idLower].fIX < 335)
1820                   pad[1][0][2] = fGetIdTotalData[fPadData[idLower].fIX+1][fPadData[idLower].fIY][1];
1821               }
1822               if (fPadData[idCentralNB].fIY < 236)
1823               {
1824                 int idUpper = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY+1][1];
1825                 pad[1][2][1] = idUpper;
1826                 if (fPadData[idUpper].fIX > 0)
1827                   pad[1][2][0] = fGetIdTotalData[fPadData[idUpper].fIX-1][fPadData[idUpper].fIY][1];
1828                 if (fPadData[idUpper].fIX < 335)
1829                   pad[1][2][2] = fGetIdTotalData[fPadData[idUpper].fIX+1][fPadData[idUpper].fIY][1];
1830               }
1831               
1832               AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
1833               
1834               // Now generate the pad structures from all the pad indices found above.
1835               for (int i = 0; i < 2; i++)
1836               for (int j = 0; j < 3; j++)
1837               for (int k = 0; k < 3; k++)
1838               {
1839                 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                 if (p.fCharge <= 0) continue;
1843                 
1844                 UShort_t manuId; UChar_t channelId; UShort_t adc;
1845                 AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
1846                 
1847                 fChannels[fChannelCount].fClusterId = clusterId;
1848                 fChannels[fChannelCount].fBusPatch = p.fBusPatch;
1849                 fChannels[fChannelCount].fManu = manuId;
1850                 fChannels[fChannelCount].fChannelAddress = channelId;
1851                 fChannels[fChannelCount].fSignal = adc;
1852                 fChannels[fChannelCount].fRawDataWord = p.fRawData;
1853                 fChannelCount++;
1854               }
1855             }
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             (*fRecPointsCount)++;
1863           }//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   delete [] isMergedY;
1871   delete [] isMergedX;
1872   return true;
1873 }
1874
1875
1876 void AliHLTMUONHitReconstructor::Clear()
1877 {
1878   // function to clear internal arrays.
1879
1880   HLTDebug("Clearing fPadData and fNofDataInDetElem buffers.");
1881
1882
1883   for(int iPad=1;iPad<fDigitPerDDL;iPad++){
1884     fGetIdTotalData[fPadData[iPad].fIX][fPadData[iPad].fIY][fPadData[iPad].fPlane] = 0;
1885     fPadData[iPad].fDetElemId = 0;
1886     fPadData[iPad].fIX = 0 ;
1887     fPadData[iPad].fIY = 0 ;
1888     fPadData[iPad].fRealX = 0.0 ;
1889     fPadData[iPad].fRealY = 0.0 ;
1890     fPadData[iPad].fRealZ = 0.0 ;
1891     fPadData[iPad].fHalfPadSize = -1 ;
1892     fPadData[iPad].fPlane = 0 ;
1893     fPadData[iPad].fCharge = 0 ;
1894     fPadData[iPad].fBusPatch = -1;
1895     fPadData[iPad].fRawData = 0;
1896   }  
1897
1898   for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
1899     fNofDataInDetElem[idet] = 0;
1900   
1901   // for(int i=0;i<130;i++)
1902   //   fMaxFiredPerDetElem[i] = 0;
1903 }
1904
1905
1906 AliHLTInt32_t AliHLTMUONHitReconstructor::GetkNofDetElemInDDL(Int_t iDDL)
1907 {
1908         /// Returns the number of detection elements for a DDL.
1909         
1910         if(iDDL>=0 && iDDL<=19)
1911                 return fgkNofDetElemInDDL[iDDL];
1912         else
1913                 return -1;
1914 }
1915
1916
1917 AliHLTInt32_t AliHLTMUONHitReconstructor::GetkMinDetElemIdInDDL(Int_t iDDL)
1918 {
1919         /// Returns the first detection element ID for a DDL.
1920         
1921         if(iDDL>=0 && iDDL<=19)
1922                 return fgkMinDetElemIdInDDL[iDDL];
1923         else
1924                 return -1;
1925 }
1926
1927
1928 AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::AliHLTMUONRawDecoder() :
1929         fkBufferStart(NULL),
1930         fBusPatchId(0),
1931         fDCCut(-1),
1932         fPadData(NULL),
1933         fkLookUpTableData(NULL),
1934         fkIdToEntry(),
1935         fkMaxEntryPerBusPatch(),
1936         fDDL(-1),
1937         fDataCount(1),
1938         fPrevDetElemId(0),
1939         fPadCharge(0),
1940         fCharge(0.0),
1941         fIdManuChannel(0x0),
1942         fLutEntry(0),
1943         fDataCountListPerDetElem(NULL),
1944         fNofDataInDetElem(NULL),
1945         fWarnOnly(false),
1946         fSkipParityErrors(false),
1947         fDontPrintParityErrors(false),
1948         fPrintParityErrorAsWarning(false),
1949         fParityErrorFound(false),
1950         fNonParityErrorFound(false),
1951         fIsMuchNoisy(false)
1952 {
1953         // ctor
1954 }
1955
1956
1957 AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::~AliHLTMUONRawDecoder()
1958 {
1959         // dtor
1960 }
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         assert( buffer != NULL );
1970         fkBufferStart = buffer;
1971         // dataCount starts from 1 because the 0-th element of fPadData is used as null value.
1972         fDataCount = 1;
1973         for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
1974           fNofDataInDetElem[idet] = 0;
1975         fPrevDetElemId = 0;
1976         fParityErrorFound = false;
1977         fNonParityErrorFound = false;
1978 };
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         if (code == kParityError)
1990         {
1991                 fParityErrorFound = true;
1992         }
1993         else
1994         {
1995                 fNonParityErrorFound = true;
1996         }
1997         if (fDontPrintParityErrors and code == kParityError) return;
1998         
1999         long bytepos = long(location) - long(fkBufferStart);
2000         if (fWarnOnly or (fPrintParityErrorAsWarning and code == kParityError))
2001         {
2002                 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                 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 };
2014
2015 void  AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnNewBusPatch(const AliMUONBusPatchHeaderStruct* header, const void* /*data*/) 
2016 {
2017   // operation to perform on new data
2018   fBusPatchId = int(header->fBusPatchId);
2019   MaxEntryPerBusPatch& maxEntryPerBusPatch 
2020     = * const_cast<MaxEntryPerBusPatch*>(fkMaxEntryPerBusPatch);
2021   fIsMuchNoisy = false;
2022   if(AliHLTInt32_t(header->fLength)> maxEntryPerBusPatch[fBusPatchId])
2023     fIsMuchNoisy = true;
2024   
2025 };
2026
2027 void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnData(UInt_t dataWord, bool parityError)
2028 {
2029   //function to arrange the decoded Raw Data
2030
2031   if (fSkipParityErrors and parityError) return;
2032   
2033   if(fIsMuchNoisy) return;
2034
2035   fIdManuChannel = 0x0;
2036   fIdManuChannel = (fIdManuChannel|fBusPatchId)<<17;
2037   fIdManuChannel |= (dataWord >> 12) & 0x1FFFF;
2038   
2039   IdManuChannelToEntry& idToEntry = * const_cast<IdManuChannelToEntry*>(fkIdToEntry);
2040   fLutEntry = idToEntry[fIdManuChannel];
2041   if(fLutEntry==0)
2042   {
2043     HLTDebug("Failed to find a valid LUT entry.");
2044     return;
2045   }
2046   fPadCharge = int(((unsigned short)(dataWord & 0xFFF)) - fkLookUpTableData[fLutEntry].fPed);
2047   
2048   fCharge = 0;    
2049   if(fPadCharge > 2.0*fkLookUpTableData[fLutEntry].fSigma){  // (charge > 4) is due cut out the noise level                     
2050       
2051     fPadData[fDataCount].fDetElemId = fkLookUpTableData[fLutEntry].fDetElemId;
2052     fPadData[fDataCount].fIX = AliHLTInt32_t(AliHLTUInt32_t(fkLookUpTableData[fLutEntry].fIX) % 336);  // modulus protectes against overflow.
2053     fPadData[fDataCount].fIY = AliHLTInt32_t(AliHLTUInt32_t(fkLookUpTableData[fLutEntry].fIY) % 237);  // modulus protectes against overflow.
2054     fPadData[fDataCount].fRealX = fkLookUpTableData[fLutEntry].fRealX;
2055     fPadData[fDataCount].fRealY = fkLookUpTableData[fLutEntry].fRealY;
2056     fPadData[fDataCount].fRealZ = fkLookUpTableData[fLutEntry].fRealZ;
2057     fPadData[fDataCount].fHalfPadSize = fkLookUpTableData[fLutEntry].fHalfPadSize;
2058     fPadData[fDataCount].fPadSizeXY = fkLookUpTableData[fLutEntry].fPadSizeXY;
2059     fPadData[fDataCount].fPlane = fkLookUpTableData[fLutEntry].fPlane & 0x1;  // The mask makes sure the plane value is within range.
2060     fPadData[fDataCount].fBusPatch = fBusPatchId;
2061     fPadData[fDataCount].fRawData = dataWord;
2062     
2063     if ( fPadCharge < fkLookUpTableData[fLutEntry].fThres ) {
2064       fCharge = (fkLookUpTableData[fLutEntry].fA0)*fPadCharge;
2065     }else{
2066       fCharge = (fkLookUpTableData[fLutEntry].fA0)*(fkLookUpTableData[fLutEntry].fThres) 
2067         + (fkLookUpTableData[fLutEntry].fA0)*(fPadCharge-fkLookUpTableData[fLutEntry].fThres) 
2068         + (fkLookUpTableData[fLutEntry].fA1)*(fPadCharge-fkLookUpTableData[fLutEntry].fThres)*(fPadCharge-fkLookUpTableData[fLutEntry].fThres);
2069     }
2070     
2071     fPadData[fDataCount].fCharge = fCharge;
2072     
2073     if(fkLookUpTableData[fLutEntry].fDetElemId/100 == 6){
2074       fDataCountListPerDetElem[
2075                                ((fkLookUpTableData[fLutEntry].fDetElemId-(GetkMinDetElemIdInDDL(fDDL)+100))%GetkNofDetElemInDDL(fDDL) 
2076                                 + GetkNofDetElemInDDL(fDDL)/2)
2077                                ]
2078         [fNofDataInDetElem[((fkLookUpTableData[fLutEntry].fDetElemId-(GetkMinDetElemIdInDDL(fDDL)+100))%GetkNofDetElemInDDL(fDDL) 
2079                             + GetkNofDetElemInDDL(fDDL)/2)
2080                            ]++] = fDataCount;
2081     }else{
2082       fDataCountListPerDetElem[(fkLookUpTableData[fLutEntry].fDetElemId-GetkMinDetElemIdInDDL(fDDL))%GetkNofDetElemInDDL(fDDL)]
2083         [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     fDataCount++;
2119   }// if charge is more than DC Cut limit condition
2120   
2121 }