]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/OnlineAnalysis/AliHLTMUONHitReconstructor.cxx
Integrating dimuon HLT with AliSimulation framework via AliHLTSystem interfaces.
[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 <cstring>
39 #include <strings.h>
40
41
42 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkDetectorId = 0xA00;
43 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkDDLOffSet = 12;
44 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkNofDDL = 8;
45 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkDDLHeaderSize = 8;
46 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkLutLine = 59648 + 1;
47
48
49 AliHLTMUONHitReconstructor::AliHLTMUONHitReconstructor() :
50         AliHLTLogging(),
51         fHLTMUONDecoder(),
52         fkBlockHeaderSize(8),
53         fkDspHeaderSize(8),
54         fkBuspatchHeaderSize(4),
55         fDCCut(0),
56         fPadData(NULL),
57         fLookUpTableData(NULL),
58         fRecPoints(NULL),
59         fRecPointsCount(NULL),
60         fMaxRecPointsCount(0),
61         fCentralCountB(0),
62         fCentralCountNB(0),
63         fDigitPerDDL(0),
64         fCentralChargeB(NULL),
65         fCentralChargeNB(NULL),
66         fRecX(NULL),
67         fRecY(NULL),
68         fAvgChargeX(NULL),
69         fAvgChargeY(NULL),
70         fNofBChannel(NULL),
71         fNofNBChannel(NULL),
72         fNofFiredDetElem(0),
73         fIdToEntry()
74 {
75         /// Default constructor
76         
77         fkBlockHeaderSize    = 8;
78         fkDspHeaderSize      = 8;
79         fkBuspatchHeaderSize = 4;
80         
81         try
82         {
83                 fPadData = new AliHLTMUONPad[fgkLutLine];
84         }
85         catch (const std::bad_alloc&)
86         {
87                 HLTError("Dynamic memory allocation failed for fPadData in constructor.");
88                 throw;
89         }
90         
91         fPadData[0].fDetElemId = 0;
92         fPadData[0].fIX = 0 ;
93         fPadData[0].fIY = 0 ;
94         fPadData[0].fRealX = 0.0 ;
95         fPadData[0].fRealY = 0.0 ;
96         fPadData[0].fRealZ = 0.0 ;
97         fPadData[0].fHalfPadSize = 0.0 ;
98         fPadData[0].fPlane = -1 ;
99         fPadData[0].fCharge = 0 ;
100         
101         bzero(fGetIdTotalData, 336*237*2*sizeof(int));
102 }
103
104
105 AliHLTMUONHitReconstructor::~AliHLTMUONHitReconstructor()
106 {
107         /// Default destructor
108         
109         if (fPadData)
110         {
111                 delete [] fPadData;
112                 fPadData = NULL;
113         }
114 }
115
116
117 void AliHLTMUONHitReconstructor::SetLookUpTable(
118                 const AliHLTMUONHitRecoLutRow* lookupTable,
119                 const IdManuChannelToEntry* idToEntry
120         )
121 {
122         /// Sets the Lookup table (LUT) containing the position of each pad with
123         /// electronic channel associated with it. Also the appropriate manu
124         /// channel ID mapping to LUT row is also set.
125
126         assert( lookupTable != NULL );
127         assert( idToEntry != NULL );
128         
129         fIdToEntry = idToEntry;
130         fLookUpTableData = lookupTable;
131 }
132
133
134 bool AliHLTMUONHitReconstructor::Run(
135                 const AliHLTUInt32_t* rawData,
136                 AliHLTUInt32_t rawDataSize,
137                 AliHLTMUONRecHitStruct* recHit,
138                 AliHLTUInt32_t& nofHit
139         ) 
140 {
141   // main function called by HLTReconstructor to perform DHLT Hitreconstruction 
142
143   fRecPoints = recHit;
144   fMaxRecPointsCount = nofHit;
145   fRecPointsCount = &nofHit;
146   *fRecPointsCount = 0;
147   fDigitPerDDL = 0;
148
149   if (not DecodeDDL(rawData, rawDataSize)) {
150     // Dont need to log any message again. Already done so in DecodeDDL.
151     return false;
152   }
153
154   if (fDigitPerDDL == 1)
155   {
156     // There are no digits to process so stop here.
157     return true;
158   }
159
160   if (not FindRecHits()) {
161     HLTError("Failed to generate RecHits");
162     return false;
163   }
164
165   return true;
166 }
167
168
169 bool AliHLTMUONHitReconstructor::DecodeDDL(const AliHLTUInt32_t* rawData,AliHLTUInt32_t rawDataSize)
170 {
171   //function to decode Raw Data 
172
173   AliHLTMUONRawDecoder& handler = reinterpret_cast<AliHLTMUONRawDecoder&>(fHLTMUONDecoder.GetHandler());
174   UInt_t bufferSize = UInt_t(rawDataSize*sizeof(AliHLTUInt32_t));
175
176   handler.SetDCCut(fDCCut);
177   handler.SetPadData(fPadData);
178   handler.SetLookUpTable(fLookUpTableData);
179   handler.SetIdManuChannelToEntry(fIdToEntry);
180   handler.SetNofFiredDetElemId(fNofFiredDetElem);
181   handler.SetMaxFiredPerDetElem(fMaxFiredPerDetElem);
182  
183   if(!fHLTMUONDecoder.Decode(rawData,bufferSize))
184     return false;
185
186   fDigitPerDDL = handler.GetDataCount();
187   fMaxFiredPerDetElem[fNofFiredDetElem-1] = handler.GetDataCount();
188     
189   if(fDigitPerDDL == 1){
190     HLTInfo("An Empty DDL File found");
191   }
192     
193   return true;
194 }
195
196
197 bool AliHLTMUONHitReconstructor::FindRecHits()
198 {
199   // fuction that calls hit reconstruction detector element-wise.
200
201   assert( fCentralChargeB == NULL );
202   assert( fCentralChargeNB == NULL );
203   assert( fRecX == NULL );
204   assert( fRecY == NULL );
205   assert( fAvgChargeX == NULL );
206   assert( fAvgChargeY == NULL );
207   assert( fNofBChannel == NULL );
208   assert( fNofNBChannel == NULL );
209   
210   bool resultOk = false;
211
212   for(int iDet=0; iDet<fNofFiredDetElem ; iDet++)
213   {
214     fCentralCountB = 0;
215     fCentralCountNB = 0;
216
217     try
218     {
219       fCentralChargeB = new int[fMaxFiredPerDetElem[iDet]];
220       HLTDebug("Allocated fCentralChargeB with %d elements.", fMaxFiredPerDetElem[iDet]);
221       fCentralChargeNB = new int[fMaxFiredPerDetElem[iDet]];
222       HLTDebug("Allocated fCentralChargeNB with %d elements.", fMaxFiredPerDetElem[iDet]);
223       resultOk = true;
224     }
225     catch(const std::bad_alloc&)
226     {
227       HLTError("Dynamic memory allocation failed for fCentralChargeNB and fCentralChargeB");
228       resultOk = false;
229     }
230
231     // Continue processing, but check if everything is OK as we do, otherwise
232     // do not execute the next steps.
233     if (resultOk)
234     {
235       if(iDet>0)
236         FindCentralHits(fMaxFiredPerDetElem[iDet-1],fMaxFiredPerDetElem[iDet]);
237       else
238         // minimum value is 1 because dataCount in ReadDDL starts from 1 instead of 0;
239         FindCentralHits(1,fMaxFiredPerDetElem[iDet]);
240
241       try
242       {
243         fRecY = new float[fCentralCountB];
244         HLTDebug("Allocated fRecY with %d elements.", fCentralCountB);
245         fRecX = new float[fCentralCountNB];
246         HLTDebug("Allocated fRecX with %d elements.", fCentralCountNB);
247         fAvgChargeY = new float[fCentralCountB];
248         HLTDebug("Allocated fAvgChargeY with %d elements.", fCentralCountB);
249         fAvgChargeX = new float[fCentralCountNB];
250         HLTDebug("Allocated fAvgChargeX with %d elements.", fCentralCountNB);
251         fNofBChannel = new int[fCentralCountB];
252         HLTDebug("Allocated fNofBChannel with %d elements.", fCentralCountB);
253         fNofNBChannel = new int[fCentralCountNB];
254         HLTDebug("Allocated fNofNBChannel with %d elements.", fCentralCountNB);
255         resultOk = true;
256       }
257       catch(const std::bad_alloc&){
258         HLTError("Dynamic memory allocation failed for internal arrays.");
259         resultOk = false;
260       }
261     }
262
263     if (resultOk) RecXRecY();
264     if (resultOk)
265     {
266       resultOk = MergeRecHits();
267     }
268     if (resultOk)
269     {
270       if(iDet==0)
271         // minimum value in loop is 1 because dataCount in ReadDDL starts from 1 instead of 0;
272         for(int i=1;i<fMaxFiredPerDetElem[iDet];i++)
273           fGetIdTotalData[fPadData[i].fIX][fPadData[i].fIY][fPadData[i].fPlane] = 0;
274       else
275         for(int i=fMaxFiredPerDetElem[iDet-1];i<fMaxFiredPerDetElem[iDet];i++)
276           fGetIdTotalData[fPadData[i].fIX][fPadData[i].fIY][fPadData[i].fPlane] = 0;
277     }
278
279     // Make sure to release any memory that was allocated.
280     if (fCentralChargeB != NULL)
281     {
282       delete [] fCentralChargeB;
283       HLTDebug("Released fCentralChargeB array.");
284       fCentralChargeB = NULL;
285     }
286     if (fCentralChargeNB != NULL)
287     {
288       delete [] fCentralChargeNB;
289       HLTDebug("Released fCentralChargeNB array.");
290       fCentralChargeNB = NULL;
291     }
292     if (fRecX != NULL)
293     {
294       delete [] fRecX;
295       HLTDebug("Released fRecX array.");
296       fRecX = NULL;
297     }
298     if (fRecY != NULL)
299     {
300       delete [] fRecY;
301       HLTDebug("Released fRecY array.");
302       fRecY = NULL;
303     }
304     if (fAvgChargeX != NULL)
305     {
306       delete [] fAvgChargeX;
307       HLTDebug("Released fAvgChargeX array.");
308       fAvgChargeX = NULL;
309     }
310     if (fAvgChargeY != NULL)
311     {
312       delete [] fAvgChargeY;
313       HLTDebug("Released fAvgChargeY array.");
314       fAvgChargeY = NULL;
315     }
316     if (fNofBChannel != NULL)
317     {
318       delete [] fNofBChannel;
319       HLTDebug("Released fNofBChannel array.");
320       fNofBChannel = NULL;
321     }
322     if (fNofNBChannel != NULL)
323     {
324       delete [] fNofNBChannel;
325       HLTDebug("Released fNofNBChannel array.");
326       fNofNBChannel = NULL;
327     }
328   }
329
330   Clear();  // clear internal arrays.
331
332   return resultOk;
333 }
334
335
336 void AliHLTMUONHitReconstructor::FindCentralHits(int minPadId, int maxPadId)
337 {
338   // to find central hit associated with each cluster
339
340   assert( fCentralChargeB != NULL );
341   assert( fCentralChargeNB != NULL );
342
343   int b,nb;
344   int idManuChannelCentral;
345   bool hasFind;
346
347   for(int iPad=minPadId;iPad<maxPadId;iPad++){
348
349     fGetIdTotalData[fPadData[iPad].fIX]
350       [fPadData[iPad].fIY]
351       [fPadData[iPad].fPlane] = iPad ;
352     
353     if(fPadData[iPad].fPlane == 0 ){//&& fPadData[iPad].fIY > (0+1) && fPadData[iPad].fIY < (79 - 1)){
354       //if(fPadData[iPad].fIY > 0){
355       if(fCentralCountB>0){
356         hasFind = false;
357         for(b = 0;b<fCentralCountB;b++){
358           idManuChannelCentral = fCentralChargeB[b];
359           if(fPadData[iPad].fIX == fPadData[idManuChannelCentral].fIX
360              &&
361              (fPadData[iPad].fIY 
362               == fPadData[idManuChannelCentral].fIY + 1 
363               ||
364               fPadData[iPad].fIY 
365               == fPadData[idManuChannelCentral].fIY + 2 
366               ||
367               fPadData[iPad].fIY 
368               == fPadData[idManuChannelCentral].fIY - 2 
369               ||
370               fPadData[iPad].fIY 
371               == fPadData[idManuChannelCentral].fIY - 1)){
372             
373             hasFind = true;
374             if(fPadData[iPad].fCharge > fPadData[idManuChannelCentral].fCharge){
375               fCentralChargeB[b] = iPad;
376             }// if condn on pad charge
377           }// if condon on pad position
378         }// for loop over b
379         if(!hasFind){
380           fCentralChargeB[fCentralCountB] = iPad;
381           fCentralCountB++;
382         }
383       }
384       else{
385         fCentralChargeB[fCentralCountB] = iPad;
386         fCentralCountB++;
387       }// check the size of centralHitB
388       for(b = 0;b<fCentralCountB;b++){
389         idManuChannelCentral = fCentralChargeB[b];
390       }
391       //}// if cond on iY > 2 (to avoid edge value pb)
392     }// B/Nb checking
393     else{
394       if(fCentralCountNB>0){
395         hasFind = false;
396         for(nb = 0;nb<fCentralCountNB;nb++){
397           idManuChannelCentral = fCentralChargeNB[nb];
398           if(fPadData[iPad].fIY == fPadData[idManuChannelCentral].fIY
399              &&
400              (fPadData[iPad].fIX 
401               == fPadData[idManuChannelCentral].fIX + 1 
402               ||
403               fPadData[iPad].fIX
404               == fPadData[idManuChannelCentral].fIX + 2
405               ||
406               fPadData[iPad].fIX
407               == fPadData[idManuChannelCentral].fIX - 2
408               ||
409               fPadData[iPad].fIX
410               == fPadData[idManuChannelCentral].fIX - 1)){
411             
412             hasFind = true;       
413             if(fPadData[iPad].fCharge > fPadData[idManuChannelCentral].fCharge){
414               fCentralChargeNB[nb] = iPad;
415             }// if condn over to find higher charge
416           }// if condn over to find position
417         }// for loop over presently all nb values
418         if(!hasFind){
419           fCentralChargeNB[fCentralCountNB] = iPad;
420           fCentralCountNB++;
421         }
422       }// centralHitNB size test
423       else{
424         fCentralChargeNB[fCentralCountNB] = iPad;
425         fCentralCountNB++;
426       }// centralHitNB size test
427       
428     }// fill for bending and nonbending hit
429   }// detElemId loop
430
431 }
432
433
434 void AliHLTMUONHitReconstructor::RecXRecY()
435 {
436   // find reconstructed X and Y for each plane separately
437
438   assert( fRecX != NULL );
439   assert( fRecY != NULL );
440   assert( fAvgChargeX != NULL );
441   assert( fAvgChargeY != NULL );
442   assert( fNofBChannel != NULL );
443   assert( fNofNBChannel != NULL );
444
445   int b,nb;
446   int idCentral;
447   int idLower = 0;
448   int idUpper = 0;
449   int idRight = 0;
450   int idLeft = 0;
451   
452   for(b=0;b<fCentralCountB;b++){
453     idCentral = fCentralChargeB[b];
454
455     if(fPadData[idCentral].fIY==0)
456       idLower = 0;
457     else
458       idLower = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY-1][0];
459
460     if(fPadData[idCentral].fIX==236)
461       idUpper = 0;
462     else
463       idUpper = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY+1][0];
464
465
466     fRecY[b] = (fPadData[idCentral].fRealY*fPadData[idCentral].fCharge
467                +
468                 fPadData[idUpper].fRealY*fPadData[idUpper].fCharge
469                +
470                 fPadData[idLower].fRealY*fPadData[idLower].fCharge
471                 )/(fPadData[idCentral].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge) ;
472     
473     fAvgChargeY[b] = (fPadData[idCentral].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge)/3.0 ;
474     
475     fNofBChannel[b] = 0;
476     if(fPadData[idLower].fCharge>0)
477       fNofBChannel[b]++ ;
478     if(fPadData[idCentral].fCharge>0)
479       fNofBChannel[b]++ ;
480     if(fPadData[idUpper].fCharge>0)
481       fNofBChannel[b]++ ;
482
483     HLTDebug("lower : %d, middle : %d, upper : %d, nofChannel : %d",fPadData[idLower].fCharge,
484             fPadData[idCentral].fCharge,fPadData[idUpper].fCharge,fNofBChannel[b]);
485
486     HLTDebug("RecY[%d] : %f",b,fRecY[b]);
487   }
488       
489   for(nb=0;nb<fCentralCountNB;nb++){
490     idCentral = fCentralChargeNB[nb];
491
492     if(fPadData[idCentral].fIX==0)
493       idLeft = 0;
494     else
495       idLeft = fGetIdTotalData[fPadData[idCentral].fIX-1][fPadData[idCentral].fIY][1];
496     
497     if(fPadData[idCentral].fIX==335)
498       idRight = 0 ;
499     else
500       idRight = fGetIdTotalData[fPadData[idCentral].fIX+1][fPadData[idCentral].fIY][1];
501
502     fRecX[nb] = (fPadData[idCentral].fRealX*fPadData[idCentral].fCharge
503                  +
504                  fPadData[idRight].fRealX*fPadData[idRight].fCharge
505                  +
506                  fPadData[idLeft].fRealX*fPadData[idLeft].fCharge
507                  )/(fPadData[idCentral].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
508     
509
510     fAvgChargeX[nb] = (fPadData[idCentral].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge)/3.0 ;
511     
512     
513     fNofNBChannel[nb] = 0;
514     if(fPadData[idLeft].fCharge>0)
515       fNofNBChannel[nb]++ ;
516     if(fPadData[idCentral].fCharge>0)
517       fNofNBChannel[nb]++ ;
518     if(fPadData[idRight].fCharge>0)
519       fNofNBChannel[nb]++ ;
520
521     HLTDebug("left : %d, middle : %d, right : %d, nofChannel : %d",fPadData[idLeft].fCharge,
522             fPadData[idCentral].fCharge,fPadData[idRight].fCharge,fNofNBChannel[nb]);
523
524     HLTDebug("RecX[%d] : %f",nb,fRecX[nb]);
525
526   }
527 }
528
529
530 bool AliHLTMUONHitReconstructor::MergeRecHits()
531 {
532   // Merge reconstructed hits first over same plane then bending plane with non-bending plane
533
534   assert( fRecX != NULL );
535   assert( fRecY != NULL );
536   assert( fAvgChargeX != NULL );
537   assert( fAvgChargeY != NULL );
538   assert( fNofBChannel != NULL );
539   assert( fNofNBChannel != NULL );
540
541   int idCentralB,idCentralNB ;
542   float padCenterXB;
543   float padCenterYNB;
544   float diffX,diffY;
545   float halfPadLengthX,halfPadLengthY;
546
547   // MERGE Bending Plane hits, which are placed side by side
548   for(int i=0;i<fCentralCountB-1;i++){
549     if(fRecY[i] != 0.0){
550       for(int j=i+1;j<fCentralCountB;j++){
551                  
552         if(fCentralChargeB[i]==fCentralChargeB[j]){
553           fRecY[j] = 0.0;
554           continue;
555         }
556         else if(
557            (
558             fPadData[fCentralChargeB[i]].fIY == fPadData[fCentralChargeB[j]].fIY
559             )
560            &&
561            (
562             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX + 1
563             ||
564             fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX - 1
565             )
566            &&
567            fRecY[j] != 0.0
568            &&
569            fRecY[i] != 0.0
570            ){
571
572           if(fAvgChargeY[i] > fAvgChargeY[j]){
573             fRecY[i] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
574                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
575             fRecY[j] = 0.0;
576           }
577           else{
578             fRecY[j] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
579                         )/(fAvgChargeY[i] + fAvgChargeY[j]);
580             fRecY[i] = 0.0;
581
582           }// search for higher charge
583         }//pad position
584       }//j for loop
585     }//if fRecY[i] != 0.0
586   }// i for loop
587   
588   // MERGE Non Bending Plane hits, which are place side by side
589   for(int i=0;i<fCentralCountNB-1;i++){
590     if(fRecX[i] != 0.0){
591       for(int j=i+1;j<fCentralCountNB;j++){
592
593         if(fCentralChargeNB[i]==fCentralChargeNB[j]){
594           fRecX[j] = 0.0;
595           continue;
596         }
597         else if(
598            (
599             fPadData[fCentralChargeNB[i]].fIX == fPadData[fCentralChargeNB[j]].fIX
600             )
601            &&
602            (
603             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY + 1
604             ||
605             fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY - 1
606             )
607            &&
608            fRecX[j] != 0.0
609            &&
610            fRecX[i] != 0.0
611            ){
612
613           if(fAvgChargeX[i] > fAvgChargeX[j]){
614             fRecX[i] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
615                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
616             fRecX[j] = 0.0;
617           }
618           else{
619             fRecX[j] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
620                        )/(fAvgChargeX[i] + fAvgChargeX[j]);
621             fRecX[i] = 0.0;
622           }// search for higher charge
623         }//pad position
624       }//j for loop
625     }//if fRecX[i] != 0.0
626   }// i for loop
627
628   // Merge bending Plane hits with Non Bending
629   for(int b=0;b<fCentralCountB;b++){
630     if(fRecY[b]!=0.0){
631       idCentralB = fCentralChargeB[b];
632       padCenterXB = fPadData[idCentralB].fRealX; 
633       
634       halfPadLengthX = fPadData[idCentralB].fIY ;
635
636       for(int nb=0;nb<fCentralCountNB;nb++){
637         if(fRecX[nb]!=0.0){
638           idCentralNB = fCentralChargeNB[nb];
639
640           padCenterYNB = fPadData[idCentralNB].fRealY;
641
642           halfPadLengthY = fPadData[idCentralNB].fHalfPadSize ;
643
644           if(fabsf(fRecX[nb]) > fabsf(padCenterXB))
645             diffX = fabsf(fRecX[nb]) -  fabsf(padCenterXB);
646           else
647             diffX = fabsf(padCenterXB) -  fabsf(fRecX[nb]);
648           
649           if(fabsf(padCenterYNB)>fabsf(fRecY[b]))
650             diffY = fabsf(padCenterYNB) - fabsf(fRecY[b]);
651           else
652             diffY =  fabsf(fRecY[b]) - fabsf(padCenterYNB);
653
654           if(diffX < halfPadLengthX && diffY < halfPadLengthY ){//&& fPadData[idCentralB].fIY != 0){
655
656             if(fNofBChannel[b]==3)
657               fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
658             
659             fRecX[nb] += 0.075*sin(9.5*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
660             
661             // First check that we have not overflowed the buffer.
662             if((*fRecPointsCount) == fMaxRecPointsCount){
663               HLTError("Number of RecHit (i.e. %d) exceeds the max number of RecHit limit %d.",(*fRecPointsCount),fMaxRecPointsCount);
664               return false;
665             }
666             
667             //fRecPoints[(*fRecPointsCount)].fId = idCentralB;
668             fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
669             fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
670             fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
671 //          fRecPoints[(*fRecPointsCount)].fXCenter = fPadData[idCentralNB].fRealX;
672 //          fRecPoints[(*fRecPointsCount)].fYCenter = fPadData[idCentralB].fRealY;
673 //          fRecPoints[(*fRecPointsCount)].fNofBChannel = fNofBChannel[b];
674 //          fRecPoints[(*fRecPointsCount)].fNofNBChannel = fNofNBChannel[nb];
675 //          fRecPoints[(*fRecPointsCount)].fDetElemId = (AliHLTUInt32_t)fPadData[idCentralB].fDetElemId;
676             (*fRecPointsCount)++;
677           }//if lies wihtin 5.0 mm
678         }// condn over fRecX ! = 0.0
679       }// loop over NB side
680     }// condn on fRecY[b] !=  0.0
681   }// loop over B side;
682
683   return true;
684 }
685
686
687 void AliHLTMUONHitReconstructor::Clear()
688 {
689   // function to clear internal arrays.
690
691   for(int iPad=1;iPad<fDigitPerDDL;iPad++){
692     fGetIdTotalData[fPadData[iPad].fIX][fPadData[iPad].fIY][fPadData[iPad].fPlane] = 0;
693     fPadData[iPad].fDetElemId = 0;
694     fPadData[iPad].fIX = 0 ;
695     fPadData[iPad].fIY = 0 ;
696     fPadData[iPad].fRealX = 0.0 ;
697     fPadData[iPad].fRealY = 0.0 ;
698     fPadData[iPad].fRealZ = 0.0 ;
699     fPadData[iPad].fHalfPadSize = -1 ;
700     fPadData[iPad].fPlane = -1 ;
701     fPadData[iPad].fCharge = 0 ;
702   }  
703   
704   for(int i=0;i<13;i++)
705     fMaxFiredPerDetElem[i] = 0;
706 }
707
708
709 AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::AliHLTMUONRawDecoder() :
710         fBufferStart(NULL),
711         fBusPatchId(0),
712         fDCCut(0),
713         fPadData(NULL),
714         fLookUpTableData(NULL),
715         fNofFiredDetElem(NULL),
716         fMaxFiredPerDetElem(NULL),
717         fIdToEntry(),
718         fDataCount(1),
719         fPrevDetElemId(0),
720         fPadCharge(0),
721         fCharge(0.0),
722         fIdManuChannel(0x0),
723         fLutEntry(0)
724 {
725         // ctor
726 }
727
728
729 AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::~AliHLTMUONRawDecoder()
730 {
731         // dtor
732 }
733
734
735 void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnNewBuffer(const void* buffer, UInt_t /*bufferSize*/)
736 {
737         /// Called for every new raw DDL data payload being processed.
738         /// Just clears internal counters.
739         /// \param buffer  The pointer to the raw data buffer.
740
741         assert( buffer != NULL );
742         fBufferStart = buffer;
743         // dataCount starts from 1 because the 0-th element of fPadData is used as null value.
744         fDataCount = 1;
745         *fNofFiredDetElem = 0;
746         fPrevDetElemId = 0 ;
747 };
748
749
750 void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnError(ErrorCode code, const void* location)
751 {
752         /// Called if there was an error detected in the raw DDL data.
753         /// Logs an error message.
754         /// \param code  The error code describing the problem.
755         /// \param location  A pointer to the location in the raw data buffer
756         ///      where the problem was found.
757         
758         long bytepos = long(location) - long(fBufferStart) + sizeof(AliRawDataHeader);
759         HLTError("There is a problem with decoding the raw data. %s (Error code: %d, at byte %d)",
760                 ErrorCodeToMessage(code), code, bytepos
761         );
762 };
763
764
765 void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnData(UInt_t dataWord, bool /*parityError*/)
766 {
767   //function to arrange the decoded Raw Data
768
769   fIdManuChannel = 0x0;
770   fIdManuChannel = (fIdManuChannel|fBusPatchId)<<17;
771   fIdManuChannel |= (dataWord >> 12) & 0x1FFFF;
772   
773   IdManuChannelToEntry& idToEntry = * const_cast<IdManuChannelToEntry*>(fIdToEntry);
774   fLutEntry = idToEntry[fIdManuChannel];
775   fPadCharge = int(((unsigned short)(dataWord & 0xFFF)) - fLookUpTableData[fLutEntry].fPed);
776   
777   fCharge = 0;    
778   if(fPadCharge > fDCCut && fPadCharge > 5.0*fLookUpTableData[fLutEntry].fSigma){  // (charge > 4) is due cut out the noise level                       
779       
780     fPadData[fDataCount].fDetElemId = fLookUpTableData[fLutEntry].fDetElemId;
781     fPadData[fDataCount].fIX = fLookUpTableData[fLutEntry].fIX;
782     fPadData[fDataCount].fIY = fLookUpTableData[fLutEntry].fIY;
783     fPadData[fDataCount].fRealX = fLookUpTableData[fLutEntry].fRealX;
784     fPadData[fDataCount].fRealY = fLookUpTableData[fLutEntry].fRealY;
785     fPadData[fDataCount].fRealZ = fLookUpTableData[fLutEntry].fRealZ;
786     fPadData[fDataCount].fHalfPadSize = fLookUpTableData[fLutEntry].fHalfPadSize;
787     fPadData[fDataCount].fPlane = fLookUpTableData[fLutEntry].fPlane;
788     
789     if ( fPadCharge < fLookUpTableData[fLutEntry].fThres ) {
790       fCharge = (fLookUpTableData[fLutEntry].fA0)*fPadCharge;
791     }else{
792       fCharge = (fLookUpTableData[fLutEntry].fA0)*(fLookUpTableData[fLutEntry].fThres) 
793         + (fLookUpTableData[fLutEntry].fA0)*(fPadCharge-fLookUpTableData[fLutEntry].fThres) 
794         + (fLookUpTableData[fLutEntry].fA1)*(fPadCharge-fLookUpTableData[fLutEntry].fThres)*(fPadCharge-fLookUpTableData[fLutEntry].fThres);
795     }
796     
797     fPadData[fDataCount].fCharge = fCharge;
798     
799     if(fLookUpTableData[fLutEntry].fDetElemId != fPrevDetElemId){
800       if((*fNofFiredDetElem)>0){
801         fMaxFiredPerDetElem[(*fNofFiredDetElem)-1] = fDataCount;
802       }
803       (*fNofFiredDetElem)++;
804       fPrevDetElemId =  fLookUpTableData[fLutEntry].fDetElemId ;
805     }
806     
807 //     HLTDebug("buspatch : %d, detele : %d, id : %d, manu : %d, channel : %d, iX : %d, iY: %d, (X,Y) : (%f, %f), charge : %d, padsize : %f, plane : %d",
808 //           fBusPatchId,fPadData[fDataCount].fDetElemId,
809 //           fIdManuChannel,((dataWord >> 18) & 0x7FF),((dataWord >> 12) & 0x3F),
810 //           fPadData[fDataCount].fIX,fPadData[fDataCount].fIY,
811 //           fPadData[fDataCount].fRealX,fPadData[fDataCount].fRealY,
812 //           fPadData[fDataCount].fCharge,fPadData[fDataCount].fHalfPadSize,fPadData[fDataCount].fPlane);
813     
814       fDataCount ++;
815   }// if charge is more than DC Cut limit condition
816   
817 }