1 /**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
6 * Indranil Das <indra.das@saha.ac.in> *
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 **************************************************************************/
19 ///////////////////////////////////////////////
20 //Author : Indranil Das, SINP, INDIA
21 // Sukalyan Chattopadhyay, SINP, INDIA
23 //Email : indra.das@saha.ac.in
24 // sukalyan.chattopadhyay@saha.ac.in
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
34 /////////////////////////////////////////////////
36 #include "AliHLTMUONHitReconstructor.h"
37 #include "AliHLTMUONRecHitsBlockStruct.h"
38 #include "AliHLTMUONClustersBlockStruct.h"
39 #include "AliHLTMUONChannelsBlockStruct.h"
40 #include "AliHLTMUONUtils.h"
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,
55 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkMinDetElemIdInDDL[20] = { 100, 101, 200, 201,
62 AliHLTMUONHitReconstructor::AliHLTMUONHitReconstructor() :
67 fkBuspatchHeaderSize(4),
70 fkLookUpTableData(NULL),
72 fRecPointsCount(NULL),
73 fMaxRecPointsCount(0),
77 fGenerateClusterInfo(false),
83 fGenerateChannelInfo(false),
88 fDataCountListPerDetElem(NULL),
89 fNofDataInDetElem(NULL),
90 fCentralChargeB(NULL),
91 fCentralChargeNB(NULL),
100 fNofYNeighbour(NULL),
102 fkMaxEntryPerBusPatch(0),
103 fRecoveryMode(kDontTryRecover)
105 /// Default constructor
107 fkBlockHeaderSize = 8;
109 fkBuspatchHeaderSize = 4;
113 fPadData = new AliHLTMUONPad[fgkLutLine];
115 catch (const std::bad_alloc&)
117 HLTError("Dynamic memory allocation failed for fPadData in constructor.");
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 ;
133 bzero(fGetIdTotalData, 336*237*2*sizeof(int));
137 AliHLTMUONHitReconstructor::~AliHLTMUONHitReconstructor()
139 /// Default destructor
147 if (fClusters != NULL)
151 if (fChannels != NULL)
158 void AliHLTMUONHitReconstructor::SetLookUpTable(
159 const AliHLTMUONHitRecoLutRow* lookupTable,
160 const IdManuChannelToEntry* idToEntry,
161 const MaxEntryPerBusPatch* maxEntryPerBP
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.
168 assert( lookupTable != NULL );
169 assert( idToEntry != NULL );
170 assert( maxEntryPerBP != NULL );
172 fkLookUpTableData = lookupTable;
173 fkIdToEntry = idToEntry;
174 fkMaxEntryPerBusPatch = maxEntryPerBP;
177 bool AliHLTMUONHitReconstructor::DeInitDetElemInDDLArray()
181 if (fDataCountListPerDetElem)
183 delete [] fDataCountListPerDetElem;
184 fDataCountListPerDetElem = NULL;
187 if (fNofDataInDetElem)
189 delete [] fNofDataInDetElem;
190 fNofDataInDetElem = NULL;
196 bool AliHLTMUONHitReconstructor::InitDetElemInDDLArray()
201 if(GetkNofDetElemInDDL(fDDL)==-1){
202 HLTError("Check if the DDLNumber(AliHLTInt32_t value) is Set before this method");
207 fDataCountListPerDetElem = new AliHLTUInt16_t*[GetkNofDetElemInDDL(fDDL)];
208 }catch (const std::bad_alloc&){
209 HLTError("Dynamic memory allocation failed in constructor : fDataCountListPerDetElem");
213 for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
215 fDataCountListPerDetElem[idet] = new AliHLTUInt16_t[fgkMaxNofDataPerDetElem];
216 }catch (const std::bad_alloc&){
217 HLTError("Dynamic memory allocation failed in constructor : fDataCountListPerDetElem[%d]",idet);
222 fNofDataInDetElem = new AliHLTUInt16_t[GetkNofDetElemInDDL(fDDL)];
223 }catch (const std::bad_alloc&){
224 HLTError("Dynamic memory allocation failed in constructor : fDataCountListPerDetElem");
228 for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
229 fNofDataInDetElem[idet] = 0;
234 void AliHLTMUONHitReconstructor::TryRecover(ERecoveryMode mode)
236 /// Sets if the decoder should enable the error recovery logic.
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;
244 fHLTMUONDecoder.TryRecover(true);
245 fHLTMUONDecoder.ExitOnError(false);
246 fHLTMUONDecoder.GetHandler().WarnOnly(true);
247 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
249 case kRecoverJustSkip:
250 fHLTMUONDecoder.TryRecover(false);
251 fHLTMUONDecoder.ExitOnError(false);
252 fHLTMUONDecoder.GetHandler().WarnOnly(true);
253 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
255 case kRecoverFromParityErrorsOnly:
256 fHLTMUONDecoder.TryRecover(false);
257 fHLTMUONDecoder.ExitOnError(false);
258 fHLTMUONDecoder.GetHandler().WarnOnly(false);
259 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
262 fRecoveryMode = kDontTryRecover;
263 fHLTMUONDecoder.TryRecover(false);
264 fHLTMUONDecoder.ExitOnError(true);
265 fHLTMUONDecoder.GetHandler().WarnOnly(false);
266 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(false);
272 bool AliHLTMUONHitReconstructor::Run(
273 AliHLTUInt32_t* rawData,
274 AliHLTUInt32_t rawDataSize,
275 AliHLTMUONRecHitStruct* const recHit,
276 AliHLTUInt32_t& nofHit
279 // main function called by HLTReconstructor to perform DHLT Hitreconstruction
282 fMaxRecPointsCount = nofHit;
283 fRecPointsCount = &nofHit;
284 *fRecPointsCount = 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);
292 if (not DecodeDDL(rawData, rawDataSize)) {
293 // Dont need to log any message again. Already done so in DecodeDDL.
297 if (fDigitPerDDL == 1)
299 // There are no digits to process so stop here.
303 // Allocate fClusters and fChannels if required to do so and only if the allocated
304 // size of the arrays is too small.
307 if (fGenerateClusterInfo and fMaxClusters < fMaxRecPointsCount)
309 if (fClusters != NULL)
314 fClusters = new AliHLTMUONClusterStruct[fMaxRecPointsCount];
315 fMaxClusters = fMaxRecPointsCount;
317 if (fGenerateChannelInfo and fMaxChannels < fMaxRecPointsCount*fMaxChannelMult)
319 if (fChannels != NULL)
324 fChannels = new AliHLTMUONChannelStruct[fMaxRecPointsCount*fMaxChannelMult];
325 fMaxChannels = fMaxRecPointsCount*fMaxChannelMult;
328 catch(const std::bad_alloc&)
330 HLTError("Could not allocate memory for the extra cluster and channel information.");
334 if (not FindRecHits()) {
335 HLTError("Failed to generate RecHits");
343 bool AliHLTMUONHitReconstructor::FillClusterData(
344 AliHLTMUONClusterStruct* clusters, AliHLTUInt32_t& nofClusters
347 /// Fills the output clusters array with extra cluster information.
349 bool sizeOk = fClusterCount <= nofClusters;
350 AliHLTUInt32_t n = sizeOk ? fClusterCount : nofClusters;
351 memcpy(clusters, fClusters, sizeof(AliHLTMUONClusterStruct)*n);
357 bool AliHLTMUONHitReconstructor::FillChannelData(
358 AliHLTMUONChannelStruct* channels, AliHLTUInt32_t& nofChannels
361 /// Fills the output channels array with extra channel information for each cluster.
363 bool sizeOk = fChannelCount <= nofChannels;
364 AliHLTUInt32_t n = sizeOk ? fChannelCount : nofChannels;
365 memcpy(channels, fChannels, sizeof(AliHLTMUONChannelStruct)*n);
371 bool AliHLTMUONHitReconstructor::DecodeDDL(AliHLTUInt32_t* rawData,AliHLTUInt32_t rawDataSize)
373 //function to decode Raw Data
375 AliHLTMUONRawDecoder& handler = reinterpret_cast<AliHLTMUONRawDecoder&>(fHLTMUONDecoder.GetHandler());
376 UInt_t bufferSize = UInt_t(rawDataSize*sizeof(AliHLTUInt32_t));
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);
387 if (not fHLTMUONDecoder.Decode(rawData,bufferSize))
389 switch (TryRecover())
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())
398 HLTWarning("There was a problem with the raw data."
399 " Recovered as much data as possible."
400 " Will continue processing the next event."
404 case kRecoverJustSkip:
405 if (fHLTMUONDecoder.GetHandler().NonParityErrorFound() or
406 (fHLTMUONDecoder.GetHandler().ParityErrorFound() and not fHLTMUONDecoder.GetHandler().DontPrintParityErrors())
409 HLTWarning("There was a problem with the raw data."
410 " Skipped corrupted data structures."
411 " Will continue processing the next event."
415 case kRecoverFromParityErrorsOnly:
416 if (fHLTMUONDecoder.GetHandler().NonParityErrorFound())
418 HLTError("Failed to decode the tracker DDL raw data.");
421 if (not fHLTMUONDecoder.GetHandler().DontPrintParityErrors())
423 assert( fHLTMUONDecoder.GetHandler().ParityErrorFound() );
424 HLTWarning("Found parity errors in the raw data,"
425 " but will continue processing."
430 HLTError("Failed to decode the tracker DDL raw data.");
435 fDigitPerDDL = handler.GetDataCount();
437 // fMaxFiredPerDetElem[fNofFiredDetElem-1] = handler.GetDataCount();
439 // HLTDebug("fNofFiredDetElem : %d, NofDigits %d and max reco point limit is : %d, nofDetElems : %d",
440 // fNofFiredDetElem,fDigitPerDDL,fMaxRecPointsCount,fNofFiredDetElem);
442 // for(int iDet=0; iDet<TMath::Max(fNofFiredDetElem,130); iDet++)
443 // HLTDebug("NofCount (fMaxFiredPerDetElem) in iDet %d is : %d", iDet, fMaxFiredPerDetElem[iDet]);
445 // if(fNofFiredDetElem>129){
446 // HLTError("Number of fired detection elements is %d, which is more than 129.", fNofFiredDetElem);
450 if(fDigitPerDDL == 1){
451 HLTDebug("An Empty DDL file was found.");
458 bool AliHLTMUONHitReconstructor::FindRecHits()
460 // fuction that calls hit reconstruction detector element-wise.
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 );
474 bool resultOk = false;
478 for(int iDet=0; iDet< GetkNofDetElemInDDL(fDDL) ; iDet++)
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]);
491 catch(const std::bad_alloc&)
493 HLTError("Dynamic memory allocation failed for fCentralChargeNB and fCentralChargeB");
495 //break; Do not break. Might have smaller memory requirements in the next iteration.
498 // Continue processing, but check if everything is OK as we do, otherwise
499 // do not execute the next steps.
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);
506 HLTDebug("For iDet : %d, Found fCentralCountB : %d, fCentralCountNB : %d",iDet,fCentralCountB,fCentralCountNB);
507 if(fCentralCountB==0 or fCentralCountNB==0)
509 HLTDebug("There is no fired pad in bending/nonbending plane...skipping this detection element");
510 if (fCentralChargeB != NULL)
512 delete [] fCentralChargeB;
513 HLTDebug("Released fCentralChargeB array.");
514 fCentralChargeB = NULL;
516 if (fCentralChargeNB != NULL)
518 delete [] fCentralChargeNB;
519 HLTDebug("Released fCentralChargeNB array.");
520 fCentralChargeNB = NULL;
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);
550 catch(const std::bad_alloc&){
551 HLTError("Dynamic memory allocation failed for internal arrays.");
553 //break; Must not break, this will prevent calling delete and memory cleanup, i.e. memory leak.
557 if (resultOk) RecXRecY();
562 resultOk = MergeQuadRecHits();
564 resultOk = MergeSlatRecHits();
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;
573 // Make sure to release any memory that was allocated.
574 if (fCentralChargeB != NULL)
576 delete [] fCentralChargeB;
577 HLTDebug("Released fCentralChargeB array.");
578 fCentralChargeB = NULL;
580 if (fCentralChargeNB != NULL)
582 delete [] fCentralChargeNB;
583 HLTDebug("Released fCentralChargeNB array.");
584 fCentralChargeNB = NULL;
589 HLTDebug("Released fRecX array.");
595 HLTDebug("Released fRecY array.");
598 if (fAvgChargeX != NULL)
600 delete [] fAvgChargeX;
601 HLTDebug("Released fAvgChargeX array.");
604 if (fAvgChargeY != NULL)
606 delete [] fAvgChargeY;
607 HLTDebug("Released fAvgChargeY array.");
610 if (fTotChargeX != NULL)
612 delete [] fTotChargeX;
613 HLTDebug("Released fTotChargeX array.");
616 if (fTotChargeY != NULL)
618 delete [] fTotChargeY;
619 HLTDebug("Released fTotChargeY array.");
622 if (fNofBChannel != NULL)
624 delete [] fNofBChannel;
625 HLTDebug("Released fNofBChannel array.");
628 if (fNofNBChannel != NULL)
630 delete [] fNofNBChannel;
631 HLTDebug("Released fNofNBChannel array.");
632 fNofNBChannel = NULL;
634 if (fNofYNeighbour != NULL)
636 delete [] fNofYNeighbour;
637 HLTDebug("Released fNofYNeighbour array.");
638 fNofYNeighbour = NULL;
642 Clear(); // clear internal arrays.
648 void AliHLTMUONHitReconstructor::FindCentralHits(int iDet)
650 // to find central hit associated with each cluster
652 assert( fCentralChargeB != NULL );
653 assert( fCentralChargeNB != NULL );
656 int idManuChannelCentral;
660 for(int iEntry=0;iEntry<fNofDataInDetElem[iDet];iEntry++){
662 iPad = fDataCountListPerDetElem[iDet][iEntry];
664 //if(fPadData[iPad].fDetElemId==102)
665 HLTDebug("iPad : %d, detElem : %d, fCentralCountB : %d, fCentralCountNB : %d",iPad,fPadData[iPad].fDetElemId,fCentralCountB,fCentralCountNB);
667 fGetIdTotalData[fPadData[iPad].fIX]
669 [fPadData[iPad].fPlane] = iPad ;
671 if(fPadData[iPad].fCharge <= fDCCut ) continue;
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){
677 for(b = 0;b<fCentralCountB;b++){
678 idManuChannelCentral = fCentralChargeB[b];
679 if(fPadData[iPad].fIX == fPadData[idManuChannelCentral].fIX
682 == fPadData[idManuChannelCentral].fIY + 1
685 == fPadData[idManuChannelCentral].fIY + 2
688 == fPadData[idManuChannelCentral].fIY - 2
691 == fPadData[idManuChannelCentral].fIY - 1)){
694 if(fPadData[iPad].fCharge > fPadData[idManuChannelCentral].fCharge){
695 fCentralChargeB[b] = iPad;
696 }// if condn on pad charge
697 }// if condon on pad position
700 fCentralChargeB[fCentralCountB] = iPad;
705 fCentralChargeB[fCentralCountB] = iPad;
707 }// check the size of centralHitB
708 for(b = 0;b<fCentralCountB;b++){
709 idManuChannelCentral = fCentralChargeB[b];
711 //}// if cond on iY > 2 (to avoid edge value pb)
714 if(fCentralCountNB>0){
716 for(nb = 0;nb<fCentralCountNB;nb++){
717 idManuChannelCentral = fCentralChargeNB[nb];
718 if(fPadData[iPad].fIY == fPadData[idManuChannelCentral].fIY
721 == fPadData[idManuChannelCentral].fIX + 1
724 == fPadData[idManuChannelCentral].fIX + 2
727 == fPadData[idManuChannelCentral].fIX - 2
730 == fPadData[idManuChannelCentral].fIX - 1)){
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
739 fCentralChargeNB[fCentralCountNB] = iPad;
742 }// centralHitNB size test
744 fCentralChargeNB[fCentralCountNB] = iPad;
746 }// centralHitNB size test
748 }// fill for bending and nonbending hit
753 void AliHLTMUONHitReconstructor::RecXRecY()
755 // find reconstructed X and Y for each plane separately
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 );
774 for(b=0;b<fCentralCountB;b++){
775 idCentral = fCentralChargeB[b];
777 if(fPadData[idCentral].fIY==0)
780 idLower = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY-1][0];
782 if(fPadData[idCentral].fIY==236)
785 idUpper = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY+1][0];
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 ;
792 fRecY[b] = (fPadData[idCentral].fRealY*fPadData[idCentral].fCharge
794 fPadData[idUpper].fRealY*fPadData[idUpper].fCharge
796 fPadData[idLower].fRealY*fPadData[idLower].fCharge
797 )/fTotChargeY[b];//(fPadData[idCentral].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge) ;
800 fNofYNeighbour[b] = 0;
801 if(fPadData[idLower].fCharge>0.0){
805 if(fPadData[idCentral].fCharge>0.0)
807 if(fPadData[idUpper].fCharge>0.0){
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);
815 //collect left coloumn
816 if((fPadData[idCentral].fIX-1)>=0){
818 idLeft = fGetIdTotalData[fPadData[idCentral].fIX-1][fPadData[idCentral].fIY][0];
820 if(fPadData[idLeft].fIY==0)
823 idLower = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY-1][0];
825 if(fPadData[idLeft].fIY==236)
828 idUpper = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY+1][0];
830 fTotChargeY[b] += (fPadData[idLeft].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge);
832 if(fPadData[idLower].fCharge>0.0)
834 if(fPadData[idLeft].fCharge>0.0)
836 if(fPadData[idUpper].fCharge>0.0)
840 ////////////////////////////////////////////////////
842 //collect right coloumn
843 if((fPadData[idCentral].fIX+1)<=335){
845 idRight = fGetIdTotalData[fPadData[idCentral].fIX+1][fPadData[idCentral].fIY][0];
847 if(fPadData[idRight].fIY==0)
850 idLower = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY-1][0];
852 if(fPadData[idRight].fIY==236)
855 idUpper = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY+1][0];
857 fTotChargeY[b] += (fPadData[idRight].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge);
859 if(fPadData[idLower].fCharge>0.0)
861 if(fPadData[idRight].fCharge>0.0)
863 if(fPadData[idUpper].fCharge>0.0)
867 //////////////////////////////////////////////////////////////////////////////////
868 HLTDebug("RecY[%d] : %f, nofChannel : %d, detelem : %d",b,fRecY[b],fNofBChannel[b],fPadData[idCentral].fDetElemId);
872 for(nb=0;nb<fCentralCountNB;nb++){
873 idCentral = fCentralChargeNB[nb];
875 if(fPadData[idCentral].fIX==0)
878 idLeft = fGetIdTotalData[fPadData[idCentral].fIX-1][fPadData[idCentral].fIY][1];
880 if(fPadData[idCentral].fIX==335)
883 idRight = fGetIdTotalData[fPadData[idCentral].fIX+1][fPadData[idCentral].fIY][1];
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 ;
889 fRecX[nb] = (fPadData[idCentral].fRealX*fPadData[idCentral].fCharge
891 fPadData[idRight].fRealX*fPadData[idRight].fCharge
893 fPadData[idLeft].fRealX*fPadData[idLeft].fCharge
894 )/fTotChargeX[nb];//(fPadData[idCentral].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
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]++ ;
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);
910 if((fPadData[idCentral].fIY-1)>=0){
912 idLower = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY-1][1];
914 if(fPadData[idLower].fIX==0)
917 idLeft = fGetIdTotalData[fPadData[idLower].fIX-1][fPadData[idLower].fIY][1];
919 if(fPadData[idLower].fIX==335)
922 idRight = fGetIdTotalData[fPadData[idLower].fIX+1][fPadData[idLower].fIY][1];
924 fTotChargeX[nb] += (fPadData[idLower].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
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]++ ;
934 ////////////////////////////////////////////////////////////
937 if((fPadData[idCentral].fIY+1)<=236){
939 idUpper = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY+1][1];
941 if(fPadData[idUpper].fIX==0)
944 idLeft = fGetIdTotalData[fPadData[idUpper].fIX-1][fPadData[idUpper].fIY][1];
946 if(fPadData[idUpper].fIX==335)
949 idRight = fGetIdTotalData[fPadData[idUpper].fIX+1][fPadData[idUpper].fIY][1];
951 fTotChargeX[nb] += (fPadData[idUpper].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
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]++ ;
961 ////////////////////////////////////////////////////////////
963 HLTDebug("RecX[%d] : %f, nofChannel : %d",nb,fRecX[nb],fNofNBChannel[nb]);
971 bool AliHLTMUONHitReconstructor::MergeQuadRecHits()
973 // Merge reconstructed hits first over same plane then bending plane with non-bending plane
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 );
985 int idCentralB=0,idCentralNB=0 ;
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
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++){
1001 if(fCentralChargeB[i]==fCentralChargeB[j]){
1002 fRecY[j] = outsideSpacePoint;
1007 fPadData[fCentralChargeB[i]].fIY == fPadData[fCentralChargeB[j]].fIY
1011 fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX + 1
1013 fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX - 1
1016 fRecY[j] != outsideSpacePoint
1018 fRecY[i] != outsideSpacePoint
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;
1027 fRecY[j] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
1028 )/(fAvgChargeY[i] + fAvgChargeY[j]);
1029 fRecY[i] = outsideSpacePoint;
1031 }// search for higher charge
1034 }//if fRecY[i] != outsideSpacePoint
1036 isMergedY[fCentralCountB-1] = false;
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++){
1044 if(fCentralChargeNB[i]==fCentralChargeNB[j]){
1045 fRecX[j] = outsideSpacePoint;
1050 fPadData[fCentralChargeNB[i]].fIX == fPadData[fCentralChargeNB[j]].fIX
1054 fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY + 1
1056 fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY - 1
1059 fRecX[j] != outsideSpacePoint
1061 fRecX[i] != outsideSpacePoint
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;
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
1076 }//if fRecX[i] != outsideSpacePoint
1078 isMergedX[fCentralCountNB-1] = false;
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;
1086 halfPadLengthX = fPadData[idCentralB].fHalfPadSize ;
1088 for(int nb=0;nb<fCentralCountNB;nb++){
1089 if(fRecX[nb]!=outsideSpacePoint){
1090 idCentralNB = fCentralChargeNB[nb];
1092 padCenterYNB = fPadData[idCentralNB].fRealY;
1094 halfPadLengthY = fPadData[idCentralNB].fHalfPadSize ;
1096 if(fabsf(fRecX[nb]) > fabsf(padCenterXB))
1097 diffX = fabsf(fRecX[nb]) - fabsf(padCenterXB);
1099 diffX = fabsf(padCenterXB) - fabsf(fRecX[nb]);
1101 if(fabsf(padCenterYNB)>fabsf(fRecY[b]))
1102 diffY = fabsf(padCenterYNB) - fabsf(fRecY[b]);
1104 diffY = fabsf(fRecY[b]) - fabsf(padCenterYNB);
1106 if(diffX < halfPadLengthX && diffY < halfPadLengthY ){//&& fPadData[idCentralB].fIY != 0){
1108 isMergedY[b] = true;
1109 isMergedX[nb] = true;
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)) ;
1117 fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
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)) ;
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
1132 delete [] isMergedY;
1133 delete [] isMergedX;
1137 AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
1138 (fPadData[idCentralB].fDetElemId / 100) - 1,
1139 fPadData[idCentralB].fDetElemId
1141 fRecPoints[(*fRecPointsCount)].fFlags = idflags;
1142 fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
1143 fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
1144 fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
1146 if (fGenerateClusterInfo)
1148 if (fClusterCount >= fMaxClusters)
1150 HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
1151 delete [] isMergedY;
1152 delete [] isMergedX;
1156 fClusters[fClusterCount].fId = (fNewClusterId << 5) | fDDL;
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;
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];
1172 if (fGenerateChannelInfo)
1174 // 3 by 3 pad structure around the central pad for the 2 planes.
1175 int pad[2][3][3] = {{
1181 {0, idCentralNB, 0},
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)
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];
1200 if (fPadData[idCentralB].fIX < 335)
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];
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)
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];
1223 if (fPadData[idCentralNB].fIY < 236)
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];
1233 AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
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++)
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;
1245 UShort_t manuId; UChar_t channelId; UShort_t adc;
1246 AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
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;
1258 HLTDebug("Part 1 : Reconstructed hit (X,Y,Z) : (%f,%f,%f)",
1259 fRecPoints[(*fRecPointsCount)].fX,
1260 fRecPoints[(*fRecPointsCount)].fY,
1261 fRecPoints[(*fRecPointsCount)].fZ
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;
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];
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 ;
1277 if(TMath::Abs(400.0*fPadData[idCentralB].fHalfPadSize*fPadData[idCentralB].fPadSizeXY - minPadArea)> 1.0e-5) continue;
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)) ;
1285 fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
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)) ;
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
1300 delete [] isMergedY;
1301 delete [] isMergedX;
1305 AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
1306 (fPadData[idCentralB].fDetElemId / 100) - 1,
1307 fPadData[idCentralB].fDetElemId
1309 fRecPoints[(*fRecPointsCount)].fFlags = idflags;
1310 fRecPoints[(*fRecPointsCount)].fX = padCenterXB;
1311 fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
1312 fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
1314 if (fGenerateClusterInfo)
1316 if (fClusterCount >= fMaxClusters)
1318 HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
1319 delete [] isMergedY;
1320 delete [] isMergedX;
1324 fClusters[fClusterCount].fId = (fNewClusterId << 5) | fDDL;
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;
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];
1340 if (fGenerateChannelInfo)
1342 // 3 by 3 pad structure around the central pad for the 2 planes.
1343 int pad[2][3][3] = {{
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)
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];
1368 if (fPadData[idCentralB].fIX < 335)
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];
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];
1384 AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
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++)
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;
1396 UShort_t manuId; UChar_t channelId; UShort_t adc;
1397 AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
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;
1409 HLTDebug("Part 2 : Reconstructed hit (X,Y,Z) : (%f,%f,%f)",
1410 fRecPoints[(*fRecPointsCount)].fX,
1411 fRecPoints[(*fRecPointsCount)].fY,
1412 fRecPoints[(*fRecPointsCount)].fZ
1414 (*fRecPointsCount)++;
1416 }// condn on fRecY[b] != 0.0
1417 }// loop over B side;
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++){
1423 idCentralNB = fCentralChargeNB[nb];
1424 if(fRecX[nb]!=outsideSpacePoint and !isMergedX[nb] and fNofNBChannel[nb]>2){
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 ;
1428 if(TMath::Abs(400.0*fPadData[idCentralNB].fHalfPadSize*fPadData[idCentralNB].fPadSizeXY - minPadArea)> 1.0e-5) continue;
1430 padCenterYNB = fPadData[idCentralNB].fRealY;
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)) ;
1438 // padCenterYNB += 0.025*sin(12.0*(padCenterYNB - fPadData[idCentralNB].fRealY)) ;
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)) ;
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
1453 delete [] isMergedY;
1454 delete [] isMergedX;
1458 AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
1459 (fPadData[idCentralNB].fDetElemId / 100) - 1,
1460 fPadData[idCentralNB].fDetElemId
1462 fRecPoints[(*fRecPointsCount)].fFlags = idflags;
1463 fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
1464 fRecPoints[(*fRecPointsCount)].fY = padCenterYNB;
1465 fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralNB].fRealZ;
1467 if (fGenerateClusterInfo)
1469 if (fClusterCount >= fMaxClusters)
1471 HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
1472 delete [] isMergedY;
1473 delete [] isMergedX;
1477 fClusters[fClusterCount].fId = (fNewClusterId << 5) | fDDL;
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;
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];
1493 if (fGenerateChannelInfo)
1495 // 3 by 3 pad structure around the central pad for the 2 planes.
1496 int pad[2][3][3] = {{
1502 {0, idCentralNB, 0},
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.
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)
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];
1522 if (fPadData[idCentralNB].fIY < 236)
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];
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];
1538 AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
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++)
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;
1550 UShort_t manuId; UChar_t channelId; UShort_t adc;
1551 AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
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;
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
1569 (*fRecPointsCount)++;
1570 }//if lies wihtin 5.0 mm
1571 }// condn over fRecX ! = 0.0
1573 delete [] isMergedY;
1574 delete [] isMergedX;
1579 bool AliHLTMUONHitReconstructor::MergeSlatRecHits()
1581 // Merge reconstructed hits first over same plane then bending plane with non-bending plane
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 );
1593 int idCentralB,idCentralNB ;
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
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++){
1608 if(fCentralChargeB[i]==fCentralChargeB[j]){
1609 fRecY[j] = outsideSpacePoint;
1614 fPadData[fCentralChargeB[i]].fIY == fPadData[fCentralChargeB[j]].fIY
1618 fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX + 1
1620 fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX - 1
1623 fRecY[j] != outsideSpacePoint
1625 fRecY[i] != outsideSpacePoint
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;
1634 fRecY[j] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
1635 )/(fAvgChargeY[i] + fAvgChargeY[j]);
1636 fRecY[i] = outsideSpacePoint;
1638 }// search for higher charge
1641 }//if fRecY[i] != outsideSpacePoint
1643 isMergedY[fCentralCountB-1] = false;
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++){
1651 if(fCentralChargeNB[i]==fCentralChargeNB[j]){
1652 fRecX[j] = outsideSpacePoint;
1657 fPadData[fCentralChargeNB[i]].fIX == fPadData[fCentralChargeNB[j]].fIX
1661 fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY + 1
1663 fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY - 1
1666 fRecX[j] != outsideSpacePoint
1668 fRecX[i] != outsideSpacePoint
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;
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
1683 }//if fRecX[i] != outsideSpacePoint
1685 isMergedX[fCentralCountNB-1] = false;
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;
1693 halfPadLengthX = fPadData[idCentralB].fHalfPadSize ;
1695 for(int nb=0;nb<fCentralCountNB;nb++){
1696 if(fRecX[nb]!=outsideSpacePoint){
1697 idCentralNB = fCentralChargeNB[nb];
1699 padCenterYNB = fPadData[idCentralNB].fRealY;
1701 halfPadLengthY = fPadData[idCentralNB].fHalfPadSize ;
1703 if(fabsf(fRecX[nb]) > fabsf(padCenterXB))
1704 diffX = fabsf(fRecX[nb]) - fabsf(padCenterXB);
1706 diffX = fabsf(padCenterXB) - fabsf(fRecX[nb]);
1708 if(fabsf(padCenterYNB)>fabsf(fRecY[b]))
1709 diffY = fabsf(padCenterYNB) - fabsf(fRecY[b]);
1711 diffY = fabsf(fRecY[b]) - fabsf(padCenterYNB);
1713 if(diffX < halfPadLengthX && diffY < halfPadLengthY ){//&& fPadData[idCentralB].fIY != 0){
1715 isMergedY[b] = true;
1716 isMergedX[nb] = true;
1718 if(fNofYNeighbour[b]==2){
1719 fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1722 fRecX[nb] += 0.075*sin(9.5*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
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
1731 delete [] isMergedY;
1732 delete [] isMergedX;
1736 AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
1737 (fPadData[idCentralB].fDetElemId / 100) - 1,
1738 fPadData[idCentralB].fDetElemId
1740 fRecPoints[(*fRecPointsCount)].fFlags = idflags;
1741 fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
1742 fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
1743 fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
1745 if (fGenerateClusterInfo)
1747 if (fClusterCount >= fMaxClusters)
1749 HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
1750 delete [] isMergedY;
1751 delete [] isMergedX;
1755 fClusters[fClusterCount].fId = (fNewClusterId << 5) | fDDL;
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;
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];
1771 if (fGenerateChannelInfo)
1773 // 3 by 3 pad structure around the central pad for the 2 planes.
1774 int pad[2][3][3] = {{
1780 {0, idCentralNB, 0},
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)
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];
1799 if (fPadData[idCentralB].fIX < 335)
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];
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)
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];
1822 if (fPadData[idCentralNB].fIY < 236)
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];
1832 AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
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++)
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;
1844 UShort_t manuId; UChar_t channelId; UShort_t adc;
1845 AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
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;
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
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;
1870 delete [] isMergedY;
1871 delete [] isMergedX;
1876 void AliHLTMUONHitReconstructor::Clear()
1878 // function to clear internal arrays.
1880 HLTDebug("Clearing fPadData and fNofDataInDetElem buffers.");
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;
1898 for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
1899 fNofDataInDetElem[idet] = 0;
1901 // for(int i=0;i<130;i++)
1902 // fMaxFiredPerDetElem[i] = 0;
1906 AliHLTInt32_t AliHLTMUONHitReconstructor::GetkNofDetElemInDDL(Int_t iDDL)
1908 /// Returns the number of detection elements for a DDL.
1910 if(iDDL>=0 && iDDL<=19)
1911 return fgkNofDetElemInDDL[iDDL];
1917 AliHLTInt32_t AliHLTMUONHitReconstructor::GetkMinDetElemIdInDDL(Int_t iDDL)
1919 /// Returns the first detection element ID for a DDL.
1921 if(iDDL>=0 && iDDL<=19)
1922 return fgkMinDetElemIdInDDL[iDDL];
1928 AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::AliHLTMUONRawDecoder() :
1929 fkBufferStart(NULL),
1933 fkLookUpTableData(NULL),
1935 fkMaxEntryPerBusPatch(),
1941 fIdManuChannel(0x0),
1943 fDataCountListPerDetElem(NULL),
1944 fNofDataInDetElem(NULL),
1946 fSkipParityErrors(false),
1947 fDontPrintParityErrors(false),
1948 fPrintParityErrorAsWarning(false),
1949 fParityErrorFound(false),
1950 fNonParityErrorFound(false),
1957 AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::~AliHLTMUONRawDecoder()
1963 void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnNewBuffer(const void* buffer, UInt_t /*bufferSize*/)
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.
1969 assert( buffer != NULL );
1970 fkBufferStart = buffer;
1971 // dataCount starts from 1 because the 0-th element of fPadData is used as null value.
1973 for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
1974 fNofDataInDetElem[idet] = 0;
1976 fParityErrorFound = false;
1977 fNonParityErrorFound = false;
1981 void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnError(ErrorCode code, const void* location)
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.
1989 if (code == kParityError)
1991 fParityErrorFound = true;
1995 fNonParityErrorFound = true;
1997 if (fDontPrintParityErrors and code == kParityError) return;
1999 long bytepos = long(location) - long(fkBufferStart);
2000 if (fWarnOnly or (fPrintParityErrorAsWarning and code == kParityError))
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
2009 HLTError("There is a problem with decoding the raw data. %s (Error code: %d, at byte %d)",
2010 ErrorCodeToMessage(code), code, bytepos
2015 void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnNewBusPatch(const AliMUONBusPatchHeaderStruct* header, const void* /*data*/)
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;
2027 void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnData(UInt_t dataWord, bool parityError)
2029 //function to arrange the decoded Raw Data
2031 if (fSkipParityErrors and parityError) return;
2033 if(fIsMuchNoisy) return;
2035 fIdManuChannel = 0x0;
2036 fIdManuChannel = (fIdManuChannel|fBusPatchId)<<17;
2037 fIdManuChannel |= (dataWord >> 12) & 0x1FFFF;
2039 IdManuChannelToEntry& idToEntry = * const_cast<IdManuChannelToEntry*>(fkIdToEntry);
2040 fLutEntry = idToEntry[fIdManuChannel];
2043 HLTDebug("Failed to find a valid LUT entry.");
2046 fPadCharge = int(((unsigned short)(dataWord & 0xFFF)) - fkLookUpTableData[fLutEntry].fPed);
2049 if(fPadCharge > 2.0*fkLookUpTableData[fLutEntry].fSigma){ // (charge > 4) is due cut out the noise level
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;
2063 if ( fPadCharge < fkLookUpTableData[fLutEntry].fThres ) {
2064 fCharge = (fkLookUpTableData[fLutEntry].fA0)*fPadCharge;
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);
2071 fPadData[fDataCount].fCharge = fCharge;
2073 if(fkLookUpTableData[fLutEntry].fDetElemId/100 == 6){
2074 fDataCountListPerDetElem[
2075 ((fkLookUpTableData[fLutEntry].fDetElemId-(GetkMinDetElemIdInDDL(fDDL)+100))%GetkNofDetElemInDDL(fDDL)
2076 + GetkNofDetElemInDDL(fDDL)/2)
2078 [fNofDataInDetElem[((fkLookUpTableData[fLutEntry].fDetElemId-(GetkMinDetElemIdInDDL(fDDL)+100))%GetkNofDetElemInDDL(fDDL)
2079 + GetkNofDetElemInDDL(fDDL)/2)
2082 fDataCountListPerDetElem[(fkLookUpTableData[fLutEntry].fDetElemId-GetkMinDetElemIdInDDL(fDDL))%GetkNofDetElemInDDL(fDDL)]
2083 [fNofDataInDetElem[(fkLookUpTableData[fLutEntry].fDetElemId-GetkMinDetElemIdInDDL(fDDL))%GetkNofDetElemInDDL(fDDL)]++] = fDataCount;
2086 // if(fkLookUpTableData[fLutEntry].fDetElemId != fPrevDetElemId){
2087 // if((*fNofFiredDetElem)>0){
2088 // fMaxFiredPerDetElem[(*fNofFiredDetElem)-1] = fDataCount;
2091 // HLTDebug("detElem : %d, prevDetElem : %d, datacount : %d, maxFiredPerDetElem[%d] : %d",
2092 // fkLookUpTableData[fLutEntry].fDetElemId,fPrevDetElemId,fDataCount,
2093 // ((*fNofFiredDetElem)-1),fMaxFiredPerDetElem[(*fNofFiredDetElem)-1]
2096 // (*fNofFiredDetElem)++;
2097 // fPrevDetElemId = fkLookUpTableData[fLutEntry].fDetElemId ;
2100 //if(fPadData[fDataCount].fDetElemId==102)
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);
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);
2119 }// if charge is more than DC Cut limit condition